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.
6 /* This is an implementation of the C standard IO package.
12 #include <sys/types.h>
18 extern FILE *__IO_list; /* For fflush at exit */
20 #define FIXED_BUFFERS 2
22 unsigned char data[BUFSIZ];
26 extern struct fixed_buffer _fixed_buffers[2];
28 #define Inline_init __io_init_vars()
32 #define buferr (stderr->unbuf) /* Stderr is unbuffered */
34 FILE *__IO_list = 0; /* For fflush at exit */
37 static char bufin[BUFSIZ];
38 static char bufout[BUFSIZ];
40 static char buferr[BUFSIZ];
54 {bufin, bufin, bufin, bufin, bufin + sizeof(bufin),
58 0, _IOFBF | __MODE_READ | __MODE_IOTRAN}
64 {bufout, bufout, bufout, bufout, bufout + sizeof(bufout),
68 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN}
74 {buferr, buferr, buferr, buferr, buferr + sizeof(buferr),
78 2, _IONBF | __MODE_WRITE | __MODE_IOTRAN}
81 /* Call the stdio initiliser; it's main job it to call atexit */
91 for (fp = __IO_list; fp; fp = fp->next)
95 /* Note we're not de-allocating the memory */
96 /* There doesn't seem to be much point :-) */
101 static int first_time = 0;
103 struct fixed_buffer _fixed_buffers[2];
109 if( first_time ) return;
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);
118 stdin->mode = _IOFBF | __MODE_READ | __MODE_IOTRAN | __MODE_FREEBUF;
120 _fixed_buffers[0].used = 1;
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);
128 stdout->mode = _IOFBF | __MODE_WRITE | __MODE_IOTRAN | __MODE_FREEBUF;
130 _fixed_buffers[1].used = 1;
133 stderr->bufpos = buferr = (char *)malloc(BUFSIZ);
135 stderr->bufpos = buferr;
137 stderr->bufread = buferr;
138 stderr->bufwrite = buferr;
139 stderr->bufstart = buferr;
140 stderr->bufend = buferr + sizeof(buferr);
142 stderr->mode = _IONBF | __MODE_WRITE | __MODE_IOTRAN;
145 stdout->mode |= _IOLBF;
146 atexit(__stdio_close_all);
160 /* If last op was a read ... */
161 if ((v & __MODE_READING) && fflush(fp))
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)
168 /* In MSDOS translation mode */
170 if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF)
175 if (fp->bufpos >= fp->bufend && fflush(fp))
179 *(fp->bufpos++) = ch;
180 fp->mode |= __MODE_WRITING;
182 /* Unbuffered or Line buffered and end of line */
183 if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF))
187 /* Can the macro handle this by itself ? */
188 if (v & (__MODE_IOTRAN | _IOLBF | _IONBF))
189 fp->bufwrite = fp->bufstart; /* Nope */
191 fp->bufwrite = fp->bufend; /* Yup */
193 /* Correct return val */
194 return (unsigned char) ch;
206 if (fp->mode & __MODE_WRITING)
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)
214 /* Nothing in the buffer - fill it up */
215 if (fp->bufpos >= fp->bufread)
217 fp->bufpos = fp->bufread = fp->bufstart;
218 ch = fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp);
222 fp->mode |= __MODE_READING;
223 fp->mode &= ~__MODE_UNGOT;
225 ch = *(fp->bufpos++);
228 /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */
229 if (ch == '\r' && (fp->mode & __MODE_IOTRAN))
244 if (fp == NULL) /* On NULL flush the lot. */
253 for (fp = __IO_list; fp; fp = fp->next)
260 /* If there's output data pending */
261 if (fp->mode & __MODE_WRITING)
263 len = fp->bufpos - fp->bufstart;
267 bstart = fp->bufstart;
269 * The loop is so we don't get upset by signals or partial writes.
273 cc = write(fp->fd, bstart, len);
279 while ( cc>0 || (cc == -1 && errno == EINTR));
281 * If we get here with len!=0 there was an error, exactly what to
282 * do about it is another matter ...
284 * I'll just clear the buffer.
288 fp->mode |= __MODE_ERR;
293 /* If there's data in the buffer sychronise the file positions */
294 else if (fp->mode & __MODE_READING)
296 /* Humm, I think this means sync the file like fpurge() ... */
297 /* Anyway the user isn't supposed to call this function when reading */
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)
303 /* Hummm - Not certain here, I don't think this is reported */
305 * fp->mode |= __MODE_ERR; return EOF;
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;
318 /* Nothing special here ... */
330 for (i = count; i > 0; i--)
353 gets(str) /* BAD function; DON'T use it! */
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;
361 while (((c = getc(stdin)) != EOF) && (c != '\n'))
364 return (((c == EOF) && (p == str)) ? NULL : str); /* NULL == EOF */
377 if (putc(*str++, fp) == EOF)
392 if (((n = fputs(str, stdout)) == EOF)
393 || (putc('\n', stdout) == EOF))
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.
405 * This ignores __MODE__IOTRAN; probably exactly what you want. (It _is_ what
409 fread(buf, size, nelm, fp)
416 unsigned bytes, got = 0;
421 /* Want to do this to bring the file pointer up to date */
422 if (v & __MODE_WRITING)
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)
429 /* This could be long, doesn't seem much point tho */
432 len = fp->bufread - fp->bufpos;
433 if (len >= bytes) /* Enough buffered */
435 memcpy(buf, fp->bufpos, (unsigned) bytes);
439 else if (len > 0) /* Some buffered */
441 memcpy(buf, fp->bufpos, len);
445 /* Need more; do it with a direct read */
446 len = read(fp->fd, buf + got, (unsigned) (bytes - got));
448 /* Possibly for now _or_ later */
451 fp->mode |= __MODE_ERR;
455 fp->mode |= __MODE_EOF;
457 return (got + len) / size;
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.
466 * But first we check to see if there's space in the buffer.
468 * Again this ignores __MODE__IOTRAN.
471 fwrite(buf, size, nelm, fp)
484 len=write(fp->fd, buf, bytes);
495 /* If last op was a read ... */
496 if ((v & __MODE_READING) && fflush(fp))
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)
503 /* This could be long, doesn't seem much point tho */
506 len = fp->bufend - fp->bufpos;
508 /* Flush the buffer if not enough room */
513 len = fp->bufend - fp->bufpos;
514 if (bytes <= len) /* It'll fit in the buffer ? */
516 fp->mode |= __MODE_WRITING;
517 memcpy(fp->bufpos, buf, bytes);
520 /* If we're not fully buffered */
521 if (v & (_IOLBF | _IONBF))
527 /* Too big for the buffer */
532 len = write(fp->fd, buf, bytes);
535 buf+=len; bytes-=len;
538 while (len > 0 || (len == -1 && errno == EINTR));
541 fp->mode |= __MODE_ERR;
556 fseek(fp, (long)0, 0);
563 fseek(fp, offset, ref)
569 /* FIXME: this is broken! BROKEN!!!! */
570 /* if __MODE_READING and no ungetc ever done can just move pointer */
571 /* This needs testing! */
573 if ( (fp->mode &(__MODE_READING | __MODE_UNGOT)) == __MODE_READING &&
574 ( ref == SEEK_SET || ref == SEEK_CUR ))
576 long fpos = lseek(fp->fd, 0L, SEEK_CUR);
577 if( fpos == -1 ) return EOF;
579 if( ref == SEEK_CUR )
582 offset = fpos + offset + fp->bufpos - fp->bufread;
584 if( ref == SEEK_SET )
586 if ( offset < fpos && offset >= fpos + fp->bufstart - fp->bufread )
588 fp->bufpos = offset - fpos + fp->bufread;
595 /* Use fflush to sync the pointers */
597 if (fflush(fp) == EOF)
599 if (lseek(fp->fd, offset, ref) < 0)
610 if (fflush(fp) == EOF)
612 return lseek(fp->fd, 0L, SEEK_CUR);
618 * This Fopen is all three of fopen, fdopen and freopen. The macros in
619 * stdio.h show the other names.
622 __fopen(fname, fd, fp, mode)
635 /* If we've got an fp close the old one (freopen) */
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);
644 /* decode the new open mode */
649 fopen_mode |= __MODE_READ;
652 fopen_mode |= __MODE_WRITE;
653 open_mode = (O_CREAT | O_TRUNC);
656 fopen_mode |= __MODE_WRITE;
657 open_mode = (O_CREAT | O_APPEND);
660 fopen_mode |= __MODE_RDWR;
663 case 'b': /* Binary */
664 fopen_mode &= ~__MODE_IOTRAN;
668 fopen_mode |= __MODE_IOTRAN;
674 /* Add in the read/write options to mode for open() */
675 switch (fopen_mode & (__MODE_READ | __MODE_WRITE))
680 open_mode |= O_RDONLY;
683 open_mode |= O_WRONLY;
690 /* Allocate the (FILE) before we do anything irreversable */
693 nfp = malloc(sizeof(FILE));
698 /* Open the file itself */
700 fd = open(fname, open_mode, 0666);
701 if (fd < 0) /* Grrrr */
708 /* If this isn't freopen create a (FILE) and buffer for it */
713 fp->next = __IO_list;
716 fp->mode = __MODE_FREEFIL;
721 if( do_iosense ) fopen_mode |= __MODE_IOTRAN;
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;
734 if (i == FIXED_BUFFERS)
735 fp->bufstart = malloc(BUFSIZ);
737 if (fp->bufstart == 0) /* Oops, no mem */
738 { /* Humm, full buffering with a two(!) byte
740 fp->bufstart = fp->unbuf;
741 fp->bufend = fp->unbuf + sizeof(fp->unbuf);
745 fp->bufend = fp->bufstart + BUFSIZ;
746 fp->mode |= __MODE_FREEBUF;
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;
776 if (fp->mode & __MODE_FREEBUF)
779 for(i=0;i<FIXED_BUFFERS;i++)
780 if (fp->bufstart == _fixed_buffers[i].data) {
781 _fixed_buffers[i].used = 0;
786 fp->mode &= ~__MODE_FREEBUF;
787 fp->bufstart = fp->bufend = 0;
790 if (fp->mode & __MODE_FREEFIL)
792 FILE *prev = 0, *ptr;
795 for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next)
800 __IO_list = fp->next;
802 prev->next = fp->next;
815 setbuffer(fp, buf, size)
822 if ((fp->bufstart == (unsigned char*)buf) && (fp->bufend == ((unsigned char*)buf + size)))
825 if( fp->mode & __MODE_FREEBUF ) {
827 for(i=0;i<FIXED_BUFFERS;i++)
828 if (fp->bufstart == _fixed_buffers[i].data) {
829 _fixed_buffers[i].used = 0;
835 fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
839 fp->bufstart = fp->unbuf;
840 fp->bufend = fp->unbuf + sizeof(fp->unbuf);
846 fp->bufend = buf+size;
849 fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
854 int setvbuf(fp, buf, mode, size)
861 if( fp->mode & __MODE_FREEBUF ) {
863 for(i=0;i<FIXED_BUFFERS;i++)
864 if (fp->bufstart == _fixed_buffers[i].data) {
865 _fixed_buffers[i].used = 0;
871 fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
872 fp->bufstart = fp->unbuf;
873 fp->bufend = fp->unbuf + sizeof(fp->unbuf);
876 if( mode == _IOFBF || mode == _IOLBF )
878 if( size <= 0 ) size = BUFSIZ;
880 if (size == BUFSIZ) {
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;
892 if( buf == 0 ) return EOF;
895 fp->bufend = buf+size;
898 fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
908 if (fp->mode & __MODE_WRITING)
911 /* Can't read or there's been an error then return EOF */
912 if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ)
915 /* Can't do fast fseeks */
916 fp->mode |= __MODE_UNGOT;
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;