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>
20 extern FILE *__IO_list
; /* For fflush at exit */
31 #define Inline_init __io_init_vars()
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
];
43 static char buferr
[BUFSIZ
];
48 {bufin
, bufin
, bufin
, bufin
, bufin
+ sizeof(bufin
),
49 0, _IOFBF
| __MODE_READ
| __MODE_IOTRAN
}
54 {bufout
, bufout
, bufout
, bufout
, bufout
+ sizeof(bufout
),
55 1, _IOFBF
| __MODE_WRITE
| __MODE_IOTRAN
}
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 */
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
.
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
.
98 for (fp
= __IO_list
; fp
; fp
= fp
->next
)
102 /* Note we're not de-allocating the memory */
103 /* There doesn't seem to be much point :-) */
113 static int first_time
= 1;
114 if( !first_time
) return ;
119 stdout
->mode
|= _IOLBF
;
120 atexit(__stdio_close_all
);
133 /* If last op was a read ... note fflush may change fp->mode and ret OK */
134 if ((fp
->mode
& __MODE_READING
) && fflush(fp
))
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
)
142 /* In MSDOS translation mode */
143 #if __MODE_IOTRAN && !O_BINARY
144 if (ch
== '\n' && (v
& __MODE_IOTRAN
) && fputc('\r', fp
) == EOF
)
149 if (fp
->bufpos
>= fp
->bufend
&& fflush(fp
))
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
))
161 /* Can the macro handle this by itself ? */
162 if (v
& (__MODE_IOTRAN
| _IOLBF
| _IONBF
))
163 fp
->bufwrite
= fp
->bufstart
; /* Nope */
165 fp
->bufwrite
= fp
->bufend
; /* Yup */
167 /* Correct return val */
168 return (unsigned char) ch
;
179 if (fp
->mode
& __MODE_WRITING
)
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
)
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
))
194 fp
->bufpos
= fp
->bufread
= fp
->bufstart
;
195 ch
= fread(fp
->bufpos
, 1, fp
->bufend
- fp
->bufstart
, fp
);
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
))
221 if (fp
== NULL
) /* On NULL flush the lot. */
230 for (fp
= __IO_list
; fp
; fp
= fp
->next
)
237 /* If there's output data pending */
238 if (fp
->mode
& __MODE_WRITING
)
240 len
= fp
->bufpos
- fp
->bufstart
;
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
);
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.
265 fp
->mode
|= __MODE_ERR
;
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
;
295 /* Nothing special here ... */
307 for (i
= count
-1; i
> 0; i
--)
330 gets(str
) /* BAD function; DON'T use it! */
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
;
338 while (((c
= getc(stdin
)) != EOF
) && (c
!= '\n'))
341 return (((c
== EOF
) && (p
== str
)) ? NULL
: str
); /* NULL == EOF */
354 if (putc(*str
++, fp
) == EOF
)
369 if (((n
= fputs(str
, stdout
)) == EOF
)
370 || (putc('\n', stdout
) == EOF
))
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
386 fread(buf
, size
, nelm
, fp
)
393 unsigned bytes
, got
= 0;
398 /* Want to do this to bring the file pointer up to date */
399 if (v
& __MODE_WRITING
)
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
)
406 /* This could be long, doesn't seem much point tho */
409 len
= fp
->bufread
- fp
->bufpos
;
410 if (len
>= bytes
) /* Enough buffered */
412 memcpy(buf
, fp
->bufpos
, (unsigned) bytes
);
416 else if (len
> 0) /* Some buffered */
418 memcpy(buf
, fp
->bufpos
, 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 */
429 fp
->mode
|= __MODE_ERR
;
433 fp
->mode
|= __MODE_EOF
;
435 return (got
+ len
) / size
;
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
)
459 /* If last op was a read ... note fflush may change fp->mode and ret OK */
460 if ((fp
->mode
& __MODE_READING
) && fflush(fp
))
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
)
468 /* This could be long, doesn't seem much point tho */
471 len
= fp
->bufend
- fp
->bufpos
;
473 /* Flush the buffer if not enough room */
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
);
486 if(memchr(fp
->bufpos
, '\n', bytes
))
491 /* If we're unbuffered or line buffered and have seen nl */
492 if (do_flush
|| (v
& _IONBF
) != 0)
498 /* Too big for the buffer */
503 len
= write(fp
->fd
, buf
, bytes
);
506 buf
+=len
; bytes
-=len
;
509 while (len
> 0 || (len
== -1 && errno
== EINTR
));
512 fp
->mode
|= __MODE_ERR
;
526 fseek(fp
, (long)0, 0);
533 fseek(fp
, offset
, ref
)
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
)
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
;
563 /* Use fflush to sync the pointers */
565 if (fflush(fp
) == EOF
)
567 if (lseek(fp
->fd
, offset
, ref
) < 0)
578 if (fflush(fp
) == EOF
)
580 return lseek(fp
->fd
, 0L, SEEK_CUR
);
590 return __fopen(file
, -1, (FILE*)0, mode
);
596 freopen(file
, mode
, fp
)
601 return __fopen(file
, -1, fp
, mode
);
611 return __fopen((char*)0, file
, (FILE*)0, mode
);
617 * This is the common code for all three of fopen, fdopen and freopen.
620 __fopen(fname
, fd
, fp
, mode
)
627 #if __MODE_IOTRAN && !O_BINARY
633 /* If we've got an fp close the old one (freopen) */
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
);
642 /* decode the new open mode */
647 fopen_mode
|= __MODE_READ
;
650 fopen_mode
|= __MODE_WRITE
;
651 open_mode
= (O_CREAT
| O_TRUNC
);
654 fopen_mode
|= __MODE_WRITE
;
655 open_mode
= (O_CREAT
| O_APPEND
);
658 fopen_mode
|= __MODE_RDWR
;
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
669 fopen_mode
|= __MODE_IOTRAN
;
670 #if __MODE_IOTRAN && !O_BINARY
677 /* Add in the read/write options to mode for open() */
678 switch (fopen_mode
& (__MODE_READ
| __MODE_WRITE
))
683 open_mode
|= O_RDONLY
;
686 open_mode
|= O_WRONLY
;
693 /* Allocate the (FILE) before we do anything irreversable */
696 nfp
= malloc(sizeof(FILE));
701 /* Open the file itself */
703 fd
= open(fname
, open_mode
, 0666);
704 if (fd
< 0) /* Grrrr */
710 fp
->mode
|= fopen_mode
;
711 fclose(fp
); /* Deallocate if required */
716 /* If this isn't freopen create a (FILE) and buffer for it */
720 fp
->next
= __IO_list
;
723 fp
->mode
= __MODE_FREEFIL
;
727 #if __MODE_IOTRAN && !O_BINARY
728 if( do_iosense
) fopen_mode
|= __MODE_IOTRAN
;
733 fp
->bufstart
= malloc(BUFSIZ
);
734 if (fp
->bufstart
== 0) /* Oops, no mem */
735 { /* Humm, full buffering with a two(!) byte
737 fp
->bufstart
= fp
->unbuf
;
738 fp
->bufend
= fp
->unbuf
+ sizeof(fp
->unbuf
);
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
;
778 if (fp
->mode
& __MODE_FREEBUF
)
781 fp
->mode
&= ~__MODE_FREEBUF
;
782 fp
->bufstart
= fp
->bufend
= 0;
785 if (fp
->mode
& __MODE_FREEFIL
)
787 FILE *prev
= 0, *ptr
;
790 for (ptr
= __IO_list
; ptr
&& ptr
!= fp
; ptr
= ptr
->next
)
795 __IO_list
= fp
->next
;
797 prev
->next
= fp
->next
;
810 setbuffer(fp
, buf
, size
)
816 if( fp
->mode
& __MODE_FREEBUF
) free(fp
->bufstart
);
817 fp
->mode
&= ~(__MODE_FREEBUF
|__MODE_BUF
);
821 fp
->bufstart
= fp
->unbuf
;
822 fp
->bufend
= fp
->unbuf
+ sizeof(fp
->unbuf
);
828 fp
->bufend
= buf
+size
;
831 fp
->bufpos
= fp
->bufread
= fp
->bufwrite
= fp
->bufstart
;
836 int setvbuf(fp
, buf
, mode
, size
)
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
);
850 if( mode
== _IOFBF
|| mode
== _IOLBF
)
852 if( size
<= 0 ) size
= BUFSIZ
;
855 if( (buf
= malloc(size
)) != 0 )
856 fp
->mode
|= __MODE_FREEBUF
;
862 fp
->bufend
= buf
+size
;
863 fp
->mode
&= ~__MODE_BUF
;
867 fp
->bufpos
= fp
->bufread
= fp
->bufwrite
= fp
->bufstart
;
878 if (fp
->mode
& __MODE_WRITING
)
881 /* Can't read or there's been an error then return EOF */
882 if ((fp
->mode
& (__MODE_READ
| __MODE_ERR
)) != __MODE_READ
)
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
;