* added compilers lcc and bcc (linux86)
[mascara-docs.git] / compilers / linux86-0.16.17 / libc / stdio / stdio.c
blobb8e68a581008d9f8ad20ecb09f71b34f6161362a
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 */
6 /* This is an implementation of the C standard IO package.
7 */
9 #include <stdio.h>
11 #include <fcntl.h>
12 #include <sys/types.h>
13 #include <malloc.h>
14 #include <errno.h>
16 #ifndef O_BINARY
17 #define O_BINARY 0
18 #endif
20 extern FILE *__IO_list; /* For fflush at exit */
22 #ifdef __AS386_16__
23 #define Inline_init
24 #endif
26 #ifdef __AS386_32__
27 #define Inline_init
28 #endif
30 #ifndef Inline_init
31 #define Inline_init __io_init_vars()
32 #endif
34 #ifdef L__stdio_init
36 #define buferr (stderr->unbuf) /* Stderr is unbuffered */
38 FILE *__IO_list = 0; /* For fflush at exit */
40 static char bufin[BUFSIZ];
41 static char bufout[BUFSIZ];
42 #ifndef buferr
43 static char buferr[BUFSIZ];
44 #endif
46 FILE stdin[1] =
48 {bufin, bufin, bufin, bufin, bufin + sizeof(bufin),
49 0, _IOFBF | __MODE_READ | __MODE_IOTRAN}
52 FILE stdout[1] =
54 {bufout, bufout, bufout, bufout, bufout + sizeof(bufout),
55 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN}
58 FILE stderr[1] =
60 {buferr, buferr, buferr, buferr, buferr + sizeof(buferr),
61 2, _IONBF | __MODE_WRITE | __MODE_IOTRAN}
64 /* Call the stdio initiliser; it's main job it to call atexit */
66 #ifdef __AS386_16__
67 #define STATIC static
69 #asm
70 loc 1 ! Make sure the pointer is in the correct segment
71 auto_func: ! Label for bcc -M to work.
72 .word ___io_init_vars ! Pointer to the autorun function
73 .text ! So the function after is also in the correct seg.
74 #endasm
75 #endif
77 #ifdef __AS386_32__
78 #define STATIC static
80 #asm
81 loc 1 ! Make sure the pointer is in the correct segment
82 auto_func: ! Label for bcc -M to work.
83 .long ___io_init_vars ! Pointer to the autorun function
84 .text ! So the function after is also in the correct seg.
85 #endasm
86 #endif
88 #ifndef STATIC
89 #define STATIC
90 #endif
92 STATIC int
93 __stdio_close_all()
95 FILE *fp;
96 fflush(stdout);
97 fflush(stderr);
98 for (fp = __IO_list; fp; fp = fp->next)
100 fflush(fp);
101 close(fp->fd);
102 /* Note we're not de-allocating the memory */
103 /* There doesn't seem to be much point :-) */
104 fp->fd = -1;
108 STATIC void
109 __io_init_vars()
111 #ifndef __AS386_16__
112 #ifndef __AS386_32__
113 static int first_time = 1;
114 if( !first_time ) return ;
115 first_time = 0;
116 #endif
117 #endif
118 if (isatty(1))
119 stdout->mode |= _IOLBF;
120 atexit(__stdio_close_all);
122 #endif
124 #ifdef L_fputc
126 fputc(ch, fp)
127 int ch;
128 FILE *fp;
130 register int v;
131 Inline_init;
133 /* If last op was a read ... note fflush may change fp->mode and ret OK */
134 if ((fp->mode & __MODE_READING) && fflush(fp))
135 return EOF;
137 v = fp->mode;
138 /* Can't write if there's been an EOF or error then return EOF */
139 if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE)
140 return EOF;
142 /* In MSDOS translation mode */
143 #if __MODE_IOTRAN && !O_BINARY
144 if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF)
145 return EOF;
146 #endif
148 /* Buffer is full */
149 if (fp->bufpos >= fp->bufend && fflush(fp))
150 return EOF;
152 /* Right! Do it! */
153 *(fp->bufpos++) = ch;
154 fp->mode |= __MODE_WRITING;
156 /* Unbuffered or Line buffered and end of line */
157 if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF))
158 && fflush(fp))
159 return EOF;
161 /* Can the macro handle this by itself ? */
162 if (v & (__MODE_IOTRAN | _IOLBF | _IONBF))
163 fp->bufwrite = fp->bufstart; /* Nope */
164 else
165 fp->bufwrite = fp->bufend; /* Yup */
167 /* Correct return val */
168 return (unsigned char) ch;
170 #endif
172 #ifdef L_fgetc
174 fgetc(fp)
175 FILE *fp;
177 int ch;
179 if (fp->mode & __MODE_WRITING)
180 fflush(fp);
182 try_again:
183 /* Can't read or there's been an EOF or error then return EOF */
184 if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ)
185 return EOF;
187 /* Nothing in the buffer - fill it up */
188 if (fp->bufpos >= fp->bufread)
190 /* Bind stdin to stdout if it's open and line buffered */
191 if( fp == stdin && stdout->fd >= 0 && (stdout->mode & _IOLBF ))
192 fflush(stdout);
194 fp->bufpos = fp->bufread = fp->bufstart;
195 ch = fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp);
196 if (ch == 0)
197 return EOF;
198 fp->bufread += ch;
199 fp->mode |= __MODE_READING;
200 fp->mode &= ~__MODE_UNGOT;
202 ch = *(fp->bufpos++);
204 #if __MODE_IOTRAN && !O_BINARY
205 /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */
206 if (ch == '\r' && (fp->mode & __MODE_IOTRAN))
207 goto try_again;
208 #endif
210 return ch;
212 #endif
214 #ifdef L_fflush
216 fflush(fp)
217 FILE *fp;
219 int len, cc, rv=0;
220 char * bstart;
221 if (fp == NULL) /* On NULL flush the lot. */
223 if (fflush(stdin))
224 return EOF;
225 if (fflush(stdout))
226 return EOF;
227 if (fflush(stderr))
228 return EOF;
230 for (fp = __IO_list; fp; fp = fp->next)
231 if (fflush(fp))
232 return EOF;
234 return 0;
237 /* If there's output data pending */
238 if (fp->mode & __MODE_WRITING)
240 len = fp->bufpos - fp->bufstart;
242 if (len)
244 bstart = fp->bufstart;
246 * The loop is so we don't get upset by signals or partial writes.
250 cc = write(fp->fd, bstart, len);
251 if( cc > 0 )
253 bstart+=cc; len-=cc;
256 while ( len>0 && (cc>0 || (cc == -1 && errno == EINTR)));
258 * If we get here with len!=0 there was an error, exactly what to
259 * do about it is another matter ...
261 * I'll just clear the buffer.
263 if (len)
265 fp->mode |= __MODE_ERR;
266 rv = EOF;
270 /* If there's data in the buffer sychronise the file positions */
271 else if (fp->mode & __MODE_READING)
273 /* Humm, I think this means sync the file like fpurge() ... */
274 /* Anyway the user isn't supposed to call this function when reading */
276 len = fp->bufread - fp->bufpos; /* Bytes buffered but unread */
277 /* If it's a file, make it good */
278 if (len > 0 && lseek(fp->fd, (long)-len, 1) < 0)
280 /* Hummm - Not certain here, I don't think this is reported */
282 * fp->mode |= __MODE_ERR; return EOF;
287 /* All done, no problem */
288 fp->mode &= (~(__MODE_READING|__MODE_WRITING|__MODE_EOF|__MODE_UNGOT));
289 fp->bufread = fp->bufwrite = fp->bufpos = fp->bufstart;
290 return rv;
292 #endif
294 #ifdef L_fgets
295 /* Nothing special here ... */
296 char *
297 fgets(s, count, f)
298 char *s;
299 size_t count;
300 FILE *f;
302 char *ret;
303 register size_t i;
304 register int ch;
306 ret = s;
307 for (i = count-1; i > 0; i--)
309 ch = getc(f);
310 if (ch == EOF)
312 if (s == ret)
313 return 0;
314 break;
316 *s++ = (char) ch;
317 if (ch == '\n')
318 break;
320 *s = 0;
322 if (ferror(f))
323 return 0;
324 return ret;
326 #endif
328 #ifdef L_gets
329 char *
330 gets(str) /* BAD function; DON'T use it! */
331 char *str;
333 /* Auwlright it will work but of course _your_ program will crash */
334 /* if it's given a too long line */
335 register char *p = str;
336 register int c;
338 while (((c = getc(stdin)) != EOF) && (c != '\n'))
339 *p++ = c;
340 *p = '\0';
341 return (((c == EOF) && (p == str)) ? NULL : str); /* NULL == EOF */
343 #endif
345 #ifdef L_fputs
347 fputs(str, fp)
348 char *str;
349 FILE *fp;
351 register int n = 0;
352 while (*str)
354 if (putc(*str++, fp) == EOF)
355 return (EOF);
356 ++n;
358 return (n);
360 #endif
362 #ifdef L_puts
364 puts(str)
365 char *str;
367 register int n;
369 if (((n = fputs(str, stdout)) == EOF)
370 || (putc('\n', stdout) == EOF))
371 return (EOF);
372 return (++n);
374 #endif
376 #ifdef L_fread
378 * fread will often be used to read in large chunks of data calling read()
379 * directly can be a big win in this case. Beware also fgetc calls this
380 * function to fill the buffer.
382 * This ignores __MODE__IOTRAN; probably exactly what you want. (It _is_ what
383 * fgetc wants)
386 fread(buf, size, nelm, fp)
387 char *buf;
388 int size;
389 int nelm;
390 FILE *fp;
392 int len, v;
393 unsigned bytes, got = 0;
394 Inline_init;
396 v = fp->mode;
398 /* Want to do this to bring the file pointer up to date */
399 if (v & __MODE_WRITING)
400 fflush(fp);
402 /* Can't read or there's been an EOF or error then return zero */
403 if ((v & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ)
404 return 0;
406 /* This could be long, doesn't seem much point tho */
407 bytes = size * nelm;
409 len = fp->bufread - fp->bufpos;
410 if (len >= bytes) /* Enough buffered */
412 memcpy(buf, fp->bufpos, (unsigned) bytes);
413 fp->bufpos += bytes;
414 return nelm;
416 else if (len > 0) /* Some buffered */
418 memcpy(buf, fp->bufpos, len);
419 fp->bufpos += len;
420 got = len;
423 /* Need more; do it with a direct read */
424 len = read(fp->fd, buf + got, (unsigned) (bytes - got));
426 /* Possibly for now _or_ later */
427 if (len < 0)
429 fp->mode |= __MODE_ERR;
430 len = 0;
432 else if (len == 0)
433 fp->mode |= __MODE_EOF;
435 return (got + len) / size;
437 #endif
439 #ifdef L_fwrite
441 * Like fread, fwrite will often be used to write out large chunks of
442 * data; calling write() directly can be a big win in this case.
444 * But first we check to see if there's space in the buffer.
446 * Again this ignores __MODE__IOTRAN.
449 fwrite(buf, size, nelm, fp)
450 char *buf;
451 int size;
452 int nelm;
453 FILE *fp;
455 register int v;
456 int len;
457 unsigned bytes, put;
459 /* If last op was a read ... note fflush may change fp->mode and ret OK */
460 if ((fp->mode & __MODE_READING) && fflush(fp))
461 return 0;
463 v = fp->mode;
464 /* Can't write or there's been an EOF or error then return 0 */
465 if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE)
466 return 0;
468 /* This could be long, doesn't seem much point tho */
469 bytes = size * nelm;
471 len = fp->bufend - fp->bufpos;
473 /* Flush the buffer if not enough room */
474 if (bytes > len)
475 if (fflush(fp))
476 return 0;
478 len = fp->bufend - fp->bufpos;
479 if (bytes <= len) /* It'll fit in the buffer ? */
481 register int do_flush=0;
482 fp->mode |= __MODE_WRITING;
483 memcpy(fp->bufpos, buf, bytes);
484 if (v & _IOLBF)
486 if(memchr(fp->bufpos, '\n', bytes))
487 do_flush=1;
489 fp->bufpos += bytes;
491 /* If we're unbuffered or line buffered and have seen nl */
492 if (do_flush || (v & _IONBF) != 0)
493 fflush(fp);
495 return nelm;
497 else
498 /* Too big for the buffer */
500 put = bytes;
503 len = write(fp->fd, buf, bytes);
504 if( len > 0 )
506 buf+=len; bytes-=len;
509 while (len > 0 || (len == -1 && errno == EINTR));
511 if (len < 0)
512 fp->mode |= __MODE_ERR;
514 put -= bytes;
517 return put / size;
519 #endif
521 #ifdef L_rewind
522 void
523 rewind(fp)
524 FILE * fp;
526 fseek(fp, (long)0, 0);
527 clearerr(fp);
529 #endif
531 #ifdef L_fseek
533 fseek(fp, offset, ref)
534 FILE *fp;
535 long offset;
536 int ref;
538 #if 1
539 /* if __MODE_READING and no ungetc ever done can just move pointer */
541 if ( (fp->mode &(__MODE_READING | __MODE_UNGOT)) == __MODE_READING &&
542 ( ref == SEEK_SET || ref == SEEK_CUR ))
544 long fpos = lseek(fp->fd, 0L, SEEK_CUR);
545 if( fpos == -1 ) return EOF;
547 if( ref == SEEK_CUR )
549 ref = SEEK_SET;
550 offset = fpos + offset + fp->bufpos - fp->bufread;
552 if( ref == SEEK_SET )
554 if ( offset < fpos && offset >= fpos + fp->bufstart - fp->bufread )
556 fp->bufpos = offset - fpos + fp->bufread;
557 return 0;
561 #endif
563 /* Use fflush to sync the pointers */
565 if (fflush(fp) == EOF)
566 return EOF;
567 if (lseek(fp->fd, offset, ref) < 0)
568 return EOF;
569 return 0;
571 #endif
573 #ifdef L_ftell
574 long ftell(fp)
575 FILE * fp;
577 long rv;
578 if (fflush(fp) == EOF)
579 return EOF;
580 return lseek(fp->fd, 0L, SEEK_CUR);
582 #endif
584 #ifdef L_fopen
585 FILE *
586 fopen(file, mode)
587 char * file;
588 char * mode;
590 return __fopen(file, -1, (FILE*)0, mode);
592 #endif
594 #ifdef L_freopen
595 FILE *
596 freopen(file, mode, fp)
597 char * file;
598 char * mode;
599 FILE * fp;
601 return __fopen(file, -1, fp, mode);
603 #endif
605 #ifdef L_fdopen
606 FILE *
607 fdopen(file, mode)
608 int file;
609 char * mode;
611 return __fopen((char*)0, file, (FILE*)0, mode);
613 #endif
615 #ifdef L___fopen
617 * This is the common code for all three of fopen, fdopen and freopen.
619 FILE *
620 __fopen(fname, fd, fp, mode)
621 char *fname;
622 int fd;
623 FILE *fp;
624 char *mode;
626 int open_mode = 0;
627 #if __MODE_IOTRAN && !O_BINARY
628 int do_iosense = 1;
629 #endif
630 int fopen_mode = 0;
631 FILE *nfp = 0;
633 /* If we've got an fp close the old one (freopen) */
634 if (fp)
636 /* Careful, don't de-allocate it */
637 fopen_mode |= (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF));
638 fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF);
639 fclose(fp);
642 /* decode the new open mode */
643 while (*mode)
644 switch (*mode++)
646 case 'r':
647 fopen_mode |= __MODE_READ;
648 break;
649 case 'w':
650 fopen_mode |= __MODE_WRITE;
651 open_mode = (O_CREAT | O_TRUNC);
652 break;
653 case 'a':
654 fopen_mode |= __MODE_WRITE;
655 open_mode = (O_CREAT | O_APPEND);
656 break;
657 case '+':
658 fopen_mode |= __MODE_RDWR;
659 break;
660 #if __MODE_IOTRAN || O_BINARY
661 case 'b': /* Binary */
662 fopen_mode &= ~__MODE_IOTRAN;
663 open_mode |= O_BINARY;
664 #if __MODE_IOTRAN && !O_BINARY
665 do_iosense=0;
666 #endif
667 break;
668 case 't': /* Text */
669 fopen_mode |= __MODE_IOTRAN;
670 #if __MODE_IOTRAN && !O_BINARY
671 do_iosense=0;
672 #endif
673 break;
674 #endif
677 /* Add in the read/write options to mode for open() */
678 switch (fopen_mode & (__MODE_READ | __MODE_WRITE))
680 case 0:
681 return 0;
682 case __MODE_READ:
683 open_mode |= O_RDONLY;
684 break;
685 case __MODE_WRITE:
686 open_mode |= O_WRONLY;
687 break;
688 default:
689 open_mode |= O_RDWR;
690 break;
693 /* Allocate the (FILE) before we do anything irreversable */
694 if (fp == 0)
696 nfp = malloc(sizeof(FILE));
697 if (nfp == 0)
698 return 0;
701 /* Open the file itself */
702 if (fname)
703 fd = open(fname, open_mode, 0666);
704 if (fd < 0) /* Grrrr */
706 if (nfp)
707 free(nfp);
708 if (fp)
710 fp->mode |= fopen_mode;
711 fclose(fp); /* Deallocate if required */
713 return 0;
716 /* If this isn't freopen create a (FILE) and buffer for it */
717 if (fp == 0)
719 fp = nfp;
720 fp->next = __IO_list;
721 __IO_list = fp;
723 fp->mode = __MODE_FREEFIL;
724 if( isatty(fd) )
726 fp->mode |= _IOLBF;
727 #if __MODE_IOTRAN && !O_BINARY
728 if( do_iosense ) fopen_mode |= __MODE_IOTRAN;
729 #endif
731 else
732 fp->mode |= _IOFBF;
733 fp->bufstart = malloc(BUFSIZ);
734 if (fp->bufstart == 0) /* Oops, no mem */
735 { /* Humm, full buffering with a two(!) byte
736 * buffer. */
737 fp->bufstart = fp->unbuf;
738 fp->bufend = fp->unbuf + sizeof(fp->unbuf);
740 else
742 fp->bufend = fp->bufstart + BUFSIZ;
743 fp->mode |= __MODE_FREEBUF;
747 /* Ok, file's ready clear the buffer and save important bits */
748 fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
749 fp->mode |= fopen_mode;
750 fp->fd = fd;
752 return fp;
754 #endif
756 #ifdef L_fclose
758 fclose(fp)
759 FILE *fp;
761 int rv = 0;
763 if (fp == 0)
765 errno = EINVAL;
766 return EOF;
768 if (fp->fd != -1)
770 if (fflush(fp))
771 return EOF;
773 if (close(fp->fd))
774 rv = EOF;
775 fp->fd = -1;
778 if (fp->mode & __MODE_FREEBUF)
780 free(fp->bufstart);
781 fp->mode &= ~__MODE_FREEBUF;
782 fp->bufstart = fp->bufend = 0;
785 if (fp->mode & __MODE_FREEFIL)
787 FILE *prev = 0, *ptr;
788 fp->mode = 0;
790 for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next)
792 if (ptr == fp)
794 if (prev == 0)
795 __IO_list = fp->next;
796 else
797 prev->next = fp->next;
799 free(fp);
801 else
802 fp->mode = 0;
804 return rv;
806 #endif
808 #ifdef L_setbuffer
809 void
810 setbuffer(fp, buf, size)
811 FILE * fp;
812 char * buf;
813 int size;
815 fflush(fp);
816 if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart);
817 fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
819 if( buf == 0 )
821 fp->bufstart = fp->unbuf;
822 fp->bufend = fp->unbuf + sizeof(fp->unbuf);
823 fp->mode |= _IONBF;
825 else
827 fp->bufstart = buf;
828 fp->bufend = buf+size;
829 fp->mode |= _IOFBF;
831 fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
833 #endif
835 #ifdef L_setvbuf
836 int setvbuf(fp, buf, mode, size)
837 FILE * fp;
838 char * buf;
839 int mode;
840 size_t size;
842 int rv = 0;
843 fflush(fp);
844 if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart);
845 fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
846 fp->bufstart = fp->unbuf;
847 fp->bufend = fp->unbuf + sizeof(fp->unbuf);
848 fp->mode |= _IONBF;
850 if( mode == _IOFBF || mode == _IOLBF )
852 if( size <= 0 ) size = BUFSIZ;
853 if( buf == 0 )
855 if( (buf = malloc(size)) != 0 )
856 fp->mode |= __MODE_FREEBUF;
857 else rv = EOF;
859 if( buf )
861 fp->bufstart = buf;
862 fp->bufend = buf+size;
863 fp->mode &= ~__MODE_BUF;
864 fp->mode |= mode;
867 fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
868 return rv;
870 #endif
872 #ifdef L_ungetc
874 ungetc(c, fp)
875 int c;
876 FILE *fp;
878 if (fp->mode & __MODE_WRITING)
879 fflush(fp);
881 /* Can't read or there's been an error then return EOF */
882 if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ)
883 return EOF;
885 /* Can't do fast fseeks */
886 fp->mode |= __MODE_UNGOT;
888 if( fp->bufpos > fp->bufstart )
889 return *--fp->bufpos = (unsigned char) c;
890 else if( fp->bufread == fp->bufstart )
891 return *fp->bufread++ = (unsigned char) c;
892 else
893 return EOF;
895 #endif