(fillbuf): Make sure returned char doesn't get sign extended.
[kopensolaris-gnu/glibc.git] / stdio / internals.c
1 /* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB.  If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.  */
18
19 #include <ansidecl.h>
20 #include <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25
26 /* Make sure that FP has its functions set.  */
27 void
28 DEFUN(__stdio_check_funcs, (fp), register FILE *fp)
29 {
30   if (!fp->__seen)
31     {
32       /* Initialize the stream's info, including buffering info.
33          This may give a buffer, change I/O functions, etc.
34          If no buffer is set (and the stream is not made explicitly
35          unbuffered), we allocate a buffer below, using the bufsize
36          set by this function.  */
37       extern void EXFUN(__stdio_init_stream, (FILE *));
38       fp->__room_funcs = __default_room_functions;
39       fp->__io_funcs = __default_io_functions;
40       __stdio_init_stream (fp);
41       fp->__seen = 1;
42     }
43 }
44
45
46 /* Minimum size of a buffer we will allocate by default.
47    If this much memory is not available,
48    the stream in question will be made unbuffered instead.  */
49 #define MIN_BUFSIZE     128
50
51 /* Figure out what kind of buffering (none, line, or full)
52    and what buffer size to give FP.  */
53 static void
54 DEFUN(init_stream, (fp), register FILE *fp)
55 {
56   __stdio_check_funcs (fp);
57
58   if (fp->__buffer == NULL && !fp->__userbuf)
59     {
60       int save;
61
62       if (fp->__bufsize == 0)
63         fp->__bufsize = BUFSIZ;
64
65       /* Try to get however many bytes of buffering __stdio_pickbuf
66          specified, but if that much memory isn't available,
67          try half as much each time until it succeeds or the buffer
68          size becomes too small to be useful.  */
69       save = errno;
70       while (fp->__bufsize >= MIN_BUFSIZE)
71         {
72           fp->__buffer = (char *) malloc(fp->__bufsize);
73           if (fp->__buffer == NULL)
74             fp->__bufsize /= 2;
75           else
76             break;
77         }
78       errno = save;
79
80       if (fp->__buffer == NULL)
81         {
82           /* We can't get space for the buffer, so make it unbuffered.  */
83           fp->__userbuf = 1;
84           fp->__bufsize = 0;
85         }
86     }
87
88   if (fp->__bufp == NULL)
89     {
90       /* Set the buffer pointer to the beginning of the buffer.  */
91       fp->__bufp = fp->__buffer;
92       fp->__put_limit = fp->__get_limit = fp->__buffer;
93     }
94 }
95
96
97 /* Determine the current file position of STREAM if it is unknown.  */
98 int
99 DEFUN(__stdio_check_offset, (stream), FILE *stream)
100 {
101   init_stream (stream);
102
103   if (stream->__offset == (fpos_t) -1)
104     {
105       /* This stream's offset is unknown or unknowable.  */
106       if (stream->__io_funcs.__seek == NULL)
107         {
108           /* Unknowable.  */
109           errno = ESPIPE;
110           return EOF;
111         }
112       else
113         {
114           /* Unknown.  Find it out.  */
115           fpos_t pos = (fpos_t) 0;
116           if ((*stream->__io_funcs.__seek)(stream->__cookie,
117                                            &pos, SEEK_CUR) < 0)
118             {
119               if (errno == ESPIPE)
120                 /* Object is incapable of seeking.  */
121                 stream->__io_funcs.__seek = NULL;
122               return EOF;
123             }
124           stream->__offset = pos;
125         }
126     }
127
128   if (stream->__target == (fpos_t) -1)
129     /* This stream was opened on an existing object with
130        an unknown file position.  The position is now known.
131        Make this the target position.  */
132     stream->__target = stream->__offset;
133
134   return 0;
135 }
136
137
138 /* Move FP's file position to its target file position,
139    seeking as necessary and updating its `offset' field.
140    Sets ferror(FP) (and possibly errno) for errors.  */
141 static void
142 DEFUN(seek_to_target, (fp), FILE *fp)
143 {
144   int save = errno;
145   if (__stdio_check_offset (fp) == EOF)
146     {
147       if (errno == ESPIPE)
148         errno = save;
149       else
150         fp->__error = 1;
151     }
152   else if (fp->__target != fp->__offset)
153     {
154       /* We are not at the target file position.
155          Seek to that position.  */
156       if (fp->__io_funcs.__seek == NULL)
157         {
158           /* We can't seek!  */
159           errno = ESPIPE;
160           fp->__error = 1;
161         }
162       else
163         {
164           fpos_t pos = fp->__target;
165           if ((*fp->__io_funcs.__seek)(fp->__cookie, &pos, SEEK_SET) < 0)
166             /* Seek failed!  */
167             fp->__error = 1;
168           else
169             {
170               fp->__offset = pos;
171               if (pos != fp->__target)
172                 /* Seek didn't go to the right place!  */
173                 fp->__error = 1;
174             }
175         }
176     }
177 }
178
179 /* Flush the buffer for FP.
180    If C is not EOF, it is also to be written.
181    If the stream is line buffered and C is a newline, it is written
182    to the output, otherwise it is put in the buffer after it has been
183    flushed to avoid a system call for a single character.
184    This is the default `output room' function.  */
185 static void
186 DEFUN(flushbuf, (fp, c),
187       register FILE *fp AND int c)
188 {
189   int flush_only = c == EOF;
190   size_t buffer_written;
191   size_t to_write;
192
193   /* Set if target and get_limit have already been twiddled appropriately.  */
194   int twiddled = 0;
195
196   if (fp->__put_limit == fp->__buffer)
197     {
198       /* The stream needs to be primed for writing.  */
199
200       size_t buffer_offset = 0;
201
202       /* If the user has read some of the buffer, the target position
203          is incremented for each character he has read.  */
204       fp->__target += fp->__bufp - fp->__buffer;
205
206       if (fp->__mode.__read && fp->__room_funcs.__input != NULL &&
207           !fp->__mode.__append)
208         {
209           int save = errno;
210           CONST int aligned = (fp->__buffer == NULL ||
211                                __stdio_check_offset(fp) == EOF ||
212                                fp->__target % fp->__bufsize == 0);
213           errno = save;
214
215           if (!aligned)
216             {
217               /* Move to a block (buffer size) boundary and read in a block.
218                  Then the output will be written as a whole block, too.  */
219               CONST size_t o = fp->__target % fp->__bufsize;
220               fp->__target -= o;
221               if ((*fp->__room_funcs.__input)(fp) == EOF && ferror(fp))
222                 return;
223               else
224                 __clearerr(fp);
225
226               if (fp->__get_limit - fp->__buffer < o)
227                 /* Oops.  We didn't read enough (probably because we got EOF).
228                    Forget we even mentioned it.  */
229                 fp->__target += o;
230               else
231                 /* Start bufp as far into the buffer as we were into
232                    this block before we read it.  */
233                 buffer_offset = o;
234             }
235
236           /* The target position is now set to where the beginning of the
237              buffer maps to; and the get_limit was set by the input-room
238              function.  */
239           twiddled = 1;
240         }
241
242       if (fp->__buffer != NULL)
243         {
244           /* Set up to write output into the buffer.  */
245           fp->__put_limit = fp->__buffer + fp->__bufsize;
246           fp->__bufp = fp->__buffer + buffer_offset;
247
248           if (!flush_only)
249             {
250               /* Put C in the buffer to be written out.
251                  We only need to actually write it out now if
252                  it is a newline on a line-buffered stream.  */
253               *fp->__bufp++ = (unsigned char) c;
254               if (!fp->__linebuf || (unsigned char) c != '\n')
255                 {
256                   /* There is no need to flush C from the buffer right now.
257                      Record that nothing was written from the buffer,
258                      and go do clean-up at end.  */
259                   buffer_written = 0;
260                   goto end;
261                 }
262               else
263                 /* We put C in the buffer, so don't write it again later.  */
264                 flush_only = 1;
265             }
266         }
267     }
268
269   /* If there is read data in the buffer past what was written,
270      write all of that as well.  Otherwise, just write what has been
271      written into the buffer.  */
272   buffer_written = fp->__bufp - fp->__buffer;
273   to_write = (buffer_written == 0 ? 0 :
274               fp->__get_limit > fp->__bufp ?
275               fp->__get_limit - fp->__buffer :
276               buffer_written);
277
278   if (fp->__io_funcs.__write == NULL || (to_write == 0 && flush_only))
279     {
280       /* There is no writing function or we're coming from an fflush
281          call with nothing in the buffer, so just say the buffer's
282          been flushed, increment the file offset, and return.  */
283       fp->__bufp = fp->__buffer;
284       fp->__offset += to_write;
285       goto end;
286     }
287
288   if (to_write > 0)
289     {
290       int wrote;
291
292       /* Go to the target file position.  Don't bother if appending;
293          the write will just ignore the file position anyway.  */
294       if (!fp->__mode.__append)
295         seek_to_target (fp);
296
297       if (!ferror(fp))
298         {
299           /* Write out the buffered data.  */
300           wrote = (*fp->__io_funcs.__write)(fp->__cookie, fp->__buffer,
301                                             to_write);
302           if (wrote > 0)
303             {
304               if (fp->__mode.__append)
305                 /* The write has written the data to the end of the file
306                    and updated the file position to after the data.  Don't
307                    bother to find the current position; we can get it
308                    later if we need it.  */
309                 fp->__offset = fp->__target = -1;
310               else
311                 /* Record that we've moved forward in the file.  */
312                 fp->__offset += wrote;
313             }
314           if (wrote < (int) to_write)
315             /* The writing function should always write
316                the whole buffer unless there is an error.  */
317             fp->__error = 1;
318         }
319     }
320
321   /* Reset the buffer pointer to the beginning of the buffer.  */
322   fp->__bufp = fp->__buffer;
323
324   /* If we're not just flushing, write the last character, C.  */
325   if (!flush_only && !ferror(fp))
326     {
327       if (fp->__buffer == NULL || (fp->__linebuf && (unsigned char) c == '\n'))
328         {
329           /* Either we're unbuffered, or we're line-buffered and
330              C is a newline, so really write it out immediately.  */
331           char cc = (unsigned char) c;
332           if ((*fp->__io_funcs.__write)(fp->__cookie, &cc, 1) < 1)
333             fp->__error = 1;
334           else
335             {
336               /* Record that we've moved forward in the file.  */
337               ++fp->__offset;
338               ++fp->__target;
339             }
340         }
341       else
342         /* Just put C in the buffer.  */
343         *fp->__bufp++ = (unsigned char) c;
344     }
345
346  end:
347
348   if (!twiddled)
349     {
350       /* The new target position moves up as
351          much as the user wrote into the buffer.  */
352       fp->__target += buffer_written;
353
354       /* Set the reading limit to the beginning of the buffer,
355          so the next `getc' will call __fillbf.  */
356       fp->__get_limit = fp->__buffer;
357     }
358
359   if (feof(fp) || ferror(fp))
360     fp->__bufp = fp->__put_limit;
361 }
362
363
364 /* Fill the buffer for FP and return the first character read (or EOF).
365    This is the default `input_room' function.  */
366 static int
367 DEFUN(fillbuf, (fp), register FILE *fp)
368 {
369   /* How far into the buffer we read we want to start bufp.  */
370   size_t buffer_offset = 0;
371   register char *buffer;
372   register size_t to_read, nread = 0;
373   /* This must be unsigned to avoid sign extension in return.  */
374   unsigned char c;
375
376   if (fp->__io_funcs.__read == NULL)
377     {
378       /* There is no read function, so always return EOF.  */
379       fp->__eof = 1;
380       goto end;
381     }
382
383   if (fp->__buffer == NULL)
384     {
385       /* We're unbuffered, so we want to read only one character.  */
386       buffer = (char *) &c;
387       to_read = 1;
388     }
389   else
390     {
391       /* We're buffered, so try to fill the buffer.  */
392       buffer = fp->__buffer;
393       to_read = fp->__bufsize;
394     }
395
396   /* We're reading, so we're not at the end-of-file.  */
397   fp->__eof = 0;
398
399   /* Go to the target file position.  */
400   {
401     int save = errno;
402     if (__stdio_check_offset (fp) == 0 && fp->__target != fp->__offset)
403       {
404         /* Move to a block (buffer size) boundary.  */
405         if (fp->__bufsize != 0)
406           {
407             buffer_offset = fp->__target % fp->__bufsize;
408             fp->__target -= buffer_offset;
409           }
410         seek_to_target (fp);
411       }
412     errno = save;
413   }
414
415   while (!ferror(fp) && !feof(fp) && nread <= buffer_offset)
416     {
417       /* Try to fill the buffer.  */
418       int count = (*fp->__io_funcs.__read)(fp->__cookie, buffer, to_read);
419       if (count == 0)
420         fp->__eof = 1;
421       else if (count < 0)
422         fp->__error = 1;
423       else
424         {
425           buffer += count;
426           nread += count;
427           to_read -= count;
428           /* Record that we've moved forward in the file.  */
429           fp->__offset += count;
430         }
431     }
432
433   if (fp->__buffer == NULL)
434     /* There is no buffer, so return the character we read
435        without all the buffer pointer diddling.  */
436     return (feof(fp) || ferror(fp)) ? EOF : c;
437
438   /* Reset the buffer pointer to the beginning of the buffer
439      (plus whatever offset we may have set above).  */
440   fp->__bufp = fp->__buffer + buffer_offset;
441
442  end:;
443
444   if (feof(fp) || ferror(fp))
445     {
446       /* Set both end pointers to the beginning of the buffer so
447          the next i/o call will force a call to __fillbf/__flshfp.  */
448       fp->__put_limit = fp->__get_limit = fp->__buffer;
449       return EOF;
450     }
451
452   /* Set the end pointer to one past the last character we read.  */
453   fp->__get_limit = fp->__buffer + nread;
454
455   /* Make it so the next `putc' will call __flshfp.  */
456   fp->__put_limit = fp->__buffer;
457
458   /* Return the first character in the buffer.  */
459   return *((unsigned char *) (fp->__bufp++));
460 }
461
462
463 /* Default I/O and room functions.  */
464
465 extern __io_read_fn __stdio_read;
466 extern __io_write_fn __stdio_write;
467 extern __io_seek_fn __stdio_seek;
468 extern __io_close_fn __stdio_close;
469 extern __io_fileno_fn __stdio_fileno;
470 CONST __io_functions __default_io_functions =
471   {
472     __stdio_read, __stdio_write, __stdio_seek, __stdio_close, __stdio_fileno
473   };
474
475 CONST __room_functions __default_room_functions =
476   {
477     fillbuf, flushbuf
478   };
479
480
481 /* Flush the buffer for FP and also write C if FLUSH_ONLY is nonzero.
482    This is the function used by putc and fflush.  */
483 int
484 DEFUN(__flshfp, (fp, c),
485       register FILE *fp AND int c)
486 {
487   int flush_only = c == EOF;
488
489   if (!__validfp(fp) || !fp->__mode.__write)
490     {
491       errno = EINVAL;
492       return EOF;
493     }
494
495   if (ferror(fp))
496     return EOF;
497
498   if (fp->__pushed_back)
499     {
500       /* Discard the char pushed back by ungetc.  */
501       fp->__bufp = fp->__pushback_bufp;
502       fp->__pushed_back = 0;
503     }
504
505   /* Make sure the stream is initialized (has functions and buffering).  */
506   init_stream(fp);
507
508   /* Do this early, so a `putc' on such a stream will never return success.  */
509   if (fp->__room_funcs.__output == NULL)
510     {
511       /* A NULL `output room' function means
512          to always return an output error.  */
513       fp->__error = 1;
514       return EOF;
515     }
516
517   if (!flush_only &&
518       /* Will C fit into the buffer?
519          See below about linebuf_active.  */
520       fp->__bufp < (fp->__linebuf_active ? fp->__buffer + fp->__bufsize :
521                     fp->__put_limit))
522     {
523       /* The character will fit in the buffer, so put it there.  */
524       *fp->__bufp++ = (unsigned char) c;
525       if (fp->__linebuf && (unsigned char) c == '\n')
526         flush_only = 1;
527       else
528         return (unsigned char) c;
529     }
530
531   if (fp->__linebuf_active)
532     /* This is an active line-buffered stream, so its put-limit is set
533        to the beginning of the buffer in order to force a __flshfp call
534        on each putc (see below).  We undo this hack here (by setting
535        the limit to the end of the buffer) to simplify the interface
536        with the output-room function.  */
537     fp->__put_limit = fp->__buffer + fp->__bufsize;
538
539   /* Make room in the buffer.  */
540   (*fp->__room_funcs.__output) (fp, flush_only ? EOF : (unsigned char) c);
541
542   if (fp->__linebuf)
543     {
544       /* This is a line-buffered stream, and it is now ready to do
545          some output.  We call this an "active line-buffered stream".
546          We set the put_limit to the beginning of the buffer,
547          so the next `putc' call will force a call to this function.
548          Setting the linebuf_active flag tells the code above
549          (on the next call) to undo this hackery.  */
550       fp->__put_limit = fp->__buffer;
551       fp->__linebuf_active = 1;
552     }
553
554   if (ferror (fp))
555     return EOF;
556   if (flush_only)
557     return 0;
558   return (unsigned char) c;
559 }
560
561
562 /* Fill the buffer for FP and return the first character read.
563    This is the function used by getc.  */
564 int
565 DEFUN(__fillbf, (fp), register FILE *fp)
566 {
567   register int c;
568   fpos_t new_target;
569
570   if (!__validfp(fp) || !fp->__mode.__read)
571     {
572       errno = EINVAL;
573       return EOF;
574     }
575
576   if (fp->__pushed_back)
577     {
578       /* Return the char pushed back by ungetc.  */
579       fp->__bufp = fp->__pushback_bufp;
580       fp->__pushed_back = 0;
581       return fp->__pushback;
582     }
583
584   /* Make sure the stream is initialized (has functions and buffering). */
585   init_stream(fp);
586
587   /* If we're trying to read the first character of a new
588      line of input from an unbuffered or line buffered stream,
589      we must flush all line-buffered output streams. */
590   if (fp->__buffer == NULL || fp->__linebuf)
591     {
592       register FILE *f;
593       for (f = __stdio_head; f != NULL; f = f->__next)
594         if (__validfp (f) && f->__linebuf && f->__mode.__write)
595           (void) __flshfp (f, EOF);
596     }
597
598   /* Note we must do this after flushing all line-buffered
599      streams, or else __flshfp would undo it!  */
600   if (fp->__linebuf_active)
601     {
602       /* This is an active line-buffered stream, meaning it is in the midst
603          of writing, but has a bogus put_limit.  Restore it to normality.  */
604       fp->__put_limit = fp->__buffer + fp->__bufsize;
605       fp->__linebuf_active = 0;
606     }
607
608   /* We want the beginning of the buffer to now
609      map to just past the last data we read.  */
610   new_target = fp->__target + (fp->__get_limit - fp->__buffer);
611
612   if (fp->__put_limit > fp->__buffer)
613     {
614       /* There is written data in the buffer.
615          Flush it out.  */
616       if (fp->__room_funcs.__output == NULL)
617         fp->__error = 1;
618       else
619         (*fp->__room_funcs.__output) (fp, EOF);
620     }
621
622   fp->__target = new_target;
623
624   if (ferror(fp))
625     c = EOF;
626   else if (fp->__room_funcs.__input != NULL)
627     {
628       c = (*fp->__room_funcs.__input)(fp);
629       if (fp->__buffer == NULL)
630         /* This is an unbuffered stream, so the target sync above
631            won't do anything the next time around.  Instead, note that
632            we have read one character.  The (nonexistent) buffer now
633            maps to the position just past that character.  */
634         ++fp->__target;
635     }
636   else
637     {
638       /* A NULL `input_room' function means always return EOF.  */
639       fp->__eof = 1;
640       c = EOF;
641     }
642
643   return c;
644 }
645
646
647 /* Nuke a stream, but don't kill its link in the chain.  */
648 void
649 DEFUN(__invalidate, (stream), register FILE *stream)
650 {
651   /* Save its link.  */
652   register FILE *next = stream->__next;
653
654   /* Pulverize the fucker.  */
655   memset((PTR) stream, 0, sizeof(FILE));
656
657   /* Restore the deceased's link.  */
658   stream->__next = next;
659 }