OSDN Git Service

Initial revision
[uclinux-h8/uClibc.git] / libc / stdio / stdio.c
1 /* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
2  * This file is part of the Linux-8086 C library and is distributed
3  * under the GNU Library General Public License.
4  */
5
6 /* This is an implementation of the C standard IO package.
7  */
8
9 #include <stdio.h>
10
11 #include <fcntl.h>
12 #include <sys/types.h>
13 #include <malloc.h>
14 #include <errno.h>
15
16 #undef STUB_FWRITE
17
18 extern FILE *__IO_list;         /* For fflush at exit */
19
20 #define FIXED_BUFFERS 2
21 struct fixed_buffer {
22         unsigned char data[BUFSIZ];
23         int used;
24 };
25
26 extern struct fixed_buffer _fixed_buffers[2];
27
28 #define Inline_init __io_init_vars()
29
30 #ifdef L__stdio_init
31
32 #define buferr (stderr->unbuf)  /* Stderr is unbuffered */
33
34 FILE *__IO_list = 0;            /* For fflush at exit */
35
36 #if 0
37 static char bufin[BUFSIZ];
38 static char bufout[BUFSIZ];
39 #ifndef buferr
40 static char buferr[BUFSIZ];
41 #endif
42
43 #else
44 static char *bufin;
45 static char *bufout;
46 #ifndef buferr
47 static char *buferr;
48 #endif
49 #endif
50
51 FILE  stdin[1] =
52 {
53 #if 0
54    {bufin, bufin, bufin, bufin, bufin + sizeof(bufin),
55 #else
56    {0, 0, 0, 0, 0,
57 #endif
58     0, _IOFBF | __MODE_READ | __MODE_IOTRAN}
59 };
60
61 FILE  stdout[1] =
62 {
63 #if 0
64    {bufout, bufout, bufout, bufout, bufout + sizeof(bufout),
65 #else
66    {0, 0, 0, 0, 0,
67 #endif
68     1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN}
69 };
70
71 FILE  stderr[1] =
72 {
73 #if 0
74    {buferr, buferr, buferr, buferr, buferr + sizeof(buferr),
75 #else
76    {0, 0, 0, 0, 0,
77 #endif
78     2, _IONBF | __MODE_WRITE | __MODE_IOTRAN}
79 };
80
81 /* Call the stdio initiliser; it's main job it to call atexit */
82
83 #define STATIC
84
85 STATIC int 
86 __stdio_close_all()
87 {
88    FILE *fp;
89    fflush(stdout);
90    fflush(stderr);
91    for (fp = __IO_list; fp; fp = fp->next)
92    {
93       fflush(fp);
94       close(fp->fd);
95       /* Note we're not de-allocating the memory */
96       /* There doesn't seem to be much point :-) */
97       fp->fd = -1;
98    }
99 }
100
101 static int first_time = 0;
102
103 struct fixed_buffer _fixed_buffers[2];
104
105
106 STATIC void 
107 __io_init_vars()
108 {
109    if( first_time ) return;
110    first_time = 1;
111
112    stdin->bufpos = bufin = _fixed_buffers[0].data; /*(char *)malloc(BUFSIZ)*/;
113    stdin->bufread =  bufin;
114    stdin->bufwrite = bufin;
115    stdin->bufstart = bufin;
116    stdin->bufend =  bufin + sizeof(bufin);
117    stdin->fd = 0;
118    stdin->mode = _IOFBF | __MODE_READ | __MODE_IOTRAN | __MODE_FREEBUF;
119    
120    _fixed_buffers[0].used = 1;
121
122    stdout->bufpos = bufout = _fixed_buffers[1].data; /*(char *)malloc(BUFSIZ);*/
123    stdout->bufread =  bufout;
124    stdout->bufwrite = bufout;
125    stdout->bufstart = bufout;
126    stdout->bufend =  bufout + sizeof(bufout);
127    stdout->fd = 1;
128    stdout->mode = _IOFBF | __MODE_WRITE | __MODE_IOTRAN | __MODE_FREEBUF;
129    
130    _fixed_buffers[1].used = 1;
131
132 #if 0
133    stderr->bufpos = buferr = (char *)malloc(BUFSIZ);
134 #else
135    stderr->bufpos = buferr;
136 #endif
137    stderr->bufread =  buferr;
138    stderr->bufwrite = buferr;
139    stderr->bufstart = buferr;
140    stderr->bufend =  buferr + sizeof(buferr);
141    stderr->fd = 2;
142    stderr->mode = _IONBF | __MODE_WRITE | __MODE_IOTRAN;
143
144    if (isatty(1))
145       stdout->mode |= _IOLBF;
146    atexit(__stdio_close_all);
147 }
148 #endif
149
150 #ifdef L_fputc
151 int
152 fputc(ch, fp)
153 int   ch;
154 FILE *fp;
155 {
156    register int v;
157    Inline_init;
158
159    v = fp->mode;
160    /* If last op was a read ... */
161    if ((v & __MODE_READING) && fflush(fp))
162       return EOF;
163
164    /* Can't write or there's been an EOF or error then return EOF */
165    if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE)
166       return EOF;
167
168    /* In MSDOS translation mode */
169 #if __MODE_IOTRAN
170    if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF)
171       return EOF;
172 #endif
173
174    /* Buffer is full */
175    if (fp->bufpos >= fp->bufend && fflush(fp))
176       return EOF;
177
178    /* Right! Do it! */
179    *(fp->bufpos++) = ch;
180    fp->mode |= __MODE_WRITING;
181
182    /* Unbuffered or Line buffered and end of line */
183    if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF))
184        && fflush(fp))
185       return EOF;
186
187    /* Can the macro handle this by itself ? */
188    if (v & (__MODE_IOTRAN | _IOLBF | _IONBF))
189       fp->bufwrite = fp->bufstart;      /* Nope */
190    else
191       fp->bufwrite = fp->bufend;        /* Yup */
192
193    /* Correct return val */
194    return (unsigned char) ch;
195 }
196 #endif
197
198 #ifdef L_fgetc
199 int
200 fgetc(fp)
201 FILE *fp;
202 {
203    int   ch;
204    Inline_init;
205
206    if (fp->mode & __MODE_WRITING)
207       fflush(fp);
208
209  try_again:
210    /* Can't read or there's been an EOF or error then return EOF */
211    if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ)
212       return EOF;
213
214    /* Nothing in the buffer - fill it up */
215    if (fp->bufpos >= fp->bufread)
216    {
217       fp->bufpos = fp->bufread = fp->bufstart;
218       ch = fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp);
219       if (ch == 0)
220          return EOF;
221       fp->bufread += ch;
222       fp->mode |= __MODE_READING;
223       fp->mode &= ~__MODE_UNGOT;
224    }
225    ch = *(fp->bufpos++);
226
227 #if __MODE_IOTRAN
228    /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */
229    if (ch == '\r' && (fp->mode & __MODE_IOTRAN))
230       goto try_again;
231 #endif
232
233    return ch;
234 }
235 #endif
236
237 #ifdef L_fflush
238 int
239 fflush(fp)
240 FILE *fp;
241 {
242    int   len, cc, rv=0;
243    char * bstart;
244    if (fp == NULL)              /* On NULL flush the lot. */
245    {
246       if (fflush(stdin))
247          return EOF;
248       if (fflush(stdout))
249          return EOF;
250       if (fflush(stderr))
251          return EOF;
252
253       for (fp = __IO_list; fp; fp = fp->next)
254          if (fflush(fp))
255             return EOF;
256
257       return 0;
258    }
259
260    /* If there's output data pending */
261    if (fp->mode & __MODE_WRITING)
262    {
263       len = fp->bufpos - fp->bufstart;
264
265       if (len)
266       {
267          bstart = fp->bufstart;
268          /*
269           * The loop is so we don't get upset by signals or partial writes.
270           */
271          do
272          {
273             cc = write(fp->fd, bstart, len);
274             if( cc > 0 )
275             {
276                bstart+=cc; len-=cc;
277             }
278          }
279          while ( cc>0 || (cc == -1 && errno == EINTR));
280          /*
281           * If we get here with len!=0 there was an error, exactly what to
282           * do about it is another matter ...
283           *
284           * I'll just clear the buffer.
285           */
286          if (len)
287          {
288             fp->mode |= __MODE_ERR;
289             rv = EOF;
290          }
291       }
292    }
293    /* If there's data in the buffer sychronise the file positions */
294    else if (fp->mode & __MODE_READING)
295    {
296       /* Humm, I think this means sync the file like fpurge() ... */
297       /* Anyway the user isn't supposed to call this function when reading */
298
299       len = fp->bufread - fp->bufpos;   /* Bytes buffered but unread */
300       /* If it's a file, make it good */
301       if (len > 0 && lseek(fp->fd, (long)-len, 1) < 0)
302       {
303          /* Hummm - Not certain here, I don't think this is reported */
304          /*
305           * fp->mode |= __MODE_ERR; return EOF;
306           */
307       }
308    }
309
310    /* All done, no problem */
311    fp->mode &= (~(__MODE_READING|__MODE_WRITING|__MODE_EOF|__MODE_UNGOT));
312    fp->bufread = fp->bufwrite = fp->bufpos = fp->bufstart;
313    return rv;
314 }
315 #endif
316
317 #ifdef L_fgets
318 /* Nothing special here ... */
319 char *
320 fgets(s, count, f)
321 char *s;
322 size_t count;
323 FILE *f;
324 {
325    char *ret;
326    register size_t i;
327    register int ch;
328
329    ret = s;
330    for (i = count; i > 0; i--)
331    {
332       ch = getc(f);
333       if (ch == EOF)
334       {
335          if (s == ret)
336             return 0;
337          break;
338       }
339       *s++ = (char) ch;
340       if (ch == '\n')
341          break;
342    }
343    *s = 0;
344
345    if (ferror(f))
346       return 0;
347    return ret;
348 }
349 #endif
350
351 #ifdef L_gets
352 char *
353 gets(str)                       /* BAD function; DON'T use it! */
354 char *str;
355 {
356    /* Auwlright it will work but of course _your_ program will crash */
357    /* if it's given a too long line */
358    register char *p = str;
359    register int c;
360
361    while (((c = getc(stdin)) != EOF) && (c != '\n'))
362       *p++ = c;
363    *p = '\0';
364    return (((c == EOF) && (p == str)) ? NULL : str);    /* NULL == EOF */
365 }
366 #endif
367
368 #ifdef L_fputs
369 int
370 fputs(str, fp)
371 char *str;
372 FILE *fp;
373 {
374    register int n = 0;
375    while (*str)
376    {
377       if (putc(*str++, fp) == EOF)
378          return (EOF);
379       ++n;
380    }
381    return (n);
382 }
383 #endif
384
385 #ifdef L_puts
386 int
387 puts(str)
388 char *str;
389 {
390    register int n;
391
392    if (((n = fputs(str, stdout)) == EOF)
393        || (putc('\n', stdout) == EOF))
394       return (EOF);
395    return (++n);
396 }
397 #endif
398
399 #ifdef L_fread
400 /*
401  * fread will often be used to read in large chunks of data calling read()
402  * directly can be a big win in this case. Beware also fgetc calls this
403  * function to fill the buffer.
404  * 
405  * This ignores __MODE__IOTRAN; probably exactly what you want. (It _is_ what
406  * fgetc wants)
407  */
408 int
409 fread(buf, size, nelm, fp)
410 char *buf;
411 int   size;
412 int   nelm;
413 FILE *fp;
414 {
415    int   len, v;
416    unsigned bytes, got = 0;
417    Inline_init;
418
419    v = fp->mode;
420
421    /* Want to do this to bring the file pointer up to date */
422    if (v & __MODE_WRITING)
423       fflush(fp);
424
425    /* Can't read or there's been an EOF or error then return zero */
426    if ((v & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ)
427       return 0;
428
429    /* This could be long, doesn't seem much point tho */
430    bytes = size * nelm;
431
432    len = fp->bufread - fp->bufpos;
433    if (len >= bytes)            /* Enough buffered */
434    {
435       memcpy(buf, fp->bufpos, (unsigned) bytes);
436       fp->bufpos += bytes;
437       return bytes;
438    }
439    else if (len > 0)            /* Some buffered */
440    {
441       memcpy(buf, fp->bufpos, len);
442       got = len;
443    }
444
445    /* Need more; do it with a direct read */
446    len = read(fp->fd, buf + got, (unsigned) (bytes - got));
447
448    /* Possibly for now _or_ later */
449    if (len < 0)
450    {
451       fp->mode |= __MODE_ERR;
452       len = 0;
453    }
454    else if (len == 0)
455       fp->mode |= __MODE_EOF;
456
457    return (got + len) / size;
458 }
459 #endif
460
461 #ifdef L_fwrite
462 /*
463  * Like fread, fwrite will often be used to write out large chunks of
464  * data; calling write() directly can be a big win in this case.
465  * 
466  * But first we check to see if there's space in the buffer.
467  * 
468  * Again this ignores __MODE__IOTRAN.
469  */
470 int
471 fwrite(buf, size, nelm, fp)
472 char *buf;
473 int   size;
474 int   nelm;
475 FILE *fp;
476 {
477    register int v;
478    int   len;
479    unsigned bytes, put;
480
481 #ifdef STUB_FWRITE
482         bytes = size * nelm;
483         while(bytes>0) {
484                 len=write(fp->fd, buf, bytes);
485                 if (len<=0) {
486                         break;
487                 }
488                 bytes -= len;
489                 buf += len;
490         }
491         return nelm;
492 #else
493                 
494    v = fp->mode;
495    /* If last op was a read ... */
496    if ((v & __MODE_READING) && fflush(fp))
497       return 0;
498
499    /* Can't write or there's been an EOF or error then return 0 */
500    if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE)
501       return 0;
502
503    /* This could be long, doesn't seem much point tho */
504    bytes = size * nelm;
505
506    len = fp->bufend - fp->bufpos;
507
508    /* Flush the buffer if not enough room */
509    if (bytes > len)
510       if (fflush(fp))
511          return 0;
512
513    len = fp->bufend - fp->bufpos;
514    if (bytes <= len)            /* It'll fit in the buffer ? */
515    {
516       fp->mode |= __MODE_WRITING;
517       memcpy(fp->bufpos, buf, bytes);
518       fp->bufpos += bytes;
519
520       /* If we're not fully buffered */
521       if (v & (_IOLBF | _IONBF))
522          fflush(fp);
523
524       return nelm;
525    }
526    else
527       /* Too big for the buffer */
528    {
529       put = bytes;
530       do
531       {
532          len = write(fp->fd, buf, bytes);
533          if( len > 0 )
534          {
535             buf+=len; bytes-=len;
536          }
537       }
538       while (len > 0 || (len == -1 && errno == EINTR));
539
540       if (len < 0)
541          fp->mode |= __MODE_ERR;
542
543       put -= bytes;
544    }
545
546    return put / size;
547 #endif
548 }
549 #endif
550
551 #ifdef L_rewind
552 void
553 rewind(fp)
554 FILE * fp;
555 {
556    fseek(fp, (long)0, 0);
557    clearerr(fp);
558 }
559 #endif
560
561 #ifdef L_fseek
562 int
563 fseek(fp, offset, ref)
564 FILE *fp;
565 long  offset;
566 int   ref;
567 {
568 #if 0 
569    /* FIXME: this is broken!  BROKEN!!!! */
570    /* if __MODE_READING and no ungetc ever done can just move pointer */
571    /* This needs testing! */
572
573    if ( (fp->mode &(__MODE_READING | __MODE_UNGOT)) == __MODE_READING && 
574         ( ref == SEEK_SET || ref == SEEK_CUR ))
575    {
576       long fpos = lseek(fp->fd, 0L, SEEK_CUR);
577       if( fpos == -1 ) return EOF;
578
579       if( ref == SEEK_CUR )
580       {
581          ref = SEEK_SET;
582          offset = fpos + offset + fp->bufpos - fp->bufread;
583       }
584       if( ref == SEEK_SET )
585       {
586          if ( offset < fpos && offset >= fpos + fp->bufstart - fp->bufread )
587          {
588             fp->bufpos = offset - fpos + fp->bufread;
589             return 0;
590          }
591       }
592    }
593 #endif
594
595    /* Use fflush to sync the pointers */
596
597    if (fflush(fp) == EOF)
598       return EOF;
599    if (lseek(fp->fd, offset, ref) < 0)
600       return EOF;
601    return 0;
602 }
603 #endif
604
605 #ifdef L_ftell
606 long ftell(fp)
607 FILE * fp;
608 {
609    long rv;
610    if (fflush(fp) == EOF)
611       return EOF;
612    return lseek(fp->fd, 0L, SEEK_CUR);
613 }
614 #endif
615
616 #ifdef L_fopen
617 /*
618  * This Fopen is all three of fopen, fdopen and freopen. The macros in
619  * stdio.h show the other names.
620  */
621 FILE *
622 __fopen(fname, fd, fp, mode)
623 char *fname;
624 int   fd;
625 FILE *fp;
626 char *mode;
627 {
628    int   open_mode = 0;
629 #if __MODE_IOTRAN
630    int   do_iosense = 1;
631 #endif
632    int   fopen_mode = 0;
633    FILE *nfp = 0;
634
635    /* If we've got an fp close the old one (freopen) */
636    if (fp)
637    {
638       /* Careful, don't de-allocate it */
639       fopen_mode |= (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF));
640       fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF);
641       fclose(fp);
642    }
643
644    /* decode the new open mode */
645    while (*mode)
646       switch (*mode++)
647       {
648       case 'r':
649          fopen_mode |= __MODE_READ;
650          break;
651       case 'w':
652          fopen_mode |= __MODE_WRITE;
653          open_mode = (O_CREAT | O_TRUNC);
654          break;
655       case 'a':
656          fopen_mode |= __MODE_WRITE;
657          open_mode = (O_CREAT | O_APPEND);
658          break;
659       case '+':
660          fopen_mode |= __MODE_RDWR;
661          break;
662 #if __MODE_IOTRAN
663       case 'b':         /* Binary */
664          fopen_mode &= ~__MODE_IOTRAN;
665          do_iosense=0;
666          break;
667       case 't':         /* Text */
668          fopen_mode |= __MODE_IOTRAN;
669          do_iosense=0;
670          break;
671 #endif
672       }
673
674    /* Add in the read/write options to mode for open() */
675    switch (fopen_mode & (__MODE_READ | __MODE_WRITE))
676    {
677    case 0:
678       return 0;
679    case __MODE_READ:
680       open_mode |= O_RDONLY;
681       break;
682    case __MODE_WRITE:
683       open_mode |= O_WRONLY;
684       break;
685    default:
686       open_mode |= O_RDWR;
687       break;
688    }
689
690    /* Allocate the (FILE) before we do anything irreversable */
691    if (fp == 0)
692    {
693       nfp = malloc(sizeof(FILE));
694       if (nfp == 0)
695          return 0;
696    }
697
698    /* Open the file itself */
699    if (fname)
700       fd = open(fname, open_mode, 0666);
701    if (fd < 0)                  /* Grrrr */
702    {
703       if (nfp)
704          free(nfp);
705       return 0;
706    }
707
708    /* If this isn't freopen create a (FILE) and buffer for it */
709    if (fp == 0)
710    {
711       int i;
712       fp = nfp;
713       fp->next = __IO_list;
714       __IO_list = fp;
715
716       fp->mode = __MODE_FREEFIL;
717       if( isatty(fd) )
718       {
719          fp->mode |= _IOLBF;
720 #if __MODE_IOTRAN
721          if( do_iosense ) fopen_mode |= __MODE_IOTRAN;
722 #endif
723       }
724       else
725          fp->mode |= _IOFBF;
726
727       for(i=0;i<FIXED_BUFFERS;i++)
728          if (!_fixed_buffers[i].used) {
729             fp->bufstart = _fixed_buffers[i].data;
730             _fixed_buffers[i].used = 1;
731             break;
732          }
733
734       if (i == FIXED_BUFFERS)
735          fp->bufstart = malloc(BUFSIZ);
736          
737       if (fp->bufstart == 0)    /* Oops, no mem */
738       {                         /* Humm, full buffering with a two(!) byte
739                                  * buffer. */
740          fp->bufstart = fp->unbuf;
741          fp->bufend = fp->unbuf + sizeof(fp->unbuf);
742       }
743       else
744       {
745          fp->bufend = fp->bufstart + BUFSIZ;
746          fp->mode |= __MODE_FREEBUF;
747       }
748    }
749    /* Ok, file's ready clear the buffer and save important bits */
750    fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
751    fp->mode |= fopen_mode;
752    fp->fd = fd;
753    return fp;
754 }
755 #endif
756
757 #ifdef L_fclose
758 int
759 fclose(fp)
760 FILE *fp;
761 {
762    int   rv = 0;
763
764    if (fp == 0)
765    {
766       errno = EINVAL;
767       return EOF;
768    }
769    if (fflush(fp))
770       return EOF;
771
772    if (close(fp->fd))
773       rv = EOF;
774    fp->fd = -1;
775
776    if (fp->mode & __MODE_FREEBUF)
777    {
778       int i;
779       for(i=0;i<FIXED_BUFFERS;i++)
780          if (fp->bufstart == _fixed_buffers[i].data) {
781            _fixed_buffers[i].used = 0;
782            break;
783          }
784       if(i==FIXED_BUFFERS)
785          free(fp->bufstart);
786       fp->mode &= ~__MODE_FREEBUF;
787       fp->bufstart = fp->bufend = 0;
788    }
789
790    if (fp->mode & __MODE_FREEFIL)
791    {
792       FILE *prev = 0, *ptr;
793       fp->mode = 0;
794
795       for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next)
796          ;
797       if (ptr == fp)
798       {
799          if (prev == 0)
800             __IO_list = fp->next;
801          else
802             prev->next = fp->next;
803       }
804       free(fp);
805    }
806    else
807       fp->mode = 0;
808
809    return rv;
810 }
811 #endif
812
813 #ifdef L_setbuffer
814 void
815 setbuffer(fp, buf, size)
816 FILE * fp;
817 char * buf;
818 int size;
819 {
820    fflush(fp);
821    
822    if ((fp->bufstart == (unsigned char*)buf) && (fp->bufend == ((unsigned char*)buf + size)))
823       return;
824    
825    if( fp->mode & __MODE_FREEBUF ) {
826       int i;
827       for(i=0;i<FIXED_BUFFERS;i++)
828          if (fp->bufstart == _fixed_buffers[i].data) {
829            _fixed_buffers[i].used = 0;
830            break;
831          }
832       if(i==FIXED_BUFFERS)
833          free(fp->bufstart);
834    }
835    fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
836
837    if( buf == 0 )
838    {
839       fp->bufstart = fp->unbuf;
840       fp->bufend = fp->unbuf + sizeof(fp->unbuf);
841       fp->mode |= _IONBF;
842    }
843    else
844    {
845       fp->bufstart = buf;
846       fp->bufend = buf+size;
847       fp->mode |= _IOFBF;
848    }
849    fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
850 }
851 #endif
852
853 #ifdef L_setvbuf
854 int setvbuf(fp, buf, mode, size)
855 FILE * fp;
856 char * buf;
857 int mode;
858 size_t size;
859 {
860    fflush(fp);
861    if( fp->mode & __MODE_FREEBUF ) {
862       int i;
863       for(i=0;i<FIXED_BUFFERS;i++)
864          if (fp->bufstart == _fixed_buffers[i].data) {
865            _fixed_buffers[i].used = 0;
866            break;
867          }
868       if(i==FIXED_BUFFERS)
869          free(fp->bufstart);
870    }
871    fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
872    fp->bufstart = fp->unbuf;
873    fp->bufend = fp->unbuf + sizeof(fp->unbuf);
874    fp->mode |= _IONBF;
875
876    if( mode == _IOFBF || mode == _IOLBF )
877    {
878       if( size <= 0  ) size = BUFSIZ;
879       if( buf == 0 )
880          if (size == BUFSIZ) {
881             int i;
882             for(i=0;i<FIXED_BUFFERS;i++)
883                if (!_fixed_buffers[i].used) {
884                  _fixed_buffers[i].used = 1;
885                  buf = _fixed_buffers[i].data;
886                  break;
887                }
888             if(i==FIXED_BUFFERS)
889                buf = malloc(size);
890          } else
891             buf = malloc(size);
892       if( buf == 0 ) return EOF;
893
894       fp->bufstart = buf;
895       fp->bufend = buf+size;
896       fp->mode |= mode;
897    }
898    fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
899 }
900 #endif
901
902 #ifdef L_ungetc
903 int
904 ungetc(c, fp)
905 int c;
906 FILE *fp;
907 {
908    if (fp->mode & __MODE_WRITING)
909       fflush(fp);
910
911    /* Can't read or there's been an error then return EOF */
912    if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ)
913       return EOF;
914
915    /* Can't do fast fseeks */
916    fp->mode |= __MODE_UNGOT;
917
918    if( fp->bufpos > fp->bufstart )
919       return *--fp->bufpos = (unsigned char) c;
920    else if( fp->bufread == fp->bufstart )
921       return *fp->bufread++ = (unsigned char) c;
922    else
923       return EOF;
924 }
925 #endif