diff options
Diffstat (limited to 'libc/stdio')
36 files changed, 506 insertions, 329 deletions
diff --git a/libc/stdio/_READ.c b/libc/stdio/_READ.c index 0c7febb3c..bafa8dffe 100644 --- a/libc/stdio/_READ.c +++ b/libc/stdio/_READ.c @@ -44,7 +44,7 @@ size_t attribute_hidden __stdio_READ(register FILE *stream, #warning EINTR? #endif /* RETRY: */ - if ((rv = __READ(stream, buf, bufsize)) <= 0) { + if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) { if (rv == 0) { __STDIO_STREAM_SET_EOF(stream); } else { diff --git a/libc/stdio/_WRITE.c b/libc/stdio/_WRITE.c index 2bd0977fd..83714bd4c 100644 --- a/libc/stdio/_WRITE.c +++ b/libc/stdio/_WRITE.c @@ -49,7 +49,7 @@ size_t attribute_hidden __stdio_WRITE(register FILE *stream, return bufsize; } stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX; - if ((rv = __WRITE(stream, buf, stodo)) >= 0) { + if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) { #ifdef __UCLIBC_MJN3_ONLY__ #warning TODO: Make custom stream write return check optional. #endif diff --git a/libc/stdio/_fopen.c b/libc/stdio/_fopen.c index 58066ea3f..d68f2ead1 100644 --- a/libc/stdio/_fopen.c +++ b/libc/stdio/_fopen.c @@ -76,13 +76,13 @@ FILE attribute_hidden *_stdio_fopen(intptr_t fname_or_mode, while (*++mode) { # ifdef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ - if (*mode == 'x') { /* Open exclusive (a glibc extension). */ + if (*mode == 'x') { /* Open exclusive (a glibc extension). */ open_mode |= O_EXCL; continue; } # endif # ifdef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ - if (*mode == 'F') { /* Open as large file (uClibc extension). */ + if (*mode == 'F') { /* Open as large file (uClibc extension). */ open_mode |= O_LARGEFILE; continue; } @@ -102,11 +102,7 @@ FILE attribute_hidden *_stdio_fopen(intptr_t fname_or_mode, #ifdef __UCLIBC_HAS_THREADS__ /* We only initialize the mutex in the non-freopen case. */ /* stream->__user_locking = _stdio_user_locking; */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (stream->_lock); -#else - __stdio_init_mutex(&stream->__lock); -#endif + STDIO_INIT_MUTEX(stream->__lock); #endif } @@ -198,18 +194,27 @@ FILE attribute_hidden *_stdio_fopen(intptr_t fname_or_mode, #ifdef __UCLIBC_HAS_THREADS__ /* Even in the freopen case, we reset the user locking flag. */ stream->__user_locking = _stdio_user_locking; -#ifdef __USE_STDIO_FUTEXES__ - /* _IO_lock_init (stream->_lock); */ -#else - /* __stdio_init_mutex(&stream->__lock); */ -#endif + /* STDIO_INIT_MUTEX(stream->__lock); */ #endif #ifdef __STDIO_HAS_OPENLIST - __STDIO_THREADLOCK_OPENLIST; - stream->__nextopen = _stdio_openlist; /* New files are inserted at */ - _stdio_openlist = stream; /* the head of the list. */ - __STDIO_THREADUNLOCK_OPENLIST; +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + if (!(stream->__modeflags & __FLAG_FREEFILE)) + { + /* An freopen call so the file was never removed from the list. */ + } + else +#endif + { + /* We have to lock the del mutex in case another thread wants to fclose() + * the last file. */ + __STDIO_THREADLOCK_OPENLIST_DEL; + __STDIO_THREADLOCK_OPENLIST_ADD; + stream->__nextopen = _stdio_openlist; /* New files are inserted at */ + _stdio_openlist = stream; /* the head of the list. */ + __STDIO_THREADUNLOCK_OPENLIST_ADD; + __STDIO_THREADUNLOCK_OPENLIST_DEL; + } #endif __STDIO_STREAM_VALIDATE(stream); diff --git a/libc/stdio/_fpmaxtostr.c b/libc/stdio/_fpmaxtostr.c index f5632337d..2a63fda9d 100644 --- a/libc/stdio/_fpmaxtostr.c +++ b/libc/stdio/_fpmaxtostr.c @@ -11,7 +11,7 @@ #include <locale.h> #include <bits/uClibc_fpmax.h> -libc_hidden_proto(memset) +/* Experimentally off - libc_hidden_proto(memset) */ typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, intptr_t buf); diff --git a/libc/stdio/_fwrite.c b/libc/stdio/_fwrite.c index 1e0f7ceee..ba4b02fb1 100644 --- a/libc/stdio/_fwrite.c +++ b/libc/stdio/_fwrite.c @@ -7,9 +7,9 @@ #include "_stdio.h" -libc_hidden_proto(memchr) -libc_hidden_proto(memcpy) -libc_hidden_proto(memrchr) +/* Experimentally off - libc_hidden_proto(memchr) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memrchr) */ #ifdef __STDIO_BUFFERS diff --git a/libc/stdio/_scanf.c b/libc/stdio/_scanf.c index 2957d6748..cb768cffb 100644 --- a/libc/stdio/_scanf.c +++ b/libc/stdio/_scanf.c @@ -77,10 +77,10 @@ #include <bits/uClibc_fpmax.h> #endif /* __UCLIBC_HAS_FLOATS__ */ -libc_hidden_proto(memcmp) -libc_hidden_proto(memset) -libc_hidden_proto(strcpy) -libc_hidden_proto(strlen) +/* Experimentally off - libc_hidden_proto(memcmp) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strcpy) */ +/* Experimentally off - libc_hidden_proto(strlen) */ libc_hidden_proto(ungetc) libc_hidden_proto(vfscanf) libc_hidden_proto(vsscanf) @@ -100,7 +100,7 @@ libc_hidden_proto(fgetwc_unlocked) #endif #ifdef __UCLIBC_HAS_XLOCALE__ libc_hidden_proto(__ctype_b_loc) -#elif __UCLIBC_HAS_CTYPE_TABLES__ +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ libc_hidden_proto(__ctype_b) #endif @@ -265,17 +265,13 @@ int vsscanf(__const char *sp, __const char *fmt, va_list ap) #ifdef __UCLIBC_HAS_THREADS__ f.__user_locking = 1; /* Set user locking. */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (f._lock); -#else - __stdio_init_mutex(&f.__lock); -#endif + STDIO_INIT_MUTEX(f.__lock); #endif f.__nextopen = NULL; /* Set these last since __bufgetc initialization depends on * __user_locking and only gets set if user locking is on. */ - f.__bufstart = + f.__bufstart = f.__bufpos = (unsigned char *) ((void *) sp); f.__bufread = f.__bufend = f.__bufstart + strlen(sp); @@ -317,11 +313,7 @@ int vsscanf(__const char *sp, __const char *fmt, va_list ap) #ifdef __UCLIBC_HAS_THREADS__ f.f.__user_locking = 1; /* Set user locking. */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (f.f._lock); -#else - __stdio_init_mutex(&f.f.__lock); -#endif + STDIO_INIT_MUTEX(f.f.__lock); #endif f.f.__nextopen = NULL; @@ -454,11 +446,7 @@ int vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, #ifdef __UCLIBC_HAS_THREADS__ f.__user_locking = 1; /* Set user locking. */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (f._lock); -#else - __stdio_init_mutex(&f.__lock); -#endif + STDIO_INIT_MUTEX(f.__lock); #endif f.__nextopen = NULL; @@ -518,7 +506,7 @@ enum { FLAG_THOUSANDS = 0x20, FLAG_I18N = 0x40, /* only works for d, i, u */ FLAG_MALLOC = 0x80, /* only works for s, S, and [ (and l[)*/ -}; +}; #define SPEC_RANGES { CONV_n, CONV_p, CONV_i, CONV_A, \ @@ -743,7 +731,7 @@ void attribute_hidden __init_scan_cookie(register struct scan_cookie *sc, sc->decpt = __UCLIBC_CURLOCALE_DATA.decimal_point; sc->decpt_len = __UCLIBC_CURLOCALE_DATA.decimal_point_len; #else /* __UCLIBC_HAS_LOCALE__ */ - sc->fake_decpt = sc->decpt = decpt_str; + sc->fake_decpt = sc->decpt = (unsigned char *) decpt_str; sc->decpt_len = 1; #endif /* __UCLIBC_HAS_LOCALE__ */ #ifdef __UCLIBC_HAS_WCHAR__ @@ -1036,7 +1024,7 @@ static int scan_getwc(register struct scan_cookie *sc) __set_errno(EILSEQ); /* In case of incomplete conversion. */ sc->mb_fail = 1; } - + SUCCESS: sc->width = width; /* Restore width. */ @@ -1080,9 +1068,6 @@ static int sc_getc(register struct scan_cookie *sc) wc = '.'; } else #endif /* __UCLIBC_HAS_FLOATS__ */ - if (!__isascii(wc)) { - wc = '?'; - } sc->wc = sc->ungot_char = wc; return (int) wc; @@ -1378,7 +1363,7 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) if (psfs.conv_num == CONV_percent) { goto MATCH_CHAR; - } + } if (psfs.conv_num == CONV_n) { #ifdef __UCLIBC_MJN3_ONLY__ @@ -1422,7 +1407,6 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) { b = (psfs.store ? ((unsigned char *) psfs.cur_ptr) : buf); fail = 1; - if (psfs.conv_num == CONV_c) { if (sc.width == INT_MAX) { @@ -1463,7 +1447,7 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) if (*++fmt == '^') { ++fmt; invert = 1; - } + } memset(scanset, invert, sizeof(scanset)); invert = 1-invert; @@ -1531,7 +1515,7 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) wb = (psfs.store ? ((wchar_t *) psfs.cur_ptr) : wbuf); fail = 1; - + if (psfs.conv_num == CONV_C) { if (sc.width == INT_MAX) { sc.width = 1; @@ -1808,7 +1792,6 @@ int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) unsigned char usflag, base; unsigned char nonzero = 0; unsigned char seendigit = 0; - #ifdef __UCLIBC_MJN3_ONLY__ #warning CONSIDER: What should be returned for an invalid conversion specifier? @@ -1840,7 +1823,7 @@ int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) if (psfs->store) { ++psfs->cnt; _store_inttype(psfs->cur_ptr, psfs->dataargtype, - (uintmax_t) NULL); + (uintmax_t)0); } return 0; } @@ -2101,7 +2084,7 @@ int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) } ++psfs->cnt; _store_inttype(psfs->cur_ptr, psfs->dataargtype, - (uintmax_t) STRTOUIM(buf, NULL, base, 1-usflag)); + (uintmax_t) STRTOUIM((char *) buf, NULL, base, 1-usflag)); } return 0; } @@ -2115,7 +2098,7 @@ int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) p = sc->fake_decpt; do { if (!*p) { - strcpy(b, sc->decpt); + strcpy((char *) b, (char *) sc->decpt); b += sc->decpt_len; break; } @@ -2222,7 +2205,7 @@ int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) assert(seendigit); seendigit = 0; nonzero = 0; - + if (sc->cc == '0') { seendigit = 1; *b++ = '0'; @@ -2238,7 +2221,7 @@ int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) } __scan_getc(sc); } - + if (!seendigit) { /* No digits. Unrecoverable. */ goto DONE_DO_UNGET; } @@ -2250,7 +2233,7 @@ int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) { __fpmax_t x; char *e; - x = __strtofpmax(buf, &e, exp_adjust); + x = __strtofpmax((char *) buf, &e, exp_adjust); assert(!*e); if (psfs->store) { if (psfs->dataargtype & PA_FLAG_LONG_LONG) { diff --git a/libc/stdio/_stdio.c b/libc/stdio/_stdio.c index 4975ef02e..6084abec9 100644 --- a/libc/stdio/_stdio.c +++ b/libc/stdio/_stdio.c @@ -7,7 +7,7 @@ #include "_stdio.h" -libc_hidden_proto(memcpy) +/* Experimentally off - libc_hidden_proto(memcpy) */ libc_hidden_proto(isatty) /* This is pretty much straight from uClibc, but with one important @@ -160,14 +160,18 @@ FILE *_stdio_openlist = _stdio_streams; # ifdef __UCLIBC_HAS_THREADS__ # ifdef __USE_STDIO_FUTEXES__ -# include <bits/stdio-lock.h> -_IO_lock_t _stdio_openlist_lock = _IO_lock_initializer; +# define __UCLIBC_IO_MUTEX_INITIALIZER _IO_lock_initializer # else -pthread_mutex_t _stdio_openlist_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +# define __UCLIBC_IO_MUTEX_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP # endif -int _stdio_openlist_delflag = 0; -# endif +__UCLIBC_IO_MUTEX_INIT(_stdio_openlist_add_lock, __UCLIBC_IO_MUTEX_INITIALIZER); +# ifdef __STDIO_BUFFERS +__UCLIBC_IO_MUTEX_INIT(_stdio_openlist_del_lock, __UCLIBC_IO_MUTEX_INITIALIZER); +volatile int _stdio_openlist_use_count = 0; +int _stdio_openlist_del_count = 0; +# endif +# endif #endif /**********************************************************************/ #ifdef __UCLIBC_HAS_THREADS__ @@ -175,15 +179,13 @@ int _stdio_openlist_delflag = 0; /* 2 if threading not initialized and 0 otherwise; */ int _stdio_user_locking = 2; -#ifndef __USE_STDIO_FUTEXES__ -void attribute_hidden __stdio_init_mutex(pthread_mutex_t *m) +void attribute_hidden __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m) { - static const pthread_mutex_t __stdio_mutex_initializer - = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + const __UCLIBC_MUTEX_STATIC(__stdio_mutex_initializer, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer)); } -#endif #endif /**********************************************************************/ @@ -198,11 +200,11 @@ void attribute_hidden _stdio_term(void) /* First, make sure the open file list is unlocked. If it was * locked, then I suppose there is a chance that a pointer in the * chain might be corrupt due to a partial store. - */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (_stdio_openlist_lock); -#else - __stdio_init_mutex(&_stdio_openlist_lock); + */ + STDIO_INIT_MUTEX(_stdio_openlist_add_lock); +#warning check +#ifdef __STDIO_BUFFERS + STDIO_INIT_MUTEX(_stdio_openlist_del_lock); #endif /* Next we need to worry about the streams themselves. If a stream @@ -211,7 +213,7 @@ void attribute_hidden _stdio_term(void) * Then we reinitialize the locks. */ for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { - if (__STDIO_ALWAYS_THREADTRYLOCK(ptr)) { + if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) { /* The stream is already locked, so we don't want to touch it. * However, if we have custom streams, we can't just close it * or leave it locked since a custom stream may be stacked @@ -222,13 +224,9 @@ void attribute_hidden _stdio_term(void) __STDIO_STREAM_DISABLE_PUTC(ptr); __STDIO_STREAM_INIT_BUFREAD_BUFPOS(ptr); } - + ptr->__user_locking = 1; /* Set locking mode to "by caller". */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (ptr->_lock); -#else - __stdio_init_mutex(&ptr->__lock); /* Shouldn't be necessary, but... */ -#endif + STDIO_INIT_MUTEX(ptr->__lock); /* Shouldn't be necessary, but... */ } #endif diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h index 58b013dda..e8ef08983 100644 --- a/libc/stdio/_stdio.h +++ b/libc/stdio/_stdio.h @@ -15,39 +15,76 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdarg.h> #include <unistd.h> #ifdef __UCLIBC_HAS_WCHAR__ #include <wchar.h> #endif -#ifdef __UCLIBC_HAS_THREADS__ -#include <pthread.h> +#include <bits/uClibc_mutex.h> -#ifdef __USE_STDIO_FUTEXES__ -#define __STDIO_THREADLOCK_OPENLIST \ - _IO_lock_lock(_stdio_openlist_lock) +#define __STDIO_THREADLOCK_OPENLIST_ADD \ + __UCLIBC_IO_MUTEX_LOCK(_stdio_openlist_add_lock) -#define __STDIO_THREADUNLOCK_OPENLIST \ - _IO_lock_unlock(_stdio_openlist_lock) +#define __STDIO_THREADUNLOCK_OPENLIST_ADD \ + __UCLIBC_IO_MUTEX_UNLOCK(_stdio_openlist_add_lock) -#define __STDIO_THREADTRYLOCK_OPENLIST \ - _IO_lock_trylock(_stdio_openlist_lock) -#else -#define __STDIO_THREADLOCK_OPENLIST \ - __pthread_mutex_lock(&_stdio_openlist_lock) +#ifdef __STDIO_BUFFERS -#define __STDIO_THREADUNLOCK_OPENLIST \ - __pthread_mutex_unlock(&_stdio_openlist_lock) +#define __STDIO_THREADLOCK_OPENLIST_DEL \ + __UCLIBC_IO_MUTEX_LOCK(_stdio_openlist_del_lock) -#define __STDIO_THREADTRYLOCK_OPENLIST \ - __pthread_mutex_trylock(&_stdio_openlist_lock) -#endif +#define __STDIO_THREADUNLOCK_OPENLIST_DEL \ + __UCLIBC_IO_MUTEX_UNLOCK(_stdio_openlist_del_lock) -#else -#define __STDIO_THREADLOCK_OPENLIST ((void)0) -#define __STDIO_THREADUNLOCK_OPENLIST ((void)0) +#ifdef __UCLIBC_HAS_THREADS__ +#define __STDIO_OPENLIST_INC_USE \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + ++_stdio_openlist_use_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +extern void _stdio_openlist_dec_use(void); + +#define __STDIO_OPENLIST_DEC_USE \ + _stdio_openlist_dec_use() + +#define __STDIO_OPENLIST_INC_DEL_CNT \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + ++_stdio_openlist_del_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +#define __STDIO_OPENLIST_DEC_DEL_CNT \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + --_stdio_openlist_del_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +#endif /* __UCLIBC_HAS_THREADS__ */ +#endif /* __STDIO_BUFFERS */ +#ifndef __STDIO_THREADLOCK_OPENLIST_DEL +#define __STDIO_THREADLOCK_OPENLIST_DEL ((void)0) +#endif +#ifndef __STDIO_THREADUNLOCK_OPENLIST_DEL +#define __STDIO_THREADUNLOCK_OPENLIST_DEL ((void)0) +#endif +#ifndef __STDIO_OPENLIST_INC_USE +#define __STDIO_OPENLIST_INC_USE ((void)0) +#endif +#ifndef __STDIO_OPENLIST_DEC_USE +#define __STDIO_OPENLIST_DEC_USE ((void)0) +#endif +#ifndef __STDIO_OPENLIST_INC_DEL_CNT +#define __STDIO_OPENLIST_INC_DEL_CNT ((void)0) +#endif +#ifndef __STDIO_OPENLIST_DEC_DEL_CNT +#define __STDIO_OPENLIST_DEC_DEL_CNT ((void)0) #endif #define __UNDEFINED_OR_NONPORTABLE ((void)0) @@ -91,10 +128,10 @@ extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attr (read((STREAMPTR)->__filedes,(BUF),(SIZE))) #define __WRITE(STREAMPTR,BUF,SIZE) \ (write((STREAMPTR)->__filedes,(BUF),(SIZE))) -#define __CLOSE(STREAMPTR) \ - (close((STREAMPTR)->__filedes)) #define __SEEK(STREAMPTR,PPOS,WHENCE) \ (__stdio_seek((STREAMPTR),(PPOS),(WHENCE))) +#define __CLOSE(STREAMPTR) \ + (close((STREAMPTR)->__filedes)) #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ @@ -131,30 +168,30 @@ extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attr /**********************************************************************/ #ifdef __UCLIBC_HAS_WCHAR__ -#define __STDIO_STREAM_IS_NARROW_WRITING(S) \ - (((S)->__modeflags & (__FLAG_WRITING|__FLAG_NARROW)) \ +#define __STDIO_STREAM_IS_NARROW_WRITING(S) \ + (((S)->__modeflags & (__FLAG_WRITING|__FLAG_NARROW)) \ == (__FLAG_WRITING|__FLAG_NARROW)) -#define __STDIO_STREAM_IS_WIDE_WRITING(S) \ - (((S)->__modeflags & (__FLAG_WRITING|__FLAG_WIDE)) \ +#define __STDIO_STREAM_IS_WIDE_WRITING(S) \ + (((S)->__modeflags & (__FLAG_WRITING|__FLAG_WIDE)) \ == (__FLAG_WRITING|__FLAG_WIDE)) #if (__FLAG_NARROW <= __MASK_READING) #error assumption violated regarding __FLAG_NARROW #endif -#define __STDIO_STREAM_IS_NARROW_READING(S) \ +#define __STDIO_STREAM_IS_NARROW_READING(S) \ (((S)->__modeflags & (__MASK_READING|__FLAG_NARROW)) > __FLAG_NARROW) -#define __STDIO_STREAM_IS_WIDE_READING(S) \ +#define __STDIO_STREAM_IS_WIDE_READING(S) \ (((S)->__modeflags & (__MASK_READING|__FLAG_WIDE)) > __FLAG_WIDE) #define __STDIO_STREAM_IS_NARROW(S) ((S)->__modeflags & __FLAG_NARROW) #define __STDIO_STREAM_IS_WIDE(S) ((S)->__modeflags & __FLAG_WIDE) -#define __STDIO_STREAM_SET_NARROW(S) \ +#define __STDIO_STREAM_SET_NARROW(S) \ ((void)((S)->__modeflags |= __FLAG_NARROW)) -#define __STDIO_STREAM_SET_WIDE(S) \ +#define __STDIO_STREAM_SET_WIDE(S) \ ((void)((S)->__modeflags |= __FLAG_WIDE)) #else @@ -163,11 +200,11 @@ extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attr #define __STDIO_STREAM_IS_NARROW_READING(S) __STDIO_STREAM_IS_READING(S) -#define __STDIO_STREAM_IS_NARROW(S) (1) -#define __STDIO_STREAM_IS_WIDE(S) (0) +#define __STDIO_STREAM_IS_NARROW(S) (1) +#define __STDIO_STREAM_IS_WIDE(S) (0) -#define __STDIO_STREAM_SET_NARROW(S) ((void)0) -#define __STDIO_STREAM_SET_WIDE(S) ((void)0) +#define __STDIO_STREAM_SET_NARROW(S) ((void)0) +#define __STDIO_STREAM_SET_WIDE(S) ((void)0) #endif /**********************************************************************/ @@ -197,7 +234,7 @@ extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attr #else # define __STDIO_STREAM_DISABLE_GETC(S) ((void)0) # define __STDIO_STREAM_ENABLE_GETC(S) ((void)0) -# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) (0) +# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) (0) #endif #ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ @@ -210,26 +247,28 @@ extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attr #else # define __STDIO_STREAM_DISABLE_PUTC(S) ((void)0) # define __STDIO_STREAM_ENABLE_PUTC(S) ((void)0) -# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) (0) +# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) (0) #endif #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ #define __STDIO_STREAM_IS_CUSTOM(S) ((S)->__cookie != &((S)->__filedes)) #else -#define __STDIO_STREAM_IS_CUSTOM(S) (0) +#define __STDIO_STREAM_IS_CUSTOM(S) (0) #endif /**********************************************************************/ #ifdef __STDIO_BUFFERS -#define __STDIO_STREAM_FREE_BUFFER(S) \ - do { if ((S)->__modeflags & __FLAG_FREEBUF) free((S)->__bufstart); } while (0) +#define __STDIO_STREAM_FREE_BUFFER(S) \ + do { if ((S)->__modeflags & __FLAG_FREEBUF) \ + free((S)->__bufstart); } while (0) #else #define __STDIO_STREAM_FREE_BUFFER(S) ((void)0) #endif #define __STDIO_STREAM_FREE_FILE(S) \ - do { if ((S)->__modeflags & __FLAG_FREEFILE) free((S)); } while (0) + do { if ((S)->__modeflags & __FLAG_FREEFILE) \ + free((S)); } while (0) #ifdef __UCLIBC_HAS_LFS__ @@ -251,7 +290,7 @@ extern size_t __stdio_wcommit(FILE *__restrict stream) attribute_hidden; extern size_t __stdio_rfill(FILE *__restrict stream) attribute_hidden; extern size_t __stdio_fwrite(const unsigned char *__restrict buffer, - size_t bytes, FILE *__restrict stream) attribute_hidden; + size_t bytes, FILE *__restrict stream) attribute_hidden; #else #define __stdio_fwrite(B,N,S) __stdio_WRITE((S),(B),(N)) @@ -259,8 +298,9 @@ extern size_t __stdio_fwrite(const unsigned char *__restrict buffer, #endif extern size_t __stdio_WRITE(FILE *stream, const unsigned char *buf, - size_t bufsize) attribute_hidden; -extern size_t __stdio_READ(FILE *stream, unsigned char *buf, size_t bufsize) attribute_hidden; + size_t bufsize) attribute_hidden; +extern size_t __stdio_READ(FILE *stream, unsigned char *buf, + size_t bufsize) attribute_hidden; extern int __stdio_trans2r(FILE *__restrict stream) attribute_hidden; extern int __stdio_trans2w(FILE *__restrict stream) attribute_hidden; @@ -293,14 +333,14 @@ extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidde /* Valid when reading... */ #define __STDIO_STREAM_BUFFER_RAVAIL(S) ((S)->__bufread - (S)->__bufpos) #define __STDIO_STREAM_BUFFER_GET(S) (*(S)->__bufpos++) -#define __STDIO_FILL_READ_BUFFER(S) __stdio_rfill((S)) +#define __STDIO_FILL_READ_BUFFER(S) __stdio_rfill((S)) -#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) \ +#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) \ (S)->__bufread = (S)->__bufpos = (S)->__bufstart #define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES (-2) -#define __STDIO_STREAM_FAKE_VSSCANF_FILEDES (-2) +#define __STDIO_STREAM_FAKE_VSSCANF_FILEDES (-2) #define __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES (-3) #define __STDIO_STREAM_FAKE_VSWSCANF_FILEDES (-3) @@ -315,9 +355,9 @@ extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidde #else /* __STDIO_BUFFERS */ -#define __STDIO_STREAM_IS_FBF(S) (0) -#define __STDIO_STREAM_IS_LBF(S) (0) -#define __STDIO_STREAM_IS_NBF(S) (1) +#define __STDIO_STREAM_IS_FBF(S) (0) +#define __STDIO_STREAM_IS_LBF(S) (0) +#define __STDIO_STREAM_IS_NBF(S) (1) #define __STDIO_STREAM_BUFFER_SIZE(S) (0) #define __STDIO_STREAM_BUFFER_ADD(S,C) ((void)0) @@ -329,8 +369,8 @@ extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidde #define __STDIO_STREAM_BUFFER_RAVAIL(S) (0) #define __STDIO_STREAM_BUFFER_GET(S) (EOF) -#define __STDIO_FILL_READ_BUFFER(S) (0) -#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) ((void)0) +#define __STDIO_FILL_READ_BUFFER(S) (0) +#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) ((void)0) #undef __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES #undef __STDIO_STREAM_FAKE_VSSCANF_FILEDES @@ -341,14 +381,14 @@ extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidde #undef __STDIO_STREAM_IS_FAKE_VSWPRINTF # ifdef __USE_OLD_VFPRINTF__ -# define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB (-2) -# define __STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(S) \ +# define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB (-2) +# define __STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(S) \ ((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB) # endif # ifndef __UCLIBC_HAS_WCHAR__ -# define __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB (-2) -# define __STDIO_STREAM_IS_FAKE_VSSCANF_NB(S) \ +# define __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB (-2) +# define __STDIO_STREAM_IS_FAKE_VSSCANF_NB(S) \ ((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB) # endif @@ -359,7 +399,8 @@ extern int __stdio_adjust_position(FILE *__restrict stream, __offmax_t *pos) att #ifdef __STDIO_HAS_OPENLIST /* Uses an implementation hack!!! */ -#define __STDIO_FLUSH_LBF_STREAMS fflush_unlocked((FILE *) &_stdio_openlist) +#define __STDIO_FLUSH_LBF_STREAMS \ + fflush_unlocked((FILE *) &_stdio_openlist) #else #define __STDIO_FLUSH_LBF_STREAMS ((void)0) #endif @@ -382,13 +423,24 @@ extern void _stdio_validate_FILE(const FILE *stream); /**********************************************************************/ -extern FILE *_stdio_fopen(intptr_t fname_or_mode, - const char *__restrict mode, - FILE *__restrict stream, int filedes) attribute_hidden; +extern FILE *_stdio_fopen(intptr_t fname_or_mode, const char *__restrict mode, + FILE *__restrict stream, int filedes) attribute_hidden; + +#ifdef __UCLIBC_HAS_WCHAR__ +extern size_t _wstdio_fwrite(const wchar_t *__restrict ws, + size_t n, FILE *__restrict stream) attribute_hidden; +#endif + +/**********************************************************************/ + +extern int _vfprintf_internal (FILE * __restrict stream, + const char * __restrict format, + va_list arg) attribute_hidden; #ifdef __UCLIBC_HAS_WCHAR__ -extern size_t _wstdio_fwrite(const wchar_t *__restrict ws, size_t n, - FILE *__restrict stream) attribute_hidden; +extern int _vfwprintf_internal (FILE * __restrict stream, + const wchar_t * __restrict format, + va_list arg) attribute_hidden; #endif /**********************************************************************/ diff --git a/libc/stdio/_store_inttype.c b/libc/stdio/_store_inttype.c index 6eb74fe86..fdd4dce05 100644 --- a/libc/stdio/_store_inttype.c +++ b/libc/stdio/_store_inttype.c @@ -35,7 +35,7 @@ void _store_inttype(register void *dest, int desttype, uintmax_t val) *((unsigned char *) dest) = val; return; } -#if defined(LLONG_MAX) && (LONG_MAX != LLONG_MAX) +#if defined(LLONG_MAX) && (INT_MAX != LLONG_MAX) if (desttype == PA_FLAG_LONG_LONG) { *((unsigned long long int *) dest) = val; return; diff --git a/libc/stdio/_uintmaxtostr.c b/libc/stdio/_uintmaxtostr.c index 4310d6458..7a80371b8 100644 --- a/libc/stdio/_uintmaxtostr.c +++ b/libc/stdio/_uintmaxtostr.c @@ -11,7 +11,7 @@ #include <locale.h> #include <bits/uClibc_uintmaxtostr.h> -libc_hidden_proto(memcpy) +/* Experimentally off - libc_hidden_proto(memcpy) */ /* Avoid using long long / and % operations to cut down dependencies on * libgcc.a. Definitely helps on i386 at least. */ diff --git a/libc/stdio/_vfprintf.c b/libc/stdio/_vfprintf.c index f4bbb1c1e..947b5b077 100644 --- a/libc/stdio/_vfprintf.c +++ b/libc/stdio/_vfprintf.c @@ -101,8 +101,6 @@ #include <stdint.h> #include <errno.h> #include <locale.h> - -#define __PRINTF_INFO_NO_BITFIELD #include <printf.h> #ifdef __UCLIBC_HAS_THREADS__ @@ -117,10 +115,10 @@ #include <bits/uClibc_uintmaxtostr.h> #include <bits/uClibc_va_copy.h> -libc_hidden_proto(memcpy) -libc_hidden_proto(memset) -libc_hidden_proto(strlen) -libc_hidden_proto(strnlen) +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strnlen) */ libc_hidden_proto(__glibc_strerror_r) libc_hidden_proto(fputs_unlocked) libc_hidden_proto(abort) @@ -732,7 +730,7 @@ void attribute_hidden _ppfs_setargs(register ppfs_t *ppfs) #ifdef __UCLIBC_HAS_XLOCALE__ libc_hidden_proto(__ctype_b_loc) -#elif __UCLIBC_HAS_CTYPE_TABLES__ +#elif defined __UCLIBC_HAS_CTYPE_TABLES__ libc_hidden_proto(__ctype_b) #endif @@ -898,7 +896,7 @@ int attribute_hidden _ppfs_parsespec(ppfs_t *ppfs) ) { return -1; } - } while (buf[i++]); + } while (buf[i++] && (i < sizeof(buf))); buf[sizeof(buf)-1] = 0; } #else /* __UCLIBC_HAS_WCHAR__ */ @@ -1198,7 +1196,7 @@ int register_printf_function(int spec, printf_function handler, #endif /**********************************************************************/ -#if defined(L_vfprintf) || defined(L_vfwprintf) +#if defined(L__vfprintf_internal) || defined(L__vfwprintf_internal) /* We only support ascii digits (or their USC equivalent codes) in * precision and width settings in *printf (wide) format strings. @@ -1207,14 +1205,15 @@ int register_printf_function(int spec, printf_function handler, static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad); -#ifdef L_vfprintf +#ifdef L__vfprintf_internal -#define VFPRINTF vfprintf +#define VFPRINTF_internal _vfprintf_internal #define FMT_TYPE char #define OUTNSTR _outnstr #define STRLEN strlen #define _PPFS_init _ppfs_init -#define OUTPUT(F,S) fputs_unlocked(S,F) +/* Pulls in fseek: #define OUTPUT(F,S) fputs_unlocked(S,F) */ +#define OUTPUT(F,S) __stdio_fwrite((const unsigned char *)(S),strlen(S),(F)) /* #define _outnstr(stream, string, len) __stdio_fwrite(string, len, stream) */ #define _outnstr(stream, string, len) ((len > 0) ? __stdio_fwrite(string, len, stream) : 0) #define FP_OUT _fp_out_narrow @@ -1234,19 +1233,21 @@ static size_t _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf } len = buflen; } - return r + OUTNSTR(fp, (const char *) buf, len); + return r + OUTNSTR(fp, (const unsigned char *) buf, len); } #endif /* __STDIO_PRINTF_FLOAT */ -#else /* L_vfprintf */ +#else /* L__vfprintf_internal */ -#define VFPRINTF vfwprintf +#define VFPRINTF_internal _vfwprintf_internal #define FMT_TYPE wchar_t #define OUTNSTR _outnwcs #define STRLEN wcslen #define _PPFS_init _ppwfs_init +/* Pulls in fseek: */ #define OUTPUT(F,S) fputws(S,F) +/* TODO: #define OUTPUT(F,S) _wstdio_fwrite((S),wcslen(S),(F)) */ #define _outnwcs(stream, wstring, len) _wstdio_fwrite(wstring, len, stream) #define FP_OUT _fp_out_wide @@ -1417,7 +1418,8 @@ static int _ppwfs_init(register ppfs_t *ppfs, const wchar_t *fmt0) return 0; } -#endif /* L_vfprintf */ +#endif /* L__vfprintf_internal */ + static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad) { @@ -1427,7 +1429,7 @@ static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad) FMT_TYPE pad[1]; *pad = padchar; - while (todo && (OUTNSTR(stream, pad, 1) == 1)) { + while (todo && (OUTNSTR(stream, (const unsigned char *) pad, 1) == 1)) { --todo; } @@ -1439,12 +1441,12 @@ static int _do_one_spec(FILE * __restrict stream, register ppfs_t *ppfs, int *count) { static const char spec_base[] = SPEC_BASE; -#ifdef L_vfprintf +#ifdef L__vfprintf_internal static const char prefix[] = "+\0-\0 \0000x\0000X"; /* 0 2 4 6 9 11*/ -#else /* L_vfprintf */ +#else /* L__vfprintf_internal */ static const wchar_t prefix[] = L"+\0-\0 \0000x\0000X"; -#endif /* L_vfprintf */ +#endif /* L__vfprintf_internal */ enum { PREFIX_PLUS = 0, PREFIX_MINUS = 2, @@ -1465,7 +1467,7 @@ static int _do_one_spec(FILE * __restrict stream, mbstate_t mbstate; #endif /* __UCLIBC_HAS_WCHAR__ */ size_t slen; -#ifdef L_vfprintf +#ifdef L__vfprintf_internal #define SLEN slen #else size_t SLEN; @@ -1532,7 +1534,7 @@ static int _do_one_spec(FILE * __restrict stream, alphacase = __UIM_LOWER; #ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_vfprintf +#ifdef L__vfprintf_internal #warning CONSIDER: Should we ignore these flags if stub locale? What about custom specs? #endif #endif /* __UCLIBC_MJN3_ONLY__ */ @@ -1560,13 +1562,13 @@ static int _do_one_spec(FILE * __restrict stream, padchar = ppfs->info.pad; } #ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_vfprintf +#ifdef L__vfprintf_internal #warning CONSIDER: If using outdigits and/or grouping, how should we interpret precision? #endif #endif /* __UCLIBC_MJN3_ONLY__ */ s = _uintmaxtostr(buf + sizeof(buf) - 1, (uintmax_t) - _load_inttype(*argtype & __PA_INTMASK, + _load_inttype(ppfs->conv_num == CONV_p ? PA_FLAG_LONG : *argtype & __PA_INTMASK, *argptr, base), base, alphacase); if (ppfs->conv_num > CONV_u) { /* signed int */ if (*s == '-') { @@ -1580,7 +1582,7 @@ static int _do_one_spec(FILE * __restrict stream, } } slen = (char *)(buf + sizeof(buf) - 1) - s; -#ifdef L_vfwprintf +#ifdef L__vfwprintf_internal { const char *q = s; mbstate.__mask = 0; /* Initialize the mbstate. */ @@ -1605,13 +1607,13 @@ static int _do_one_spec(FILE * __restrict stream, } if (ppfs->conv_num == CONV_p) {/* null pointer */ s = "(nil)"; -#ifdef L_vfwprintf +#ifdef L__vfwprintf_internal SLEN = #endif slen = 5; numfill = 0; } else if (numfill == 0) { /* if precision 0, no output */ -#ifdef L_vfwprintf +#ifdef L__vfwprintf_internal SLEN = #endif slen = 0; @@ -1637,7 +1639,7 @@ static int _do_one_spec(FILE * __restrict stream, return -1; /* TODO -- try to continue? */ #endif /* __STDIO_PRINTF_FLOAT */ } else if (ppfs->conv_num <= CONV_S) { /* wide char or string */ -#ifdef L_vfprintf +#ifdef L__vfprintf_internal #ifdef __UCLIBC_HAS_WCHAR__ mbstate.__mask = 0; /* Initialize the mbstate. */ @@ -1692,7 +1694,7 @@ static int _do_one_spec(FILE * __restrict stream, slen = 1; } -#else /* L_vfprintf */ +#else /* L__vfprintf_internal */ if (ppfs->conv_num == CONV_S) { /* wide string */ ws = *((wchar_t **) (*argptr)); @@ -1713,7 +1715,7 @@ static int _do_one_spec(FILE * __restrict stream, if (ppfs->conv_num == CONV_s) { /* string */ #ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Fix %s for vfwprintf... output upto illegal sequence? +#warning TODO: Fix %s for _vfwprintf_internal... output upto illegal sequence? #endif /* __UCLIBC_MJN3_ONLY__ */ s = *((char **) (*argptr)); if (s) { @@ -1746,7 +1748,7 @@ static int _do_one_spec(FILE * __restrict stream, goto CHAR_CASE; } -#endif /* L_vfprintf */ +#endif /* L__vfprintf_internal */ #ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ } else if (ppfs->conv_num == CONV_m) { @@ -1778,7 +1780,7 @@ static int _do_one_spec(FILE * __restrict stream, } #ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_vfprintf +#ifdef L__vfprintf_internal #warning CONSIDER: If using outdigits and/or grouping, how should we pad? #endif #endif /* __UCLIBC_MJN3_ONLY__ */ @@ -1805,11 +1807,12 @@ static int _do_one_spec(FILE * __restrict stream, numpad = 0; } OUTPUT(stream, prefix + prefix_num); + if (_charpad(stream, '0', numfill) != numfill) { return -1; } -#ifdef L_vfprintf +#ifdef L__vfprintf_internal #ifdef __UCLIBC_HAS_WCHAR__ if (!ws) { @@ -1831,12 +1834,12 @@ static int _do_one_spec(FILE * __restrict stream, } } #else /* __UCLIBC_HAS_WCHAR__ */ - if (_outnstr(stream, s, slen) != slen) { + if (_outnstr(stream, (const unsigned char *) s, slen) != slen) { return -1; } #endif /* __UCLIBC_HAS_WCHAR__ */ -#else /* L_vfprintf */ +#else /* L__vfprintf_internal */ if (!ws) { assert(s); @@ -1849,7 +1852,7 @@ static int _do_one_spec(FILE * __restrict stream, } } -#endif /* L_vfprintf */ +#endif /* L__vfprintf_internal */ if (_charpad(stream, ' ', numpad) != numpad) { return -1; } @@ -1860,35 +1863,21 @@ static int _do_one_spec(FILE * __restrict stream, libc_hidden_proto(fprintf) -libc_hidden_proto(VFPRINTF) -int VFPRINTF (FILE * __restrict stream, - register const FMT_TYPE * __restrict format, +int VFPRINTF_internal (FILE * __restrict stream, + const FMT_TYPE * __restrict format, va_list arg) { ppfs_t ppfs; int count, r; register const FMT_TYPE *s; - __STDIO_AUTO_THREADLOCK_VAR; - - __STDIO_AUTO_THREADLOCK(stream); count = 0; s = format; - if -#ifdef L_vfprintf - (!__STDIO_STREAM_IS_NARROW_WRITING(stream) - && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW)) -#else - (!__STDIO_STREAM_IS_WIDE_WRITING(stream) - && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE)) -#endif - { - count = -1; - } else if (_PPFS_init(&ppfs, format) < 0) { /* Bad format string. */ - OUTNSTR(stream, (const FMT_TYPE *) ppfs.fmtpos, + if (_PPFS_init(&ppfs, format) < 0) { /* Bad format string. */ + OUTNSTR(stream, (const unsigned char *) ppfs.fmtpos, STRLEN((const FMT_TYPE *)(ppfs.fmtpos))); -#if defined(L_vfprintf) && !defined(NDEBUG) +#if defined(L__vfprintf_internal) && !defined(NDEBUG) fprintf(stderr,"\nIMbS: \"%s\"\n\n", format); #endif count = -1; @@ -1901,7 +1890,7 @@ int VFPRINTF (FILE * __restrict stream, } if (format-s) { /* output any literal text in format string */ - if ( (r = OUTNSTR(stream, s, format-s)) != (format-s)) { + if ( (r = OUTNSTR(stream, (const unsigned char *) s, format-s)) != (format-s)) { count = -1; break; } @@ -1930,14 +1919,66 @@ int VFPRINTF (FILE * __restrict stream, va_end(ppfs.arg); /* Need to clean up after va_copy! */ } -/* #if defined(L_vfprintf) && defined(__UCLIBC_HAS_WCHAR__) */ +/* #if defined(L__vfprintf_internal) && defined(__UCLIBC_HAS_WCHAR__) */ /* DONE: */ /* #endif */ + return count; +} +#endif /* defined(L__vfprintf_internal) || defined(L__vfwprintf_internal) */ + + +/**********************************************************************/ +#if defined(L_vfprintf) || defined(L_vfwprintf) + +/* This is just a wrapper around VFPRINTF_internal. + * Factoring out vfprintf internals allows: + * (1) vdprintf and vsnprintf don't need to setup fake locking, + * (2) __STDIO_STREAM_TRANS_TO_WRITE is not used in vfprintf internals, + * and thus fseek etc is not pulled in by vdprintf and vsnprintf. + * + * In order to not pull in fseek through fputs, OUTPUT() macro + * is using __stdio_fwrite (TODO: do the same for wide functions). + */ +#ifdef L_vfprintf +#define VFPRINTF vfprintf +#define VFPRINTF_internal _vfprintf_internal +#define FMT_TYPE char +#else +#define VFPRINTF vfwprintf +#define VFPRINTF_internal _vfwprintf_internal +#define FMT_TYPE wchar_t +#endif + +libc_hidden_proto(VFPRINTF) +int VFPRINTF (FILE * __restrict stream, + const FMT_TYPE * __restrict format, + va_list arg) +{ + int count; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + if +#ifdef L_vfprintf + (!__STDIO_STREAM_IS_NARROW_WRITING(stream) + && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW)) +#else + (!__STDIO_STREAM_IS_WIDE_WRITING(stream) + && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE)) +#endif + { + count = -1; + } else { + count = VFPRINTF_internal(stream, format, arg); + } + __STDIO_AUTO_THREADUNLOCK(stream); return count; } libc_hidden_def(VFPRINTF) -#endif +#endif /* defined(L_vfprintf) || defined(L_vfwprintf) */ + /**********************************************************************/ diff --git a/libc/stdio/ctermid.c b/libc/stdio/ctermid.c index 1cb8a0845..26369d6f5 100644 --- a/libc/stdio/ctermid.c +++ b/libc/stdio/ctermid.c @@ -7,7 +7,7 @@ #include "_stdio.h" -libc_hidden_proto(strcpy) +/* Experimentally off - libc_hidden_proto(strcpy) */ char *ctermid(register char *s) { diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c index 843599c0f..27d3c7e96 100644 --- a/libc/stdio/fclose.c +++ b/libc/stdio/fclose.c @@ -16,12 +16,15 @@ int fclose(register FILE *stream) int rv = 0; __STDIO_AUTO_THREADLOCK_VAR; - /* First, remove the file from the open file list. */ #ifdef __STDIO_HAS_OPENLIST +#if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) + /* First, remove the file from the open file list. */ { - register FILE *ptr; + FILE *ptr; - __STDIO_THREADLOCK_OPENLIST; + __STDIO_THREADLOCK_OPENLIST_DEL; + __STDIO_THREADLOCK_OPENLIST_ADD; + ptr = _stdio_openlist; if ((ptr = _stdio_openlist) == stream) { _stdio_openlist = stream->__nextopen; } else { @@ -33,13 +36,11 @@ int fclose(register FILE *stream) ptr = ptr->__nextopen; } } - __STDIO_THREADUNLOCK_OPENLIST; - - if (!ptr) { /* Did not find stream in the open file list! */ - return EOF; - } + __STDIO_THREADUNLOCK_OPENLIST_ADD; + __STDIO_THREADUNLOCK_OPENLIST_DEL; } #endif +#endif __STDIO_AUTO_THREADLOCK(stream); @@ -62,6 +63,11 @@ int fclose(register FILE *stream) * Since a file can't be both readonly and writeonly, that makes * an effective signal. It also has the benefit of disabling * transitions to either reading or writing. */ +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + /* Before we mark the file as closed, make sure we increment the openlist use count + * so it isn't freed under us while still cleaning up. */ + __STDIO_OPENLIST_INC_USE; +#endif stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE); stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY); @@ -84,7 +90,16 @@ int fclose(register FILE *stream) __STDIO_AUTO_THREADUNLOCK(stream); __STDIO_STREAM_FREE_BUFFER(stream); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: inefficient - locks and unlocks twice and walks whole list +#endif +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + /* inefficient - locks/unlocks twice and walks whole list */ + __STDIO_OPENLIST_INC_DEL_CNT; + __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */ +#else __STDIO_STREAM_FREE_FILE(stream); +#endif return rv; } diff --git a/libc/stdio/fcloseall.c b/libc/stdio/fcloseall.c index 7d2422562..d3cbb67f8 100644 --- a/libc/stdio/fcloseall.c +++ b/libc/stdio/fcloseall.c @@ -24,14 +24,39 @@ int fcloseall (void) #ifdef __STDIO_HAS_OPENLIST int retval = 0; + FILE *f; - __STDIO_THREADLOCK_OPENLIST; - while (_stdio_openlist) { - if (fclose(_stdio_openlist)) { - retval = EOF; + __STDIO_OPENLIST_INC_USE; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: should probably have a get_head() operation +#endif + __STDIO_THREADLOCK_OPENLIST_ADD; + f = _stdio_openlist; + __STDIO_THREADUNLOCK_OPENLIST_ADD; + + while (f) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: should probably have a get_next() operation +#endif + FILE *n = f->__nextopen; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(f); + /* Only call fclose on the stream if it is not already closed. */ + if ((f->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) + != (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { + if (fclose(f)) { + retval = EOF; + } } + __STDIO_AUTO_THREADUNLOCK(f); + + f = n; } - __STDIO_THREADUNLOCK_OPENLIST; + + __STDIO_OPENLIST_DEC_USE; return retval; diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c index c0f58d8af..11b837dde 100644 --- a/libc/stdio/fflush.c +++ b/libc/stdio/fflush.c @@ -15,24 +15,57 @@ libc_hidden_proto(fflush_unlocked) #warning WISHLIST: Add option to test for undefined behavior of fflush. #endif /* __UCLIBC_MJN3_ONLY__ */ -#ifdef __UCLIBC_HAS_THREADS__ /* Even if the stream is set to user-locking, we still need to lock * when all (lbf) writing streams are flushed. */ -#define MY_STDIO_THREADLOCK(STREAM) \ - if (_stdio_user_locking != 2) { \ - __STDIO_ALWAYS_THREADLOCK(STREAM); \ - } -#define MY_STDIO_THREADUNLOCK(STREAM) \ - if (_stdio_user_locking != 2) { \ - __STDIO_ALWAYS_THREADUNLOCK(STREAM); \ +#define __MY_STDIO_THREADLOCK(__stream) \ + __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \ + (_stdio_user_locking != 2)) + +#define __MY_STDIO_THREADUNLOCK(__stream) \ + __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \ + (_stdio_user_locking != 2)) + +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) +void _stdio_openlist_dec_use(void) +{ + __STDIO_THREADLOCK_OPENLIST_DEL; + if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) { + FILE *p = NULL; + FILE *n; + FILE *stream; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: As an optimization, we could unlock after we move past the head. +#endif + /* Grab the openlist add lock since we might change the head of the list. */ + __STDIO_THREADLOCK_OPENLIST_ADD; + for (stream = _stdio_openlist; stream; stream = n) { + n = stream->__nextopen; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: fix for nonatomic +#endif + if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN)) + == (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { /* The file was closed and should be removed from the list. */ + if (!p) { + _stdio_openlist = n; + } else { + p->__nextopen = n; + } + __STDIO_STREAM_FREE_FILE(stream); + } else { + p = stream; + } + } + __STDIO_THREADUNLOCK_OPENLIST_ADD; + _stdio_openlist_del_count = 0; /* Should be clean now. */ } -#else -#define MY_STDIO_THREADLOCK(STREAM) ((void)0) -#define MY_STDIO_THREADUNLOCK(STREAM) ((void)0) + --_stdio_openlist_use_count; + __STDIO_THREADUNLOCK_OPENLIST_DEL; +} #endif - int fflush_unlocked(register FILE *stream) { #ifdef __STDIO_BUFFERS @@ -55,23 +88,39 @@ int fflush_unlocked(register FILE *stream) } if (!stream) { /* Flush all (lbf) writing streams. */ - __STDIO_THREADLOCK_OPENLIST; - for (stream = _stdio_openlist; stream ; stream = stream->__nextopen) { - MY_STDIO_THREADLOCK(stream); - if (!(((stream->__modeflags | bufmask) - ^ (__FLAG_WRITING|__FLAG_LBF) - ) & (__FLAG_WRITING|__MASK_BUFMODE)) - ) { - if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { - __STDIO_STREAM_DISABLE_PUTC(stream); - __STDIO_STREAM_CLEAR_WRITING(stream); - } else { - retval = EOF; + + __STDIO_OPENLIST_INC_USE; + + __STDIO_THREADLOCK_OPENLIST_ADD; + stream = _stdio_openlist; + __STDIO_THREADUNLOCK_OPENLIST_ADD; + + while(stream) { + /* We only care about currently writing streams and do not want to + * block trying to obtain mutexes on non-writing streams. */ +#warning fix for nonatomic +#warning unnecessary check if no threads + if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */ + __MY_STDIO_THREADLOCK(stream); + /* Need to check again once we have the lock. */ + if (!(((stream->__modeflags | bufmask) + ^ (__FLAG_WRITING|__FLAG_LBF) + ) & (__FLAG_WRITING|__MASK_BUFMODE)) + ) { + if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_CLEAR_WRITING(stream); + } else { + retval = EOF; + } } + __MY_STDIO_THREADUNLOCK(stream); } - MY_STDIO_THREADUNLOCK(stream); + stream = stream->__nextopen; } - __STDIO_THREADUNLOCK_OPENLIST; + + __STDIO_OPENLIST_DEC_USE; + } else if (__STDIO_STREAM_IS_WRITING(stream)) { if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { __STDIO_STREAM_DISABLE_PUTC(stream); diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c index 0dcc7c266..3fad7118d 100644 --- a/libc/stdio/flockfile.c +++ b/libc/stdio/flockfile.c @@ -11,6 +11,6 @@ void flockfile(FILE *stream) { __STDIO_STREAM_VALIDATE(stream); - __STDIO_ALWAYS_THREADLOCK(stream); + __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(stream); } diff --git a/libc/stdio/fmemopen.c b/libc/stdio/fmemopen.c index a78d56efc..eb4fa736e 100644 --- a/libc/stdio/fmemopen.c +++ b/libc/stdio/fmemopen.c @@ -10,7 +10,7 @@ #ifdef __USE_GNU #include "_stdio.h" -libc_hidden_proto(memcpy) +/* Experimentally off - libc_hidden_proto(memcpy) */ libc_hidden_proto(fopencookie) #ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ diff --git a/libc/stdio/fputc.c b/libc/stdio/fputc.c index 8c80bff27..ac3b23ec5 100644 --- a/libc/stdio/fputc.c +++ b/libc/stdio/fputc.c @@ -72,13 +72,19 @@ int __fputc_unlocked(int c, register FILE *stream) } libc_hidden_def(__fputc_unlocked) +/* exposing these would be fundamentally *wrong*! fix you, instead! */ +/* libc_hidden_proto(fputc_unlocked) */ strong_alias(__fputc_unlocked,fputc_unlocked) +/* exposing these would be fundamentally *wrong*! fix you, instead! */ +/* libc_hidden_def(fputc_unlocked) */ libc_hidden_proto(putc_unlocked) strong_alias(__fputc_unlocked,putc_unlocked) libc_hidden_def(putc_unlocked) #ifndef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(fputc) strong_alias(__fputc_unlocked,fputc) +libc_hidden_def(fputc) libc_hidden_proto(putc) strong_alias(__fputc_unlocked,putc) diff --git a/libc/stdio/fputs.c b/libc/stdio/fputs.c index 4111491d6..8a5fd4087 100644 --- a/libc/stdio/fputs.c +++ b/libc/stdio/fputs.c @@ -9,7 +9,7 @@ libc_hidden_proto(fputs_unlocked) -libc_hidden_proto(strlen) +/* Experimentally off - libc_hidden_proto(strlen) */ libc_hidden_proto(fwrite_unlocked) /* Note: The standard says fputs returns a nonnegative number on diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c index c603a9d2e..d8b04f733 100644 --- a/libc/stdio/fread.c +++ b/libc/stdio/fread.c @@ -11,7 +11,7 @@ libc_hidden_proto(fread_unlocked) #ifdef __DO_UNLOCKED -libc_hidden_proto(memcpy) +/* Experimentally off - libc_hidden_proto(memcpy) */ libc_hidden_proto(fflush_unlocked) size_t fread_unlocked(void * __restrict ptr, size_t size, size_t nmemb, diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c index 7314807d3..942a67991 100644 --- a/libc/stdio/freopen.c +++ b/libc/stdio/freopen.c @@ -37,6 +37,8 @@ FILE *freopen(const char * __restrict filename, const char * __restrict mode, __STDIO_STREAM_VALIDATE(stream); + __STDIO_OPENLIST_INC_USE; /* Do not remove the file from the list. */ + /* First, flush and close, but don't deallocate, the stream. */ /* This also removes the stream for the open file list. */ dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE)); @@ -48,13 +50,26 @@ FILE *freopen(const char * __restrict filename, const char * __restrict mode, != (__FLAG_READONLY|__FLAG_WRITEONLY) ) { fclose(stream); /* Failures are ignored. */ + /* NOTE: fclose always does __STDIO_OPENLIST_INC_DEL_CNT. But we don't + * want to remove this FILE from the open list, even if the freopen fails. + * Consider the case of a failed freopen() on stdin. You probably still + * want to be able to call freopen() again. Similarly for other "malloc'd" + * streams. */ + __STDIO_OPENLIST_DEC_DEL_CNT; } fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG); + if (!fp) { + /* Don't remove stream from the open file list and (potentially) free it. + * See _stdio_openlist_dec_use() in fflush.c. */ + stream->__modeflags = __FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN; + } /* Reset the allocation flags. */ stream->__modeflags |= dynmode; + __STDIO_OPENLIST_DEC_USE; + __STDIO_AUTO_THREADUNLOCK(stream); return fp; diff --git a/libc/stdio/ftello.c b/libc/stdio/ftello.c index 4445471a4..bae1d877c 100644 --- a/libc/stdio/ftello.c +++ b/libc/stdio/ftello.c @@ -39,7 +39,10 @@ OFFSET_TYPE FTELL(register FILE *stream) __STDIO_STREAM_VALIDATE(stream); - if ((__SEEK(stream, &pos, SEEK_CUR) < 0) + if ((__SEEK(stream, &pos, + ((__STDIO_STREAM_IS_WRITING(stream) + && (stream->__modeflags & __FLAG_APPEND)) + ? SEEK_END : SEEK_CUR)) < 0) || (__stdio_adjust_position(stream, &pos) < 0)) { pos = -1; } diff --git a/libc/stdio/ftrylockfile.c b/libc/stdio/ftrylockfile.c index d85b8ff59..0d2e156af 100644 --- a/libc/stdio/ftrylockfile.c +++ b/libc/stdio/ftrylockfile.c @@ -15,5 +15,5 @@ int ftrylockfile(FILE *stream) { __STDIO_STREAM_VALIDATE(stream); - return __STDIO_ALWAYS_THREADTRYLOCK(stream); + return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream); } diff --git a/libc/stdio/funlockfile.c b/libc/stdio/funlockfile.c index 048c093d5..2ddf09797 100644 --- a/libc/stdio/funlockfile.c +++ b/libc/stdio/funlockfile.c @@ -11,5 +11,5 @@ void funlockfile(FILE *stream) { __STDIO_STREAM_VALIDATE(stream); - __STDIO_ALWAYS_THREADUNLOCK(stream); + __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream); } diff --git a/libc/stdio/getchar.c b/libc/stdio/getchar.c index 6da8307b6..e29c426c8 100644 --- a/libc/stdio/getchar.c +++ b/libc/stdio/getchar.c @@ -12,13 +12,16 @@ libc_hidden_proto(__fgetc_unlocked) #undef getchar #ifdef __DO_UNLOCKED +/* the only use of the hidden getchar_unlocked is in gets.c */ #undef getchar_unlocked +libc_hidden_proto(getchar_unlocked) int getchar_unlocked(void) { register FILE *stream = stdin; return __GETC_UNLOCKED_MACRO(stream); } +libc_hidden_def(getchar_unlocked) #ifndef __UCLIBC_HAS_THREADS__ strong_alias(getchar_unlocked,getchar) diff --git a/libc/stdio/gets.c b/libc/stdio/gets.c index dc541339b..85bb8475a 100644 --- a/libc/stdio/gets.c +++ b/libc/stdio/gets.c @@ -11,11 +11,9 @@ link_warning(gets, "the 'gets' function is dangerous and should not be used.") /* UNSAFE FUNCTION -- do not bother optimizing */ +/* disable macro, force actual function call */ +#undef getchar_unlocked libc_hidden_proto(getchar_unlocked) -libc_hidden_proto(__fgetc_unlocked) -#ifndef __STDIO_GETC_MACRO -#define __stdin stdin -#endif char *gets(char *s) { diff --git a/libc/stdio/old_vfprintf.c b/libc/stdio/old_vfprintf.c index f81ef8688..85a0967c1 100644 --- a/libc/stdio/old_vfprintf.c +++ b/libc/stdio/old_vfprintf.c @@ -137,17 +137,15 @@ #include <errno.h> #include <ctype.h> #include <bits/uClibc_uintmaxtostr.h> - -#define __PRINTF_INFO_NO_BITFIELD #include <printf.h> #ifdef __UCLIBC_HAS_THREADS__ #include <pthread.h> #endif /* __UCLIBC_HAS_THREADS__ */ -libc_hidden_proto(strlen) -libc_hidden_proto(strnlen) -libc_hidden_proto(memcpy) +/* Experimentally off - libc_hidden_proto(strlen) */ +/* Experimentally off - libc_hidden_proto(strnlen) */ +/* Experimentally off - libc_hidden_proto(memcpy) */ libc_hidden_proto(putc_unlocked) libc_hidden_proto(__fputc_unlocked) libc_hidden_proto(__glibc_strerror_r) @@ -359,13 +357,13 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt, int i; } intarg; int i, cnt, dataargtype, len; - const void *argptr; /* This does not need to be initialized. */ + const void *argptr = argptr; /* ok to be initialized. */ register char *p; const char *fmt0; int preci, width; #define upcase i int radix, dpoint /*, upcase*/; - char tmp[65]; /* TODO - determing needed size from headers */ + char tmp[65]; /* TODO - determine needed size from headers */ char flag[sizeof(spec)]; __STDIO_AUTO_THREADLOCK_VAR; diff --git a/libc/stdio/open_memstream.c b/libc/stdio/open_memstream.c index 25c2f9f61..a9327608a 100644 --- a/libc/stdio/open_memstream.c +++ b/libc/stdio/open_memstream.c @@ -10,8 +10,8 @@ #ifdef __USE_GNU #include "_stdio.h" -libc_hidden_proto(memcpy) -libc_hidden_proto(memset) +/* Experimentally off - libc_hidden_proto(memcpy) */ +/* Experimentally off - libc_hidden_proto(memset) */ libc_hidden_proto(fopencookie) #ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ @@ -160,9 +160,7 @@ FILE *open_memstream(char **__restrict bufloc, size_t *__restrict sizeloc) } } - if (cookie->buf != NULL) { - free(cookie->buf); - } + free(cookie->buf); EXIT_cookie: free(cookie); diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c index 044426abf..43d07fa0f 100644 --- a/libc/stdio/popen.c +++ b/libc/stdio/popen.c @@ -20,6 +20,11 @@ #include <errno.h> #include <unistd.h> #include <sys/wait.h> +#include <bits/uClibc_mutex.h> + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "hmm... susv3 says Pipe streams are byte-oriented." +#endif /* __UCLIBC_MJN3_ONLY__ */ libc_hidden_proto(close) libc_hidden_proto(_exit) @@ -34,23 +39,16 @@ libc_hidden_proto(fclose) /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ #include <sys/syscall.h> #if ! defined __NR_vfork -# define vfork fork +# define vfork fork # define VFORK_LOCK ((void) 0) -# define VFORK_UNLOCK ((void) 0) +# define VFORK_UNLOCK ((void) 0) libc_hidden_proto(fork) #endif -#ifdef __UCLIBC_HAS_THREADS__ -# include <pthread.h> -# include <pthreadP.h> -static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; -#endif -#define LOCK __pthread_mutex_lock(&mylock) -#define UNLOCK __pthread_mutex_unlock(&mylock) - #ifndef VFORK_LOCK -# define VFORK_LOCK LOCK -# define VFORK_UNLOCK UNLOCK +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); +# define VFORK_LOCK __UCLIBC_MUTEX_LOCK(mylock) +# define VFORK_UNLOCK __UCLIBC_MUTEX_UNLOCK(mylock) #endif struct popen_list_item { @@ -127,11 +125,11 @@ FILE *popen(const char *command, const char *modes) if (pid > 0) { /* Parent of vfork... */ pi->pid = pid; pi->f = fp; - LOCK; + VFORK_LOCK; pi->next = popen_list; popen_list = pi; - UNLOCK; - + VFORK_UNLOCK; + return fp; } @@ -145,6 +143,8 @@ FILE *popen(const char *command, const char *modes) return NULL; } +#warning is pclose correct wrt the new mutex semantics? + int pclose(FILE *stream) { struct popen_list_item *p; @@ -153,7 +153,7 @@ int pclose(FILE *stream) /* First, find the list entry corresponding to stream and remove it * from the list. Set p to the list item (NULL if not found). */ - LOCK; + VFORK_LOCK; if ((p = popen_list) != NULL) { if (p->f == stream) { popen_list = p->next; @@ -172,7 +172,7 @@ int pclose(FILE *stream) } while (1); } } - UNLOCK; + VFORK_UNLOCK; if (p) { pid = p->pid; /* Save the pid we need */ diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c index c1566504a..6dbb532db 100644 --- a/libc/stdio/setvbuf.c +++ b/libc/stdio/setvbuf.c @@ -76,8 +76,8 @@ int setvbuf(register FILE * __restrict stream, register char * __restrict buf, } stream->__modeflags |= alloc_flag; - stream->__bufstart = buf; - stream->__bufend = buf + size; + stream->__bufstart = (unsigned char *) buf; + stream->__bufend = (unsigned char *) buf + size; __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); __STDIO_STREAM_DISABLE_GETC(stream); __STDIO_STREAM_DISABLE_PUTC(stream); diff --git a/libc/stdio/tempnam.c b/libc/stdio/tempnam.c index 43cbf781b..3673f4bda 100644 --- a/libc/stdio/tempnam.c +++ b/libc/stdio/tempnam.c @@ -20,7 +20,7 @@ #include <string.h> #include "../misc/internals/tempname.h" -libc_hidden_proto(strdup) +/* Experimentally off - libc_hidden_proto(strdup) */ /* Generate a unique temporary filename using up to five characters of PFX if it is not NULL. The directory to put this file in is searched for diff --git a/libc/stdio/tmpnam.c b/libc/stdio/tmpnam.c index bc4ffeb6a..8df6ff57f 100644 --- a/libc/stdio/tmpnam.c +++ b/libc/stdio/tmpnam.c @@ -20,7 +20,7 @@ #include <string.h> #include "../misc/internals/tempname.h" -libc_hidden_proto(memcpy) +/* Experimentally off - libc_hidden_proto(memcpy) */ static char tmpnam_buffer[L_tmpnam]; diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c index 7a34f6870..b7e2e0852 100644 --- a/libc/stdio/vasprintf.c +++ b/libc/stdio/vasprintf.c @@ -57,7 +57,7 @@ int vasprintf(char **__restrict buf, const char * __restrict format, #else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ - /* This implementation actually calls the printf machinery twice, but only + /* This implementation actually calls the printf machinery twice, but * only does one malloc. This can be a problem though when custom printf * specs or the %m specifier are involved because the results of the * second call might be different from the first. */ diff --git a/libc/stdio/vdprintf.c b/libc/stdio/vdprintf.c index 67adf47be..de54a5c7d 100644 --- a/libc/stdio/vdprintf.c +++ b/libc/stdio/vdprintf.c @@ -11,7 +11,9 @@ #include "_stdio.h" #include <stdarg.h> +#ifdef __USE_OLD_VFPRINTF__ libc_hidden_proto(vfprintf) +#endif libc_hidden_proto(fflush_unlocked) libc_hidden_proto(vdprintf) @@ -22,8 +24,8 @@ int vdprintf(int filedes, const char * __restrict format, va_list arg) #ifdef __STDIO_BUFFERS char buf[64]; /* TODO: provide _optional_ buffering? */ - f.__bufend = buf + sizeof(buf); - f.__bufstart = buf; + f.__bufend = (unsigned char *) buf + sizeof(buf); + f.__bufstart = (unsigned char *) buf; __STDIO_STREAM_DISABLE_GETC(&f); __STDIO_STREAM_DISABLE_PUTC(&f); __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); @@ -48,17 +50,19 @@ int vdprintf(int filedes, const char * __restrict format, va_list arg) __INIT_MBSTATE(&(f.__state)); #endif /* __STDIO_MBSTATE */ -#ifdef __UCLIBC_HAS_THREADS__ +/* _vfprintf_internal doesn't do any locking, locking init is here + * only because of fflush_unlocked. TODO? */ +#if (defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__)) && defined(__UCLIBC_HAS_THREADS__) f.__user_locking = 1; /* Set user locking. */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (f._lock); -#else - __stdio_init_mutex(&f.__lock); -#endif + STDIO_INIT_MUTEX(f.__lock); #endif f.__nextopen = NULL; +#ifdef __USE_OLD_VFPRINTF__ rv = vfprintf(&f, format, arg); +#else + rv = _vfprintf_internal(&f, format, arg); +#endif #ifdef __STDIO_BUFFERS /* If not buffering, then fflush is unnecessary. */ diff --git a/libc/stdio/vsnprintf.c b/libc/stdio/vsnprintf.c index ab6154848..8bc697a48 100644 --- a/libc/stdio/vsnprintf.c +++ b/libc/stdio/vsnprintf.c @@ -10,13 +10,16 @@ libc_hidden_proto(vsnprintf) +#ifdef __USE_OLD_VFPRINTF__ libc_hidden_proto(vfprintf) +#endif #ifdef __UCLIBC_MJN3_ONLY__ #warning WISHLIST: Implement vsnprintf for non-buffered and no custom stream case. #endif /* __UCLIBC_MJN3_ONLY__ */ #ifdef __STDIO_BUFFERS +/* NB: we can still have __USE_OLD_VFPRINTF__ defined in this case! */ int vsnprintf(char *__restrict buf, size_t size, const char * __restrict format, va_list arg) @@ -43,13 +46,9 @@ int vsnprintf(char *__restrict buf, size_t size, __INIT_MBSTATE(&(f.__state)); #endif /* __STDIO_MBSTATE */ -#ifdef __UCLIBC_HAS_THREADS__ +#if defined(__USE_OLD_VFPRINTF__) && defined(__UCLIBC_HAS_THREADS__) f.__user_locking = 1; /* Set user locking. */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (f._lock); -#else - __stdio_init_mutex(&f.__lock); -#endif + STDIO_INIT_MUTEX(f.__lock); #endif f.__nextopen = NULL; @@ -57,15 +56,20 @@ int vsnprintf(char *__restrict buf, size_t size, size = SIZE_MAX - (size_t) buf; } +/* TODO: this comment seems to be wrong */ /* Set these last since __bufputc initialization depends on * __user_locking and only gets set if user locking is on. */ - f.__bufstart = buf; - f.__bufend = buf + size; + f.__bufstart = (unsigned char *) buf; + f.__bufend = (unsigned char *) buf + size; __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); __STDIO_STREAM_DISABLE_GETC(&f); __STDIO_STREAM_ENABLE_PUTC(&f); +#ifdef __USE_OLD_VFPRINTF__ rv = vfprintf(&f, format, arg); +#else + rv = _vfprintf_internal(&f, format, arg); +#endif if (size) { if (f.__bufpos == f.__bufend) { --f.__bufpos; @@ -118,11 +122,7 @@ int vsnprintf(char *__restrict buf, size_t size, #ifdef __UCLIBC_HAS_THREADS__ f.f.__user_locking = 1; /* Set user locking. */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (f.f._lock); -#else - __stdio_init_mutex(&f.f.__lock); -#endif + STDIO_INIT_MUTEX(f.f.__lock); #endif f.f.__nextopen = NULL; @@ -205,17 +205,9 @@ int vsnprintf(char *__restrict buf, size_t size, __INIT_MBSTATE(&(f.__state)); #endif /* __STDIO_MBSTATE */ -#ifdef __UCLIBC_HAS_THREADS__ - f.__user_locking = 1; /* Set user locking. */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (f._lock); -#else - __stdio_init_mutex(&f.__lock); -#endif -#endif f.__nextopen = NULL; - rv = vfprintf(&f, format, arg); + rv = _vfprintf_internal(&f, format, arg); return rv; } diff --git a/libc/stdio/vswprintf.c b/libc/stdio/vswprintf.c index d95de51a2..cddf1d5d9 100644 --- a/libc/stdio/vswprintf.c +++ b/libc/stdio/vswprintf.c @@ -11,7 +11,7 @@ libc_hidden_proto(vswprintf) -libc_hidden_proto(vfwprintf) +/* NB: this file is not used if __USE_OLD_VFPRINTF__ */ #ifndef __STDIO_BUFFERS #warning Skipping vswprintf since no buffering! @@ -40,14 +40,6 @@ int vswprintf(wchar_t *__restrict buf, size_t size, __INIT_MBSTATE(&(f.__state)); #endif /* __STDIO_MBSTATE */ -#ifdef __UCLIBC_HAS_THREADS__ - f.__user_locking = 1; /* Set user locking. */ -#ifdef __USE_STDIO_FUTEXES__ - _IO_lock_init (f._lock); -#else - __stdio_init_mutex(&f.__lock); -#endif -#endif f.__nextopen = NULL; if (size > ((SIZE_MAX - (size_t) buf)/sizeof(wchar_t))) { @@ -60,7 +52,7 @@ int vswprintf(wchar_t *__restrict buf, size_t size, __STDIO_STREAM_DISABLE_GETC(&f); __STDIO_STREAM_DISABLE_PUTC(&f); - rv = vfwprintf(&f, format, arg); + rv = _vfwprintf_internal(&f, format, arg); /* NOTE: Return behaviour differs from snprintf... */ if (f.__bufpos == f.__bufend) { |