fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / stdio / fvwrite.c
blobaaf3a192e0b41fe8d0b3cd46f77fbfa465204ed6
1 /* No user fns here. Pesch 15apr92. */
3 /*
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by the University of California, Berkeley. The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include "local.h"
24 #include "fvwrite.h"
26 #define MIN(a, b) ((a) < (b) ? (a) : (b))
27 #define COPY(n) (void) memmove((void *) fp->_p, (void *) p, (size_t) (n))
29 #define GETIOV(extra_work) \
30 while (len == 0) \
31 { \
32 extra_work; \
33 p = iov->iov_base; \
34 len = iov->iov_len; \
35 iov++; \
39 * Write some memory regions. Return zero on success, EOF on error.
41 * This routine is large and unsightly, but most of the ugliness due
42 * to the three different kinds of output buffering is handled here.
45 int
46 __sfvwrite (fp, uio)
47 register FILE *fp;
48 register struct __suio *uio;
50 register size_t len;
51 register _CONST char *p;
52 register struct __siov *iov;
53 register int w, s;
54 char *nl;
55 int nlknown, nldist;
57 if ((len = uio->uio_resid) == 0)
58 return 0;
60 /* make sure we can write */
61 if (cantwrite (fp))
62 return EOF;
64 iov = uio->uio_iov;
65 len = 0;
67 #ifdef __SCLE
68 if (fp->_flags & __SCLE) /* text mode */
72 GETIOV (;);
73 while (len > 0)
75 if (putc(*p, fp) == EOF)
76 return EOF;
77 p++;
78 len--;
79 uio->uio_resid--;
82 while (uio->uio_resid > 0);
83 return 0;
85 #endif
87 if (fp->_flags & __SNBF)
90 * Unbuffered: write up to BUFSIZ bytes at a time.
94 GETIOV (;);
95 w = (*fp->_write) (fp->_cookie, p, MIN (len, BUFSIZ));
96 if (w <= 0)
97 goto err;
98 p += w;
99 len -= w;
101 while ((uio->uio_resid -= w) != 0);
103 else if ((fp->_flags & __SLBF) == 0)
106 * Fully buffered: fill partially full buffer, if any,
107 * and then flush. If there is no partial buffer, write
108 * one _bf._size byte chunk directly (without copying).
110 * String output is a special case: write as many bytes
111 * as fit, but pretend we wrote everything. This makes
112 * snprintf() return the number of bytes needed, rather
113 * than the number used, and avoids its write function
114 * (so that the write function can be invalid). If
115 * we are dealing with the asprintf routines, we will
116 * dynamically increase the buffer size as needed.
120 GETIOV (;);
121 w = fp->_w;
122 if (fp->_flags & __SSTR)
124 if (len > w && fp->_flags & __SMBF)
125 { /* must be asprintf family */
126 unsigned char *ptr;
127 int curpos = (fp->_p - fp->_bf._base);
128 ptr = (unsigned char *)_realloc_r (_REENT,
129 fp->_bf._base,
130 curpos + len);
131 if (!ptr)
132 goto err;
133 fp->_bf._base = ptr;
134 fp->_p = ptr + curpos;
135 fp->_bf._size = curpos + len;
136 w = fp->_w = len;
138 if (len < w)
139 w = len;
140 COPY (w); /* copy MIN(fp->_w,len), */
141 fp->_w -= w;
142 fp->_p += w;
143 w = len; /* but pretend copied all */
145 else if (fp->_p > fp->_bf._base && len > w)
147 /* fill and flush */
148 COPY (w);
149 /* fp->_w -= w; *//* unneeded */
150 fp->_p += w;
151 if (fflush (fp))
152 goto err;
154 else if (len >= (w = fp->_bf._size))
156 /* write directly */
157 w = (*fp->_write) (fp->_cookie, p, w);
158 if (w <= 0)
159 goto err;
161 else
163 /* fill and done */
164 w = len;
165 COPY (w);
166 fp->_w -= w;
167 fp->_p += w;
169 p += w;
170 len -= w;
172 while ((uio->uio_resid -= w) != 0);
174 else
177 * Line buffered: like fully buffered, but we
178 * must check for newlines. Compute the distance
179 * to the first newline (including the newline),
180 * or `infinity' if there is none, then pretend
181 * that the amount to write is MIN(len,nldist).
183 nlknown = 0;
186 GETIOV (nlknown = 0);
187 if (!nlknown)
189 nl = memchr ((void *) p, '\n', len);
190 nldist = nl ? nl + 1 - p : len + 1;
191 nlknown = 1;
193 s = MIN (len, nldist);
194 w = fp->_w + fp->_bf._size;
195 if (fp->_p > fp->_bf._base && s > w)
197 COPY (w);
198 /* fp->_w -= w; */
199 fp->_p += w;
200 if (fflush (fp))
201 goto err;
203 else if (s >= (w = fp->_bf._size))
205 w = (*fp->_write) (fp->_cookie, p, w);
206 if (w <= 0)
207 goto err;
209 else
211 w = s;
212 COPY (w);
213 fp->_w -= w;
214 fp->_p += w;
216 if ((nldist -= w) == 0)
218 /* copied the newline: flush and forget */
219 if (fflush (fp))
220 goto err;
221 nlknown = 0;
223 p += w;
224 len -= w;
226 while ((uio->uio_resid -= w) != 0);
228 return 0;
230 err:
231 fp->_flags |= __SERR;
232 return EOF;