diff options
-rw-r--r-- | libc/stdio/stdio.c | 94 |
1 files changed, 66 insertions, 28 deletions
diff --git a/libc/stdio/stdio.c b/libc/stdio/stdio.c index 3a2f2d073..4d8f2242a 100644 --- a/libc/stdio/stdio.c +++ b/libc/stdio/stdio.c @@ -65,6 +65,18 @@ * Set EOF to end of buffer when fmemopen used on a readonly stream. * Note: I really need to run some tests on this to see what the * glibc code does in each case. + * + * Sept 21, 2003 + * Modify _stdio_READ to conform with C99, as stdio input behavior upon + * encountering EOF changed with Defect Report #141. In the current + * standard, the stream's EOF indicator is "sticky". Once it is set, + * all further input from the stream should fail until the application + * explicitly clears the EOF indicator (clearerr(), file positioning), + * even if more data becomes available. + * Fixed a bug in fgets. Wasn't checking for read errors. + * Minor thread locking optimizations to avoid some unnecessary locking. + * Remove the explicit calls to __builtin_* funcs, as we really need to + * implement a more general solution. */ /* Before we include anything, convert L_ctermid to L_ctermid_function @@ -293,7 +305,8 @@ int getw(FILE *stream) #ifdef __STDIO_WIDE - return (fread((void *)aw, sizeof(int), 1, stream) > 0) ? (*aw) : EOF; + return (fread_unlocked((void *)aw, sizeof(int), 1, stream) > 0) + ? (*aw) : EOF; #else /* __STDIO_WIDE */ @@ -317,7 +330,8 @@ int putw(int w, FILE *stream) #ifdef __STDIO_WIDE - return (fwrite((void *)aw, sizeof(int), 1, stream) == 1) ? 0 : EOF; + return (fwrite_unlocked((void *)aw, sizeof(int), 1, stream) == 1) + ? 0 : EOF; #else /* __STDIO_WIDE */ @@ -1181,7 +1195,8 @@ ssize_t __getdelim(char **__restrict lineptr, size_t *__restrict n, *n += GETDELIM_GROWBY; *lineptr = buf; } - } while (((c = getc(stream)) != EOF) && ((buf[pos++ - 1] = c) != delimiter)); + } while (((c = (getc_unlocked)(stream)) != EOF) /* Disable the macro */ + && ((buf[pos++ - 1] = c) != delimiter)); __STDIO_THREADUNLOCK(stream); @@ -1322,7 +1337,8 @@ static ssize_t _stdio_READ(register FILE *stream, unsigned char *buf, size_t buf { ssize_t rv; - if (bufsize == 0) { + /* NOTE: C99 change: Input fails once the stream's EOF indicator is set. */ + if ((bufsize == 0) || (stream->modeflags & __FLAG_EOF)) { return 0; } @@ -2751,7 +2767,8 @@ UNLOCKED(int,fgetc,(FILE *stream),(stream)) #ifdef __STDIO_WIDE - return (fread(buf, (size_t) 1, (size_t) 1, stream) > 0) ? *buf : EOF; + return (fread_unlocked(buf, (size_t) 1, (size_t) 1, stream) > 0) + ? *buf : EOF; #else /* __STDIO_WIDE */ @@ -2773,19 +2790,39 @@ UNLOCKED(char *,fgets, register char *p; int c; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: What should fgets do if n <= 0? +#endif /* __UCLIBC_MJN3_ONLY__ */ + /* Should we assert here? Or set errno? Or just fail... */ + if (n <= 0) { +/* __set_errno(EINVAL); */ + goto ERROR; + } + p = s; - while ((n > 1) && ((c = getc(stream)) != EOF) && ((*p++ = c) != '\n')) { - --n; - } - if (p == s) { - /* TODO -- should we set errno? */ -/* if (n <= 0) { */ -/* errno = EINVAL; */ -/* } */ - return NULL; + + while (--n) { + if ((c = (getc_unlocked)(stream)) == EOF) { /* Disable the macro. */ + if (__FERROR(stream)) { + goto ERROR; + } + break; + } + if ((*p++ = c) == '\n') { + break; + } } - *p = 0; - return s; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: If n==1 and not at EOF, should fgets return an empty string? +#endif /* __UCLIBC_MJN3_ONLY__ */ + if (p > s) { + *p = 0; + return s; + } + + ERROR: + return NULL; } #endif @@ -2802,7 +2839,8 @@ UNLOCKED(int,fputc,(int c, FILE *stream),(c,stream)) #ifdef __STDIO_WIDE - return (fwrite(buf, (size_t) 1, (size_t) 1, stream) > 0) ? (*buf) : EOF; + return (fwrite_unlocked(buf, (size_t) 1, (size_t) 1, stream) > 0) + ? (*buf) : EOF; #else /* __STDIO_WIDE */ @@ -2824,7 +2862,7 @@ UNLOCKED(int,fputs, #ifdef __STDIO_WIDE - return (fwrite(s, n, (size_t) 1, stream) > 0) ? n : EOF; + return (fwrite_unlocked(s, n, (size_t) 1, stream) > 0) ? n : EOF; #else /* __STDIO_WIDE */ @@ -3484,8 +3522,8 @@ char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval, #ifndef __LOCALE_C_ONLY if (!grouping) { /* Finished a group. */ bufend -= __UCLIBC_CURLOCALE_DATA.thousands_sep_len; - __builtin_memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep, - __UCLIBC_CURLOCALE_DATA.thousands_sep_len); + memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep, + __UCLIBC_CURLOCALE_DATA.thousands_sep_len); if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */ /* Note: g[1] == -1 means no further grouping. But since * we'll never wrap around, we can set grouping to -1 without @@ -3502,9 +3540,9 @@ char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval, #ifndef __LOCALE_C_ONLY if (unlikely(outdigit)) { bufend -= __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]; - __builtin_memcpy(bufend, - (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit], - __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]); + memcpy(bufend, + (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit], + __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]); } else #endif { @@ -3527,8 +3565,8 @@ char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval, #ifndef __LOCALE_C_ONLY if (!grouping) { /* Finished a group. */ bufend -= __UCLIBC_CURLOCALE_DATA.thousands_sep_len; - __builtin_memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep, - __UCLIBC_CURLOCALE_DATA.thousands_sep_len); + memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep, + __UCLIBC_CURLOCALE_DATA.thousands_sep_len); if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */ /* Note: g[1] == -1 means no further grouping. But since * we'll never wrap around, we can set grouping to -1 without @@ -3554,9 +3592,9 @@ char *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval, #ifndef __LOCALE_C_ONLY if (unlikely(outdigit)) { bufend -= __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]; - __builtin_memcpy(bufend, - (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit], - __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]); + memcpy(bufend, + (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit], + __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]); } else #endif { |