diff options
author | "Steven J. Hill" <sjhill@realitydiluted.com> | 2006-02-26 03:57:14 +0000 |
---|---|---|
committer | "Steven J. Hill" <sjhill@realitydiluted.com> | 2006-02-26 03:57:14 +0000 |
commit | 9921832fa13cef31006cfa69bc5574636c36ac0f (patch) | |
tree | 4faa87a1fbc9842126d3bdc61c0d64285ebcc849 | |
parent | 292e2d7a707449b531422d37cec4608d304da24e (diff) | |
download | uClibc-alpine-9921832fa13cef31006cfa69bc5574636c36ac0f.tar.bz2 uClibc-alpine-9921832fa13cef31006cfa69bc5574636c36ac0f.tar.xz |
Merge from trunk.
132 files changed, 3024 insertions, 4715 deletions
diff --git a/libc/stdio/Makefile.in b/libc/stdio/Makefile.in index 3a6f739b4..5d4d74ed2 100644 --- a/libc/stdio/Makefile.in +++ b/libc/stdio/Makefile.in @@ -1,10 +1,12 @@ # Makefile for uClibc # # Copyright (C) 2000 by Lineo, inc. -# Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org> -# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org> +# Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> +# Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> # -# Licensed under LGPL v2.1, see the file COPYING.LIB in this tarball for details. +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +# Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. # # SUSv3 functions @@ -55,96 +57,51 @@ CUSRC := \ # putc_unlocked -> alias for fputc_unlocked # vfprintf and support functions -MSRC1 := vfprintf.c ifneq ($(USE_OLD_VFPRINTF),y) -MOBJ1 := \ - vfprintf.o \ - _ppfs_init.o _ppfs_prepargs.o _ppfs_setargs.o _ppfs_parsespec.o \ - register_printf_function.o parse_printf_format.o +VF_CSRC := \ + vfprintf.c \ + _ppfs_init.c _ppfs_prepargs.c _ppfs_setargs.c _ppfs_parsespec.c \ + register_printf_function.c parse_printf_format.c +CSRC += $(VF_CSRC) else -MOBJ1 := CSRC += old_vfprintf.c endif # vfscanf and support functions plus other *scanf funcs -MSRC2 := scanf.c -MOBJ2 := \ - vfscanf.o __scan_cookie.o __psfs_parse_spec.o __psfs_do_numeric.o \ - scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o +CSRC += \ + vfscanf.c __scan_cookie.c __psfs_parse_spec.c __psfs_do_numeric.c \ + scanf.c sscanf.c fscanf.c vscanf.c vsscanf.c -CWSRC := ifeq ($(UCLIBC_HAS_WCHAR),y) -CWSRC += _wfwrite.c fwprintf.c swprintf.c vswprintf.c vwprintf.c wprintf.c \ +CSRC += _wfwrite.c fwprintf.c swprintf.c vswprintf.c vwprintf.c wprintf.c \ fwide.c ungetwc.c CUSRC += fgetwc.c getwchar.c fgetws.c fputwc.c putwchar.c fputws.c # getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias) # putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias) -MOBJ1 += vfwprintf.o -MOBJ2 += wscanf.o swscanf.o fwscanf.o vwscanf.o vswscanf.o vfwscanf.o +CSRC += vfwprintf.c +CSRC += wscanf.c swscanf.c fwscanf.c vwscanf.c vswscanf.c vfwscanf.c endif -CSRC += $(CUSRC) $(CWSRC) +CUSRC_UNLOCKED := $(patsubst %.c,%_unlocked.c,$(CUSRC)) -ifneq ($(DOMULTI),n) -STDIO_CSRC_NO_MULTI := fwrite.c fputc.c fputs.c fprintf.c _fpmaxtostr.c -CSRC := $(filter-out $(STDIO_CSRC_NO_MULTI),$(CSRC)) -endif -STDIO_MOBJ1_NO_MULTI := vfprintf.o vfwprintf.o register_printf_function.o -STDIO_MOBJ2_NO_MULTI := vfscanf.o vfwscanf.o fscanf.o -STDIO_MOBJ_NO_MULTI := $(STDIO_MOBJ1_NO_MULTI) $(STDIO_MOBJ2_NO_MULTI) +CSRC += $(CUSRC) $(CUSRC_UNLOCKED) STDIO_DIR := $(top_srcdir)libc/stdio STDIO_OUT := $(top_builddir)libc/stdio STDIO_SRC := $(patsubst %.c,$(STDIO_DIR)/%.c,$(CSRC)) STDIO_OBJ := $(patsubst %.c,$(STDIO_OUT)/%.o,$(CSRC)) -STDIO_CUSRC := $(patsubst %.c,$(STDIO_DIR)/%.c,$(CUSRC)) -STDIO_CUOBJ := $(patsubst %.c,$(STDIO_OUT)/%_unlocked.o,$(CUSRC)) - -STDIO_MSRC1 := $(patsubst %.c,$(STDIO_DIR)/%.c,$(MSRC1)) -STDIO_MSRC2 := $(patsubst %.c,$(STDIO_DIR)/%.c,$(MSRC2)) -STDIO_MOBJ1 := $(patsubst %.o,$(STDIO_OUT)/%.o,$(MOBJ1)) -STDIO_MOBJ2 := $(patsubst %.o,$(STDIO_OUT)/%.o,$(MOBJ2)) - -STDIO_MSRC := $(STDIO_MSRC1) $(STDIO_MSRC2) -STDIO_MOBJ := $(STDIO_MOBJ1) $(STDIO_MOBJ2) - -STDIO_DEF := $(patsubst %,-DL_%,$(subst .o,,$(filter-out $(STDIO_MOBJ_NO_MULTI),$(notdir $(STDIO_MOBJ))))) - -STDIO_OBJS := $(STDIO_OBJ) $(STDIO_MOBJ) $(STDIO_CUOBJ) - -STDIO_NO_MULTI := $(STDIO_CUOBJ) - -# these need special handling or rewrite to support multi-build -# CUOBJ -%_unlocked.o: %.c - $(compile.c) -D__DO_UNLOCKED -%_unlocked.os: %.c - $(compile.c) -D__DO_UNLOCKED +libc-y += $(STDIO_OBJ) -$(STDIO_MOBJ1): $(STDIO_MSRC1) - $(compile.m) - -$(STDIO_MOBJ1:.o=.os): $(STDIO_MSRC1) - $(compile.m) - -$(STDIO_MOBJ2): $(STDIO_MSRC2) - $(compile.m) - -$(STDIO_MOBJ2:.o=.os): $(STDIO_MSRC2) - $(compile.m) - -libc-a-y+=$(STDIO_OBJS) -libc-so-y+=$(STDIO_OBJS:.o=.os) - -CFLAGS-multi-y+=$(STDIO_DEF) -libc-multi-y+=$(STDIO_SRC) $(STDIO_MSRC) -libc-nomulti-y+=$(STDIO_NO_MULTI) -libc-nomulti-y+=$(patsubst %.c,$(STDIO_OUT)/%.o,$(STDIO_CSRC_NO_MULTI)) -libc-nomulti-y+=$(patsubst %.o,$(STDIO_OUT)/%.o,$(STDIO_MOBJ_NO_MULTI)) +ifneq ($(USE_OLD_VFPRINTF),y) +libc-nomulti-y += $(patsubst %.c,$(STDIO_OUT)/%.o,$(VF_CSRC)) +endif +ifeq ($(UCLIBC_HAS_WCHAR),y) +libc-nomulti-y += $(STDIO_OUT)/vfwprintf.o $(STDIO_OUT)/vfwscanf.o +endif -objclean-y+=stdio_objclean +objclean-y += stdio_objclean stdio_objclean: - $(RM) $(STDIO_OUT)/*.{o,os} + $(RM) $(STDIO_OUT)/*.{o,os,oS} diff --git a/libc/stdio/_READ.c b/libc/stdio/_READ.c index e27309c11..0c7febb3c 100644 --- a/libc/stdio/_READ.c +++ b/libc/stdio/_READ.c @@ -5,10 +5,11 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define read __read - #include "_stdio.h" +libc_hidden_proto(read) +libc_hidden_proto(abort) + /* Given a reading stream without its end-of-file indicator set and * with no buffered input or ungots, read at most 'bufsize' bytes * into 'buf' (which may be the stream's __bufstart). diff --git a/libc/stdio/_WRITE.c b/libc/stdio/_WRITE.c index c2b0e7b5d..2bd0977fd 100644 --- a/libc/stdio/_WRITE.c +++ b/libc/stdio/_WRITE.c @@ -5,10 +5,10 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define write __write - #include "_stdio.h" +libc_hidden_proto(write) + /* Given a writing stream with no buffered output, write the * data in 'buf' (which may be the stream's bufstart) of size * 'bufsize' to the stream. If a write error occurs, set the diff --git a/libc/stdio/__fsetlocking.c b/libc/stdio/__fsetlocking.c index 5b6070cc3..746a098f9 100644 --- a/libc/stdio/__fsetlocking.c +++ b/libc/stdio/__fsetlocking.c @@ -8,6 +8,11 @@ #include "_stdio.h" #include <stdio_ext.h> +libc_hidden_proto(__fsetlocking) +#ifdef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(_stdio_user_locking) +#endif + /* Not threadsafe. */ /* Notes: @@ -15,7 +20,7 @@ * glibc treats invalid locking_mode args as FSETLOCKING_INTERNAL. */ -int attribute_hidden __fsetlocking_internal(FILE *stream, int locking_mode) +int __fsetlocking(FILE *stream, int locking_mode) { #ifdef __UCLIBC_HAS_THREADS__ int current = 1 + (stream->__user_locking & 1); @@ -43,5 +48,4 @@ int attribute_hidden __fsetlocking_internal(FILE *stream, int locking_mode) return FSETLOCKING_INTERNAL; #endif } - -strong_alias(__fsetlocking_internal,__fsetlocking) +libc_hidden_def(__fsetlocking) diff --git a/libc/stdio/__psfs_do_numeric.c b/libc/stdio/__psfs_do_numeric.c new file mode 100644 index 000000000..e3714776c --- /dev/null +++ b/libc/stdio/__psfs_do_numeric.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___psfs_do_numeric +#include "_scanf.c" diff --git a/libc/stdio/__psfs_parse_spec.c b/libc/stdio/__psfs_parse_spec.c new file mode 100644 index 000000000..cac9cda46 --- /dev/null +++ b/libc/stdio/__psfs_parse_spec.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___psfs_parse_spec +#include "_scanf.c" diff --git a/libc/stdio/__scan_cookie.c b/libc/stdio/__scan_cookie.c new file mode 100644 index 000000000..d5d53c4c5 --- /dev/null +++ b/libc/stdio/__scan_cookie.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___scan_cookie +#include "_scanf.c" diff --git a/libc/stdio/_cs_funcs.c b/libc/stdio/_cs_funcs.c index ef92048c0..38a8351e5 100644 --- a/libc/stdio/_cs_funcs.c +++ b/libc/stdio/_cs_funcs.c @@ -7,20 +7,29 @@ #include "_stdio.h" +libc_hidden_proto(read) +libc_hidden_proto(write) +libc_hidden_proto(close) +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(lseek64) +#else +libc_hidden_proto(lseek) +#endif + /**********************************************************************/ #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ /**********************************************************************/ ssize_t attribute_hidden _cs_read(void *cookie, char *buf, size_t bufsize) { - return __read(*((int *) cookie), buf, bufsize); + return read(*((int *) cookie), buf, bufsize); } /**********************************************************************/ ssize_t attribute_hidden _cs_write(void *cookie, const char *buf, size_t bufsize) { - return __write(*((int *) cookie), (char *) buf, bufsize); + return write(*((int *) cookie), (char *) buf, bufsize); } /**********************************************************************/ @@ -30,9 +39,9 @@ int attribute_hidden _cs_seek(void *cookie, register __offmax_t *pos, int whence __offmax_t res; #ifdef __UCLIBC_HAS_LFS__ - res = __lseek64(*((int *) cookie), *pos, whence); + res = lseek64(*((int *) cookie), *pos, whence); #else - res = __lseek(*((int *) cookie), *pos, whence); + res = lseek(*((int *) cookie), *pos, whence); #endif return (res >= 0) ? ((*pos = res), 0) : ((int) res); @@ -42,7 +51,7 @@ int attribute_hidden _cs_seek(void *cookie, register __offmax_t *pos, int whence int attribute_hidden _cs_close(void *cookie) { - return __close(*((int *) cookie)); + return close(*((int *) cookie)); } /**********************************************************************/ @@ -54,9 +63,9 @@ int attribute_hidden __stdio_seek(FILE *stream, register __offmax_t *pos, int wh __offmax_t res; #ifdef __UCLIBC_HAS_LFS__ - res = __lseek64(stream->__filedes, *pos, whence); + res = lseek64(stream->__filedes, *pos, whence); #else - res = __lseek(stream->__filedes, *pos, whence); + res = lseek(stream->__filedes, *pos, whence); #endif return (res >= 0) ? ((*pos = res), 0) : ((int) res); diff --git a/libc/stdio/_flushlbf.c b/libc/stdio/_flushlbf.c index 31ed2fc55..8a551a746 100644 --- a/libc/stdio/_flushlbf.c +++ b/libc/stdio/_flushlbf.c @@ -8,6 +8,8 @@ #include "_stdio.h" #include <stdio_ext.h> +libc_hidden_proto(fflush_unlocked) + /* Solaris function -- * Flush all line buffered (writing) streams. */ diff --git a/libc/stdio/_fopen.c b/libc/stdio/_fopen.c index 33b7b89ad..4ca028275 100644 --- a/libc/stdio/_fopen.c +++ b/libc/stdio/_fopen.c @@ -5,10 +5,16 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define isatty __isatty - #include "_stdio.h" +libc_hidden_proto(isatty) +libc_hidden_proto(open) +libc_hidden_proto(fcntl) + +#ifdef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(_stdio_user_locking) +#endif + /* * Cases: * fopen64 : filename != NULL, stream == NULL, filedes == -2 @@ -100,12 +106,8 @@ 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 -#endif } #ifdef __UCLIBC_MJN3_ONLY__ @@ -125,7 +127,7 @@ FILE attribute_hidden *_stdio_fopen(intptr_t fname_or_mode, /* NOTE: fopencookie needs changing if the basic check changes! */ if (((i & (((int) fname_or_mode) + 1)) != i) /* Basic agreement? */ || (((open_mode & ~((__mode_t) fname_or_mode)) & O_APPEND) - && __fcntl(filedes, F_SETFL, O_APPEND)) /* Need O_APPEND. */ + && fcntl(filedes, F_SETFL, O_APPEND)) /* Need O_APPEND. */ ) { goto DO_EINVAL; } @@ -134,7 +136,7 @@ FILE attribute_hidden *_stdio_fopen(intptr_t fname_or_mode, & O_LARGEFILE) ); } else { __STDIO_WHEN_LFS( if (filedes < -1) open_mode |= O_LARGEFILE ); - if ((stream->__filedes = __open(((const char *) fname_or_mode), + if ((stream->__filedes = open(((const char *) fname_or_mode), open_mode, 0666)) < 0) { goto FREE_STREAM; } @@ -196,12 +198,8 @@ 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 -#endif #ifdef __STDIO_HAS_OPENLIST __STDIO_THREADLOCK_OPENLIST; diff --git a/libc/stdio/_fpmaxtostr.c b/libc/stdio/_fpmaxtostr.c index 99fc9a9dd..9b87f64cf 100644 --- a/libc/stdio/_fpmaxtostr.c +++ b/libc/stdio/_fpmaxtostr.c @@ -11,6 +11,11 @@ #include <locale.h> #include <bits/uClibc_fpmax.h> +libc_hidden_proto(memset) +#ifdef __UCLIBC_HAS_LOCALE__ +libc_hidden_proto(__global_locale) +#endif + typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, intptr_t buf); @@ -198,7 +203,9 @@ static const __fpmax_t exp16_table[] = { #define FPO_STR_WIDTH (0x80 | ' '); #define FPO_STR_PREC 'p' -ssize_t attribute_hidden _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, +ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) attribute_hidden; +ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, __fp_outfunc_t fp_outfunc) { #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ @@ -275,11 +282,11 @@ ssize_t attribute_hidden _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info } if (x == 0) { /* Handle 0 now to avoid false positive. */ -#if 1 +#ifdef __UCLIBC_HAVE_SIGNED_ZERO__ if (zeroisnegative(x)) { /* Handle 'signed' zero. */ *sign_str = '-'; } -#endif +#endif /* __UCLIBC_HAVE_SIGNED_ZERO__ */ exp = -1; goto GENERATE_DIGITS; } @@ -417,7 +424,7 @@ ssize_t attribute_hidden _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info if (mode == 'f') { round += exp; if (round < -1) { - __memset(buf, '0', DECIMAL_DIG); /* OK, since 'f' -> decimal case. */ + memset(buf, '0', DECIMAL_DIG); /* OK, since 'f' -> decimal case. */ exp = -1; round = -1; } diff --git a/libc/stdio/_fwrite.c b/libc/stdio/_fwrite.c index 600b15e6d..1e0f7ceee 100644 --- a/libc/stdio/_fwrite.c +++ b/libc/stdio/_fwrite.c @@ -5,11 +5,12 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define memrchr __memrchr -#define memchr __memchr - #include "_stdio.h" +libc_hidden_proto(memchr) +libc_hidden_proto(memcpy) +libc_hidden_proto(memrchr) + #ifdef __STDIO_BUFFERS /* Either buffer data or (commit buffer if necessary and) write. */ @@ -35,7 +36,7 @@ size_t attribute_hidden __stdio_fwrite(const unsigned char * __restrict buffer, if (pending > bytes) { pending = bytes; } - __memcpy(stream->__bufpos, buffer, pending); + memcpy(stream->__bufpos, buffer, pending); stream->__bufpos += pending; __STDIO_STREAM_VALIDATE(stream); return bytes; @@ -43,7 +44,7 @@ size_t attribute_hidden __stdio_fwrite(const unsigned char * __restrict buffer, /* RETRY: */ if (bytes <= __STDIO_STREAM_BUFFER_WAVAIL(stream)) { - __memcpy(stream->__bufpos, buffer, bytes); + memcpy(stream->__bufpos, buffer, bytes); stream->__bufpos += bytes; if (__STDIO_STREAM_IS_LBF(stream) && memrchr(buffer, '\n', bytes) /* Search backwards. */ diff --git a/libc/stdio/_load_inttype.c b/libc/stdio/_load_inttype.c index e4dc61e9c..057f5f256 100644 --- a/libc/stdio/_load_inttype.c +++ b/libc/stdio/_load_inttype.c @@ -8,7 +8,8 @@ #include "_stdio.h" #include <printf.h> -uintmax_t attribute_hidden _load_inttype(int desttype, register const void *src, int uflag) +uintmax_t _load_inttype(int desttype, register const void *src, int uflag) attribute_hidden; +uintmax_t _load_inttype(int desttype, register const void *src, int uflag) { if (uflag >= 0) { /* unsigned */ #if LONG_MAX != INT_MAX diff --git a/libc/stdio/_ppfs_init.c b/libc/stdio/_ppfs_init.c new file mode 100644 index 000000000..80d8aeb96 --- /dev/null +++ b/libc/stdio/_ppfs_init.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_init +#include "_vfprintf.c" diff --git a/libc/stdio/_ppfs_parsespec.c b/libc/stdio/_ppfs_parsespec.c new file mode 100644 index 000000000..a3e298801 --- /dev/null +++ b/libc/stdio/_ppfs_parsespec.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_parsespec +#include "_vfprintf.c" diff --git a/libc/stdio/_ppfs_prepargs.c b/libc/stdio/_ppfs_prepargs.c new file mode 100644 index 000000000..a6efbf466 --- /dev/null +++ b/libc/stdio/_ppfs_prepargs.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_prepargs +#include "_vfprintf.c" diff --git a/libc/stdio/_ppfs_setargs.c b/libc/stdio/_ppfs_setargs.c new file mode 100644 index 000000000..41214d993 --- /dev/null +++ b/libc/stdio/_ppfs_setargs.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_setargs +#include "_vfprintf.c" diff --git a/libc/stdio/_stdio.c b/libc/stdio/_stdio.c index e8d90a800..a967bd0de 100644 --- a/libc/stdio/_stdio.c +++ b/libc/stdio/_stdio.c @@ -5,10 +5,11 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define isatty __isatty - #include "_stdio.h" +libc_hidden_proto(memcpy) +libc_hidden_proto(isatty) + /* This is pretty much straight from uClibc, but with one important * difference. * @@ -129,12 +130,19 @@ static FILE _stdio_streams[] = { 0 ) }; +/* psm: moved to _stdio.h: libc_hidden_proto(stdin/stdout) */ FILE *stdin = _stdio_streams; +libc_hidden_data_def(stdin) FILE *stdout = _stdio_streams + 1; +libc_hidden_data_def(stdout) +libc_hidden_proto(stderr) FILE *stderr = _stdio_streams + 2; +libc_hidden_data_def(stderr) #ifdef __STDIO_GETC_MACRO +libc_hidden_proto(__stdin) FILE *__stdin = _stdio_streams; /* For getchar() macro. */ +libc_hidden_data_def(__stdin) #endif #ifdef __STDIO_PUTC_MACRO FILE *__stdout = _stdio_streams + 1; /* For putchar() macro. */ @@ -156,6 +164,7 @@ FILE *__stdout = _stdio_streams + 1; /* For putchar() macro. */ */ FILE *_stdio_openlist = _stdio_streams; +libc_hidden_data_def(_stdio_openlist) # ifdef __UCLIBC_HAS_THREADS__ # ifdef __USE_STDIO_FUTEXES__ @@ -164,6 +173,7 @@ _IO_lock_t _stdio_openlist_lock = _IO_lock_initializer; # else pthread_mutex_t _stdio_openlist_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; # endif +libc_hidden_data_def(_stdio_openlist_lock) int _stdio_openlist_delflag = 0; # endif @@ -172,7 +182,9 @@ int _stdio_openlist_delflag = 0; #ifdef __UCLIBC_HAS_THREADS__ /* 2 if threading not initialized and 0 otherwise; */ +libc_hidden_proto(_stdio_user_locking) int _stdio_user_locking = 2; +libc_hidden_data_def(_stdio_user_locking) #ifndef __USE_STDIO_FUTEXES__ void attribute_hidden __stdio_init_mutex(pthread_mutex_t *m) @@ -180,7 +192,7 @@ void attribute_hidden __stdio_init_mutex(pthread_mutex_t *m) static const pthread_mutex_t __stdio_mutex_initializer = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; - __memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer)); + memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer)); } #endif @@ -258,6 +270,7 @@ void attribute_hidden _stdio_term(void) #endif } +#if defined __STDIO_BUFFERS || !defined __UCLIBC__ void attribute_hidden _stdio_init(void) { #ifdef __STDIO_BUFFERS @@ -271,8 +284,9 @@ void attribute_hidden _stdio_init(void) /* _stdio_term is done automatically when exiting if stdio is used. * See misc/internals/__uClibc_main.c and and stdlib/atexit.c. */ atexit(_stdio_term); -#endif /* __UCLIBC__ */ +#endif } +#endif /**********************************************************************/ diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h index 50229ffb0..83d43352b 100644 --- a/libc/stdio/_stdio.h +++ b/libc/stdio/_stdio.h @@ -5,8 +5,6 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define _GNU_SOURCE - #include <features.h> #include <assert.h> #include <errno.h> @@ -18,51 +16,19 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> - -extern int __vfprintf (FILE *__restrict __s, __const char *__restrict __format, - __gnuc_va_list __arg) attribute_hidden; - -extern int __vsnprintf (char *__restrict __s, size_t __maxlen, - __const char *__restrict __format, __gnuc_va_list __arg) - __THROW __attribute__ ((__format__ (__printf__, 3, 0))) attribute_hidden; - -extern int __vfscanf (FILE *__restrict __s, __const char *__restrict __format, - __gnuc_va_list __arg) - __attribute__ ((__format__ (__scanf__, 2, 0))) attribute_hidden; - -extern int __vsscanf (__const char *__restrict __s, - __const char *__restrict __format, __gnuc_va_list __arg) - __THROW __attribute__ ((__format__ (__scanf__, 2, 0))) attribute_hidden; - #ifdef __UCLIBC_HAS_WCHAR__ #include <wchar.h> +#endif -extern int __vfwprintf (__FILE *__restrict __s, - __const wchar_t *__restrict __format, - __gnuc_va_list __arg) attribute_hidden; - -extern int __vfwscanf (__FILE *__restrict __s, - __const wchar_t *__restrict __format, - __gnuc_va_list __arg) attribute_hidden; +libc_hidden_proto(stdin) +libc_hidden_proto(stdout) -extern int __vswscanf (__const wchar_t *__restrict __s, - __const wchar_t *__restrict __format, - __gnuc_va_list __arg) __THROW attribute_hidden; -#endif +libc_hidden_proto(_stdio_openlist) #ifdef __UCLIBC_HAS_THREADS__ #include <pthread.h> +libc_hidden_proto(_stdio_openlist_lock) -#ifdef __USE_STDIO_FUTEXES___ -#define __STDIO_THREADLOCK_OPENLIST \ - _IO_lock_lock(_stdio_openlist_lock) - -#define __STDIO_THREADUNLOCK_OPENLIST \ - _IO_lock_unlock(_stdio_openlist_lock) - -#define __STDIO_THREADTRYLOCK_OPENLIST \ - _IO_lock_trylock(_stdio_openlist_lock) -#else #define __STDIO_THREADLOCK_OPENLIST \ __pthread_mutex_lock(&_stdio_openlist_lock) @@ -71,9 +37,6 @@ extern int __vswscanf (__const wchar_t *__restrict __s, #define __STDIO_THREADTRYLOCK_OPENLIST \ __pthread_mutex_trylock(&_stdio_openlist_lock) -#endif - - #else @@ -300,8 +263,6 @@ extern int __stdio_trans2w(FILE *__restrict stream) attribute_hidden; extern int __stdio_trans2r_o(FILE *__restrict stream, int oflag) attribute_hidden; extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidden; -extern int __setvbuf (FILE *__restrict __stream, char *__restrict __buf, - int __modes, size_t __n) __THROW attribute_hidden; /**********************************************************************/ #ifdef __STDIO_BUFFERS @@ -389,46 +350,11 @@ extern int __setvbuf (FILE *__restrict __stream, char *__restrict __buf, #endif /* __STDIO_BUFFERS */ /**********************************************************************/ -extern int __fputs_unlocked(const char *__restrict s, FILE *__restrict stream) attribute_hidden; - -extern int __putchar_unlocked(int c); - - -extern size_t __fwrite_unlocked(const void *__restrict ptr, size_t size, - size_t nmemb, FILE *__restrict stream) attribute_hidden; - -extern size_t __fread_unlocked(void *__restrict ptr, size_t size, - size_t nmemb, FILE *__restrict stream) attribute_hidden; - -extern int __fputc_unlocked_internal(int c, FILE *stream) attribute_hidden; - -extern int __fflush_unlocked(FILE *stream) attribute_hidden; - extern int __stdio_adjust_position(FILE *__restrict stream, __offmax_t *pos) attribute_hidden; -extern void __clearerr_unlocked(FILE *stream); -extern int __feof_unlocked(FILE *stream); -extern int __ferror_unlocked(FILE *stream); - -extern int __fgetc_unlocked_internal(FILE *stream) attribute_hidden; -extern int __getc_unlocked(FILE *stream) attribute_hidden; -extern char *__fgets_unlocked(char *__restrict s, int n, - FILE * __restrict stream) attribute_hidden; - -extern int __fileno_unlocked(FILE *stream) attribute_hidden; - -extern int __getchar_unlocked(void) attribute_hidden; - -extern int __fseek(FILE *stream, long int offset, int whence) attribute_hidden; -extern long int __ftell(FILE *stream) attribute_hidden; -#ifdef __UCLIBC_HAS_LFS__ -extern int __fseeko64(FILE *stream, __off64_t offset, int whence) attribute_hidden; -extern __off64_t __ftello64(FILE *stream) attribute_hidden; -#endif - #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 @@ -451,14 +377,6 @@ extern void _stdio_validate_FILE(const FILE *stream); /**********************************************************************/ -extern int _stdio_adjpos(FILE *__restrict stream, __offmax_t * pos); -extern int _stdio_lseek(FILE *stream, __offmax_t *pos, int whence); - -extern size_t _stdio_fwrite(const unsigned char *buffer, size_t bytes, - FILE *stream); -extern size_t _stdio_fread(unsigned char *buffer, size_t bytes, - FILE *stream); - extern FILE *_stdio_fopen(intptr_t fname_or_mode, const char *__restrict mode, FILE *__restrict stream, int filedes) attribute_hidden; @@ -466,9 +384,6 @@ extern FILE *_stdio_fopen(intptr_t fname_or_mode, #ifdef __UCLIBC_HAS_WCHAR__ extern size_t _wstdio_fwrite(const wchar_t *__restrict ws, size_t n, FILE *__restrict stream) attribute_hidden; - -extern wint_t __fgetwc_unlocked(register FILE *stream) attribute_hidden; -extern wint_t __fputwc_unlocked(wchar_t wc, FILE *stream) attribute_hidden; #endif /**********************************************************************/ diff --git a/libc/stdio/_store_inttype.c b/libc/stdio/_store_inttype.c index 82fb894c6..6eb74fe86 100644 --- a/libc/stdio/_store_inttype.c +++ b/libc/stdio/_store_inttype.c @@ -28,7 +28,8 @@ /* We assume int may be short or long, but short and long are different. */ -void attribute_hidden _store_inttype(register void *dest, int desttype, uintmax_t val) +void _store_inttype(register void *dest, int desttype, uintmax_t val) attribute_hidden; +void _store_inttype(register void *dest, int desttype, uintmax_t val) { if (desttype == __PA_FLAG_CHAR) { /* assume char not int */ *((unsigned char *) dest) = val; diff --git a/libc/stdio/_trans2w.c b/libc/stdio/_trans2w.c index 650a5e1a0..ed1a583fc 100644 --- a/libc/stdio/_trans2w.c +++ b/libc/stdio/_trans2w.c @@ -7,6 +7,8 @@ #include "_stdio.h" +libc_hidden_proto(fseek) + /* Function to handle transition to writing. * Initialize or verify the stream's orientation (even if readonly). * Check that the stream is writable. @@ -64,7 +66,7 @@ int attribute_hidden __stdio_trans2w(FILE * __restrict stream) * the end even if not reading.*/ if (((__STDIO_STREAM_BUFFER_RAVAIL(stream)) || (stream->__modeflags & __FLAG_UNGOT)) - && __fseek(stream, 0L, + && fseek(stream, 0L, ((stream->__modeflags & __FLAG_APPEND) ? SEEK_END : SEEK_CUR)) ) { diff --git a/libc/stdio/_uintmaxtostr.c b/libc/stdio/_uintmaxtostr.c index bf92506d5..f9c83506e 100644 --- a/libc/stdio/_uintmaxtostr.c +++ b/libc/stdio/_uintmaxtostr.c @@ -11,6 +11,11 @@ #include <locale.h> #include <bits/uClibc_uintmaxtostr.h> +libc_hidden_proto(memcpy) +#ifdef __UCLIBC_HAS_LOCALE__ +libc_hidden_proto(__global_locale) +#endif + /* Avoid using long long / and % operations to cut down dependencies on * libgcc.a. Definitely helps on i386 at least. */ #if (INTMAX_MAX > INT_MAX) && (((INTMAX_MAX/INT_MAX)/2) - 2 <= INT_MAX) @@ -61,7 +66,7 @@ char attribute_hidden *_uintmaxtostr(register char * __restrict bufend, uintmax_ #ifndef __LOCALE_C_ONLY if (!grouping) { /* Finished a group. */ bufend -= __UCLIBC_CURLOCALE_DATA.thousands_sep_len; - __memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep, + 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 @@ -79,7 +84,7 @@ char attribute_hidden *_uintmaxtostr(register char * __restrict bufend, uintmax_ #ifndef __LOCALE_C_ONLY if (unlikely(outdigit)) { bufend -= __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]; - __memcpy(bufend, + memcpy(bufend, (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit], __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]); } else @@ -104,7 +109,7 @@ char attribute_hidden *_uintmaxtostr(register char * __restrict bufend, uintmax_ #ifndef __LOCALE_C_ONLY if (!grouping) { /* Finished a group. */ bufend -= __UCLIBC_CURLOCALE_DATA.thousands_sep_len; - __memcpy(bufend, __UCLIBC_CURLOCALE_DATA.thousands_sep, + 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 @@ -131,7 +136,7 @@ char attribute_hidden *_uintmaxtostr(register char * __restrict bufend, uintmax_ #ifndef __LOCALE_C_ONLY if (unlikely(outdigit)) { bufend -= __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]; - __memcpy(bufend, + memcpy(bufend, (&__UCLIBC_CURLOCALE_DATA.outdigit0_mb)[digit], __UCLIBC_CURLOCALE_DATA.outdigit_length[digit]); } else diff --git a/libc/stdio/_vfprintf.c b/libc/stdio/_vfprintf.c new file mode 100644 index 000000000..a32960f2e --- /dev/null +++ b/libc/stdio/_vfprintf.c @@ -0,0 +1,1951 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * My stdio library for linux and (soon) elks. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This code needs a lot of clean up. Some of that is on hold until uClibc + * gets a better configuration system (on Erik's todo list). + * The other cleanup will take place during the implementation/integration of + * the wide char (un)formatted i/o functions which I'm currently working on. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * This code is currently under development. Also, I plan to port + * it to elks which is a 16-bit environment with a fairly limited + * compiler. Therefore, please refrain from modifying this code + * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + + +/* April 1, 2002 + * Initialize thread locks for fake files in vsnprintf and vdprintf. + * reported by Erik Andersen (andersen@codepoet.com) + * Fix an arg promotion handling bug in _do_one_spec for %c. + * reported by Ilguiz Latypov <ilatypov@superbt.com> + * + * May 10, 2002 + * Remove __isdigit and use new ctype.h version. + * Add conditional setting of QUAL_CHARS for size_t and ptrdiff_t. + * + * Aug 16, 2002 + * Fix two problems that showed up with the python 2.2.1 tests; one + * involving %o and one involving %f. + * + * Oct 28, 2002 + * Fix a problem in vasprintf (reported by vodz a while back) when built + * without custom stream support. In that case, it is necessary to do + * a va_copy. + * Make sure each va_copy has a matching va_end, as required by C99. + * + * Nov 4, 2002 + * Add locale-specific grouping support for integer decimal conversion. + * Add locale-specific decimal point support for floating point conversion. + * Note: grouping will have to wait for _dtostr() rewrite. + * Add printf wchar support for %lc (%C) and %ls (%S). + * Require printf format strings to be valid multibyte strings beginning and + * ending in their initial shift state, as per the stds. + * + * Nov 21, 2002 + * Add *wprintf functions. Currently they don't support floating point + * conversions. That will wait until the rewrite of _dtostr. + * + * Aug 1, 2003 + * Optional hexadecimal float notation support for %a/%A. + * Floating point output now works for *wprintf. + * Support for glibc locale-specific digit grouping for floats. + * Misc bug fixes. + * + * Aug 31, 2003 + * Fix precision bug for %g conversion specifier when using %f style. + * + * Sep 5, 2003 + * Implement *s*scanf for the non-buffered stdio case with old_vfprintf. + * + * Sep 23, 2003 + * vfprintf was not always checking for narrow stream orientation. + */ + +/* TODO: + * + * Should we validate that *printf format strings are valid multibyte + * strings in the current locale? ANSI/ISO C99 seems to imply this + * and Plauger's printf implementation in his Standard C Library book + * treats this as an error. + */ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include <features.h> +#include "_stdio.h" +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <ctype.h> +#include <limits.h> +#include <stdarg.h> +#include <assert.h> +#include <stdint.h> +#include <errno.h> +#include <locale.h> + +#define __PRINTF_INFO_NO_BITFIELD +#include <printf.h> + +#ifdef __UCLIBC_HAS_THREADS__ +#include <stdio_ext.h> +#include <pthread.h> +#endif /* __UCLIBC_HAS_THREADS__ */ + +#ifdef __UCLIBC_HAS_WCHAR__ +#include <wchar.h> +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#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) +libc_hidden_proto(__glibc_strerror_r) +libc_hidden_proto(fputs_unlocked) +libc_hidden_proto(abort) +#ifdef __UCLIBC_HAS_WCHAR__ +libc_hidden_proto(wcslen) +libc_hidden_proto(wcsnlen) +libc_hidden_proto(mbsrtowcs) +libc_hidden_proto(wcsrtombs) +libc_hidden_proto(btowc) +libc_hidden_proto(wcrtomb) +libc_hidden_proto(fputws) +#endif + +/* Some older or broken gcc toolchains define LONG_LONG_MAX but not + * LLONG_MAX. Since LLONG_MAX is part of the standard, that's what + * we use. So complain if we do not have it but should. + */ +#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX) +#error Apparently, LONG_LONG_MAX is defined but LLONG_MAX is not. You need to fix your toolchain headers to support the standard macros for (unsigned) long long. +#endif + +/**********************************************************************/ +/* These provide some control over printf's feature set */ + +/* This is undefined below depeding on uClibc's configuration. */ +#define __STDIO_PRINTF_FLOAT 1 + +/* Now controlled by uClibc_stdio.h. */ +/* #define __UCLIBC_HAS_PRINTF_M_SPEC__ */ + + +/**********************************************************************/ + +#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_FLOATS__) +#undef __STDIO_PRINTF_FLOAT +#endif + +#ifdef __BCC__ +#undef __STDIO_PRINTF_FLOAT +#endif + +#ifdef __STDIO_PRINTF_FLOAT +#include <float.h> +#include <bits/uClibc_fpmax.h> +#else /* __STDIO_PRINTF_FLOAT */ +#undef L__fpmaxtostr +#endif /* __STDIO_PRINTF_FLOAT */ + + +#undef __STDIO_HAS_VSNPRINTF +#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) +#define __STDIO_HAS_VSNPRINTF 1 +#endif + +/**********************************************************************/ + +/* Now controlled by uClibc_stdio.h. */ +/* #define __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +/* TODO -- move these to a configuration section? */ +#define MAX_FIELD_WIDTH 4095 + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_register_printf_function +/* emit only once */ +#warning WISHLIST: Make MAX_USER_SPEC configurable? +#warning WISHLIST: Make MAX_ARGS_PER_SPEC configurable? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + +#define MAX_USER_SPEC 10 +#define MAX_ARGS_PER_SPEC 5 + +#else /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +#undef MAX_USER_SPEC +#define MAX_ARGS_PER_SPEC 1 + +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +#if MAX_ARGS_PER_SPEC < 1 +#error MAX_ARGS_PER_SPEC < 1! +#undef MAX_ARGS_PER_SPEC +#define MAX_ARGS_PER_SPEC 1 +#endif + +#if defined(NL_ARGMAX) && (NL_ARGMAX < 9) +#error NL_ARGMAX < 9! +#endif + +#if defined(NL_ARGMAX) && (NL_ARGMAX >= (MAX_ARGS_PER_SPEC + 2)) +#define MAX_ARGS NL_ARGMAX +#else +/* N for spec itself, plus 1 each for width and precision */ +#define MAX_ARGS (MAX_ARGS_PER_SPEC + 2) +#endif + +/**********************************************************************/ + +#define __PA_FLAG_INTMASK \ + (__PA_FLAG_CHAR|PA_FLAG_SHORT|__PA_FLAG_INT|PA_FLAG_LONG|PA_FLAG_LONG_LONG) + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +extern printf_function _custom_printf_handler[MAX_USER_SPEC] attribute_hidden; +extern printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC] attribute_hidden; +extern char *_custom_printf_spec attribute_hidden; +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +/**********************************************************************/ + +#define SPEC_FLAGS " +0-#'I" +enum { + FLAG_SPACE = 0x01, + FLAG_PLUS = 0x02, /* must be 2 * FLAG_SPACE */ + FLAG_ZERO = 0x04, + FLAG_MINUS = 0x08, /* must be 2 * FLAG_ZERO */ + FLAG_HASH = 0x10, + FLAG_THOUSANDS = 0x20, + FLAG_I18N = 0x40, /* only works for d, i, u */ + FLAG_WIDESTREAM = 0x80 +}; + +/**********************************************************************/ + +/* float layout 01234567890123456789 TODO: B?*/ +#define SPEC_CHARS "npxXoudifFeEgGaACScs" +enum { + CONV_n = 0, + CONV_p, + CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i, + CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A, + CONV_C, CONV_S, CONV_c, CONV_s, +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + CONV_m, +#endif + CONV_custom0 /* must be last */ +}; + +/* p x X o u d i */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 10 } + +#define SPEC_RANGES { CONV_n, CONV_p, CONV_i, CONV_A, \ + CONV_C, CONV_S, CONV_c, CONV_s, CONV_custom0 } + +#define SPEC_OR_MASK { \ + /* n */ (PA_FLAG_PTR|PA_INT), \ + /* p */ PA_POINTER, \ + /* oxXudi */ PA_INT, \ + /* fFeEgGaA */ PA_DOUBLE, \ + /* C */ PA_WCHAR, \ + /* S */ PA_WSTRING, \ + /* c */ PA_CHAR, \ + /* s */ PA_STRING, \ +} + +#define SPEC_AND_MASK { \ + /* n */ (PA_FLAG_PTR|__PA_INTMASK), \ + /* p */ PA_POINTER, \ + /* oxXudi */ (__PA_INTMASK), \ + /* fFeEgGaA */ (PA_FLAG_LONG_DOUBLE|PA_DOUBLE), \ + /* C */ (PA_WCHAR), \ + /* S */ (PA_WSTRING), \ + /* c */ (PA_CHAR), \ + /* s */ (PA_STRING), \ +} + +/**********************************************************************/ +/* + * In order to ease translation to what arginfo and _print_info._flags expect, + * we map: 0:int 1:char 2:longlong 4:long 8:short + * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) + */ + +/* TODO -- Fix the table below to take into account stdint.h. */ +/* #ifndef LLONG_MAX */ +/* #error fix QUAL_CHARS for no long long! Affects 'L', 'j', 'q', 'll'. */ +/* #else */ +/* #if LLONG_MAX != INTMAX_MAX */ +/* #error fix QUAL_CHARS intmax_t entry 'j'! */ +/* #endif */ +/* #endif */ + +#ifdef PDS +#error PDS already defined! +#endif +#ifdef SS +#error SS already defined! +#endif +#ifdef IMS +#error IMS already defined! +#endif + +#if PTRDIFF_MAX == INT_MAX +#define PDS 0 +#elif PTRDIFF_MAX == LONG_MAX +#define PDS 4 +#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) +#define PDS 8 +#else +#error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#if SIZE_MAX == UINT_MAX +#define SS 0 +#elif SIZE_MAX == ULONG_MAX +#define SS 4 +#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) +#define SS 8 +#else +#error fix QUAL_CHARS size_t entries 'z', 'Z'! +#endif + +#if INTMAX_MAX == INT_MAX +#define IMS 0 +#elif INTMAX_MAX == LONG_MAX +#define IMS 4 +#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) +#define IMS 8 +#else +#error fix QUAL_CHARS intmax_t entry 'j'! +#endif + +#define QUAL_CHARS { \ + /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int */ \ + /* q:long_long Z:(s)size_t */ \ + 'h', 'l', 'L', 'j', 'z', 't', 'q', 'Z', 0, \ + 2, 4, 8, IMS, SS, PDS, 8, SS, 0, /* TODO -- fix!!! */\ + 1, 8 \ +} + +/**********************************************************************/ + +#ifdef __STDIO_VA_ARG_PTR +#ifdef __BCC__ +#define __va_arg_ptr(ap,type) (((type *)(ap += sizeof(type))) - 1) +#endif + +#if 1 +#ifdef __GNUC__ +/* TODO -- need other than for 386 as well! */ + +#ifndef __va_rounded_size +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +#endif +#define __va_arg_ptr(AP, TYPE) \ + (AP = (va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ + ((void *) ((char *) (AP) - __va_rounded_size (TYPE)))) +#endif +#endif +#endif /* __STDIO_VA_ARG_PTR */ + +#ifdef __va_arg_ptr +#define GET_VA_ARG(AP,F,TYPE,ARGS) (*(AP) = __va_arg_ptr(ARGS,TYPE)) +#define GET_ARG_VALUE(AP,F,TYPE) (*((TYPE *)(*(AP)))) +#else +typedef union { + wchar_t wc; + unsigned int u; + unsigned long ul; +#ifdef ULLONG_MAX + unsigned long long ull; +#endif +#ifdef __STDIO_PRINTF_FLOAT + double d; + long double ld; +#endif /* __STDIO_PRINTF_FLOAT */ + void *p; +} argvalue_t; + +#define GET_VA_ARG(AU,F,TYPE,ARGS) (AU->F = va_arg(ARGS,TYPE)) +#define GET_ARG_VALUE(AU,F,TYPE) ((TYPE)((AU)->F)) +#endif + +typedef struct { + const char *fmtpos; /* TODO: move below struct?? */ + struct printf_info info; +#ifdef NL_ARGMAX + int maxposarg; /* > 0 if args are positional, 0 if not, -1 if unknown */ +#endif /* NL_ARGMAX */ + int num_data_args; /* TODO: use sentinal??? */ + unsigned int conv_num; + unsigned char argnumber[4]; /* width | prec | 1st data | unused */ + int argtype[MAX_ARGS]; + va_list arg; +#ifdef __va_arg_ptr + void *argptr[MAX_ARGS]; +#else +/* if defined(NL_ARGMAX) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__) */ + /* While this is wasteful of space in the case where pos args aren't + * enabled, it is also needed to support custom printf handlers. */ + argvalue_t argvalue[MAX_ARGS]; +#endif +} ppfs_t; /* parse printf format state */ + +/**********************************************************************/ + +/* TODO: fix printf to return 0 and set errno if format error. Standard says + only returns -1 if sets error indicator for the stream. */ + +#ifdef __STDIO_PRINTF_FLOAT +typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); + +extern ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) attribute_hidden; +#endif + +extern int _ppfs_init(ppfs_t *ppfs, const char *fmt0) attribute_hidden; /* validates */ +extern void _ppfs_prepargs(ppfs_t *ppfs, va_list arg) attribute_hidden; /* sets posargptrs */ +extern void _ppfs_setargs(ppfs_t *ppfs) attribute_hidden; /* sets argptrs for current spec */ +extern int _ppfs_parsespec(ppfs_t *ppfs) attribute_hidden; /* parses specifier */ + +extern void _store_inttype(void *dest, int desttype, uintmax_t val) attribute_hidden; +extern uintmax_t _load_inttype(int desttype, const void *src, int uflag) attribute_hidden; + +/**********************************************************************/ +#ifdef L_parse_printf_format + +/* NOTE: This function differs from the glibc version in that parsing stops + * upon encountering an invalid conversion specifier. Since this is the way + * my printf functions work, I think it makes sense to do it that way here. + * Unfortunately, since glibc sets the return type as size_t, we have no way + * of returning that the template is illegal, other than returning 0. + */ + +size_t parse_printf_format(register const char *template, + size_t n, register int *argtypes) +{ + ppfs_t ppfs; + size_t i; + size_t count = 0; + + if (_ppfs_init(&ppfs, template) >= 0) { +#ifdef NL_ARGMAX + if (ppfs.maxposarg > 0) { /* Using positional args. */ + count = ppfs.maxposarg; + if (n > count) { + n = count; + } + for (i = 0 ; i < n ; i++) { + *argtypes++ = ppfs.argtype[i]; + } + } else { /* Not using positional args. */ +#endif /* NL_ARGMAX */ + while (*template) { + if ((*template == '%') && (*++template != '%')) { + ppfs.fmtpos = template; + _ppfs_parsespec(&ppfs); /* Can't fail. */ + template = ppfs.fmtpos; /* Update to one past spec end. */ + if (ppfs.info.width == INT_MIN) { + ++count; + if (n > 0) { + *argtypes++ = PA_INT; + --n; + } + } + if (ppfs.info.prec == INT_MIN) { + ++count; + if (n > 0) { + *argtypes++ = PA_INT; + --n; + } + } + for (i = 0 ; i < ppfs.num_data_args ; i++) { + if ((ppfs.argtype[i]) != __PA_NOARG) { + ++count; + if (n > 0) { + *argtypes++ = ppfs.argtype[i]; + --n; + } + } + } + } else { + ++template; + } + } +#ifdef NL_ARGMAX + } +#endif /* NL_ARGMAX */ + } + + return count; +} + +#endif +/**********************************************************************/ +#ifdef L__ppfs_init + +#ifdef __UCLIBC_HAS_LOCALE__ +libc_hidden_proto(__global_locale) +#endif + +int attribute_hidden _ppfs_init(register ppfs_t *ppfs, const char *fmt0) +{ + int r; + + /* First, zero out everything... argnumber[], argtype[], argptr[] */ + memset(ppfs, 0, sizeof(ppfs_t)); /* TODO: nonportable???? */ +#ifdef NL_ARGMAX + --ppfs->maxposarg; /* set to -1 */ +#endif /* NL_ARGMAX */ + ppfs->fmtpos = fmt0; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Make checking of the format string in C locale an option. +#endif +#ifdef __UCLIBC_HAS_LOCALE__ + /* To support old programs, don't check mb validity if in C locale. */ + if (((__UCLIBC_CURLOCALE_DATA).encoding) != __ctype_encoding_7_bit) { + /* ANSI/ISO C99 requires format string to be a valid multibyte string + * beginning and ending in its initial shift state. */ + static const char invalid_mbs[] = "Invalid multibyte format string."; + mbstate_t mbstate; + const char *p; + mbstate.__mask = 0; /* Initialize the mbstate. */ + p = fmt0; + if (mbsrtowcs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { + ppfs->fmtpos = invalid_mbs; + return -1; + } + } +#endif /* __UCLIBC_HAS_LOCALE__ */ + /* now set all argtypes to no-arg */ + { +#if 1 + /* TODO - use memset here since already "paid for"? */ + register int *p = ppfs->argtype; + + r = MAX_ARGS; + do { + *p++ = __PA_NOARG; + } while (--r); +#else + /* TODO -- get rid of this?? */ + register char *p = (char *) ((MAX_ARGS-1) * sizeof(int)); + + do { + *((int *)(((char *)ppfs) + ((int)p) + offsetof(ppfs_t,argtype))) = __PA_NOARG; + p -= sizeof(int); + } while (p); +#endif + } + + /* + * Run through the entire format string to validate it and initialize + * the positional arg numbers (if any). + */ + { + register const char *fmt = fmt0; + + while (*fmt) { + if ((*fmt == '%') && (*++fmt != '%')) { + ppfs->fmtpos = fmt; /* back up to the '%' */ + if ((r = _ppfs_parsespec(ppfs)) < 0) { + return -1; + } + fmt = ppfs->fmtpos; /* update to one past end of spec */ + } else { + ++fmt; + } + } + ppfs->fmtpos = fmt0; /* rewind */ + } + +#ifdef NL_MAX_ARG + /* If we have positional args, make sure we know all the types. */ + { + register int *p = ppfs->argtype; + r = ppfs->maxposarg; + while (--r >= 0) { + if ( *p == __PA_NOARG ) { /* missing arg type!!! */ + return -1; + } + ++p; + } + } +#endif /* NL_MAX_ARG */ + + return 0; +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_prepargs +void attribute_hidden _ppfs_prepargs(register ppfs_t *ppfs, va_list arg) +{ + int i; + + va_copy(ppfs->arg, arg); + +#ifdef NL_ARGMAX + if ((i = ppfs->maxposarg) > 0) { /* init for positional args */ + ppfs->num_data_args = i; + ppfs->info.width = ppfs->info.prec = ppfs->maxposarg = 0; + _ppfs_setargs(ppfs); + ppfs->maxposarg = i; + } +#endif /* NL_ARGMAX */ +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_setargs + +void attribute_hidden _ppfs_setargs(register ppfs_t *ppfs) +{ +#ifdef __va_arg_ptr + register void **p = ppfs->argptr; +#else + register argvalue_t *p = ppfs->argvalue; +#endif + int i; + +#ifdef NL_ARGMAX + if (ppfs->maxposarg == 0) { /* initing for or no pos args */ +#endif /* NL_ARGMAX */ + if (ppfs->info.width == INT_MIN) { + ppfs->info.width = +#ifdef __va_arg_ptr + *(int *) +#endif + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + } + if (ppfs->info.prec == INT_MIN) { + ppfs->info.prec = +#ifdef __va_arg_ptr + *(int *) +#endif + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + } + i = 0; + while (i < ppfs->num_data_args) { + switch(ppfs->argtype[i++]) { + case (PA_INT|PA_FLAG_LONG_LONG): +#ifdef ULLONG_MAX + GET_VA_ARG(p,ull,unsigned long long,ppfs->arg); + break; +#endif + case (PA_INT|PA_FLAG_LONG): +#if ULONG_MAX != UINT_MAX + GET_VA_ARG(p,ul,unsigned long,ppfs->arg); + break; +#endif + case PA_CHAR: /* TODO - be careful */ + /* ... users could use above and really want below!! */ + case (PA_INT|__PA_FLAG_CHAR):/* TODO -- translate this!!! */ + case (PA_INT|PA_FLAG_SHORT): + case PA_INT: + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + break; + case PA_WCHAR: /* TODO -- assume int? */ + /* we're assuming wchar_t is at least an int */ + GET_VA_ARG(p,wc,wchar_t,ppfs->arg); + break; +#ifdef __STDIO_PRINTF_FLOAT + /* PA_FLOAT */ + case PA_DOUBLE: + GET_VA_ARG(p,d,double,ppfs->arg); + break; + case (PA_DOUBLE|PA_FLAG_LONG_DOUBLE): + GET_VA_ARG(p,ld,long double,ppfs->arg); + break; +#else /* __STDIO_PRINTF_FLOAT */ + case PA_DOUBLE: + case (PA_DOUBLE|PA_FLAG_LONG_DOUBLE): + assert(0); + continue; +#endif /* __STDIO_PRINTF_FLOAT */ + default: + /* TODO -- really need to ensure this can't happen */ + assert(ppfs->argtype[i-1] & PA_FLAG_PTR); + case PA_POINTER: + case PA_STRING: + case PA_WSTRING: + GET_VA_ARG(p,p,void *,ppfs->arg); + break; + case __PA_NOARG: + continue; + } + ++p; + } +#ifdef NL_ARGMAX + } else { + if (ppfs->info.width == INT_MIN) { + ppfs->info.width + = (int) GET_ARG_VALUE(p + ppfs->argnumber[0] - 1,u,unsigned int); + } + if (ppfs->info.prec == INT_MIN) { + ppfs->info.prec + = (int) GET_ARG_VALUE(p + ppfs->argnumber[1] - 1,u,unsigned int); + } + } +#endif /* NL_ARGMAX */ + + /* Now we know the width and precision. */ + if (ppfs->info.width < 0) { + ppfs->info.width = -ppfs->info.width; + PRINT_INFO_SET_FLAG(&(ppfs->info),left); + PRINT_INFO_CLR_FLAG(&(ppfs->info),space); + ppfs->info.pad = ' '; + } +#if 0 + /* NOTE -- keep neg for now so float knows! */ + if (ppfs->info.prec < 0) { /* spec says treat as omitted. */ + /* so use default prec... 1 for everything but floats and strings. */ + ppfs->info.prec = 1; + } +#endif +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_parsespec + +#ifdef __UCLIBC_HAS_XLOCALE__ +libc_hidden_proto(__ctype_b_loc) +#else +libc_hidden_proto(__ctype_b) +#endif + +/* Notes: argtype differs from glibc for the following: + * mine glibc + * lc PA_WCHAR PA_CHAR the standard says %lc means %C + * ls PA_WSTRING PA_STRING the standard says %ls means %S + * {*}n {*}|PA_FLAG_PTR PA_FLAG_PTR size of n can be qualified + */ + +/* TODO: store positions of positional args */ + +/* TODO -- WARNING -- assumes aligned on integer boundaries!!! */ + +/* TODO -- disable if not using positional args!!! */ +#define _OVERLAPPING_DIFFERENT_ARGS + +/* TODO -- rethink this -- perhaps we should set to largest type??? */ + +#ifdef _OVERLAPPING_DIFFERENT_ARGS + +#define PROMOTED_SIZE_OF(X) ((sizeof(X) + sizeof(int) - 1) / sizeof(X)) + +static const short int type_codes[] = { + __PA_NOARG, /* must be first entry */ + PA_POINTER, + PA_STRING, + PA_WSTRING, + PA_CHAR, + PA_INT|PA_FLAG_SHORT, + PA_INT, + PA_INT|PA_FLAG_LONG, + PA_INT|PA_FLAG_LONG_LONG, + PA_WCHAR, +#ifdef __STDIO_PRINTF_FLOAT + /* PA_FLOAT, */ + PA_DOUBLE, + PA_DOUBLE|PA_FLAG_LONG_DOUBLE, +#endif /* __STDIO_PRINTF_FLOAT */ +}; + +static const unsigned char type_sizes[] = { + /* unknown type consumes no arg */ + 0, /* must be first entry */ + PROMOTED_SIZE_OF(void *), + PROMOTED_SIZE_OF(char *), + PROMOTED_SIZE_OF(wchar_t *), + PROMOTED_SIZE_OF(char), + PROMOTED_SIZE_OF(short), + PROMOTED_SIZE_OF(int), + PROMOTED_SIZE_OF(long), +#ifdef ULLONG_MAX + PROMOTED_SIZE_OF(long long), +#else + PROMOTED_SIZE_OF(long), /* TODO -- is this correct? (above too) */ +#endif + PROMOTED_SIZE_OF(wchar_t), +#ifdef __STDIO_PRINTF_FLOAT + /* PROMOTED_SIZE_OF(float), */ + PROMOTED_SIZE_OF(double), + PROMOTED_SIZE_OF(long double), +#endif /* __STDIO_PRINTF_FLOAT */ +}; + +static int _promoted_size(int argtype) +{ + register const short int *p; + + /* note -- since any unrecognized type is treated as a pointer */ + p = type_codes + sizeof(type_codes)/sizeof(type_codes[0]); + do { + if (*--p == argtype) { + break; + } + } while (p > type_codes); + + return type_sizes[(int)(p - type_codes)]; +} + +static int _is_equal_or_bigger_arg(int curtype, int newtype) +{ + /* Quick test */ + if (newtype == __PA_NOARG) { + return 0; + } + if ((curtype == __PA_NOARG) || (curtype == newtype)) { + return 1; + } + /* Ok... slot is already filled and types are different in name. */ + /* So, compare promoted sizes of curtype and newtype args. */ + return _promoted_size(curtype) <= _promoted_size(newtype); +} + +#else + +#define _is_equal_or_bigger_arg(C,N) (((C) == __PA_NOARG) || ((C) == (N))) + +#endif + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +/* TODO - do this differently? */ +static char _bss_custom_printf_spec[MAX_USER_SPEC]; /* 0-init'd for us. */ + +attribute_hidden char *_custom_printf_spec = _bss_custom_printf_spec; +attribute_hidden printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC]; +attribute_hidden printf_function _custom_printf_handler[MAX_USER_SPEC]; +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +int attribute_hidden _ppfs_parsespec(ppfs_t *ppfs) +{ + register const char *fmt; + register const char *p; + int preci; + int width; + int flags; + int dataargtype; + int i; + int dpoint; +#ifdef NL_ARGMAX + int maxposarg; +#endif /* NL_ARGMAX */ + int p_m_spec_chars; + int n; + int argtype[MAX_ARGS_PER_SPEC+2]; + int argnumber[3]; /* width, precision, 1st data arg */ + static const char spec_flags[] = SPEC_FLAGS; + static const char spec_chars[] = SPEC_CHARS;/* TODO: b? */ + static const char spec_ranges[] = SPEC_RANGES; + static const short spec_or_mask[] = SPEC_OR_MASK; + static const short spec_and_mask[] = SPEC_AND_MASK; + static const char qual_chars[] = QUAL_CHARS; +#ifdef __UCLIBC_HAS_WCHAR__ + char buf[32]; +#endif /* __UCLIBC_HAS_WCHAR__ */ + + /* WIDE note: we can test against '%' here since we don't allow */ + /* WIDE note: other mappings of '%' in the wide char set. */ + preci = -1; + argnumber[0] = 0; + argnumber[1] = 0; + argtype[0] = __PA_NOARG; + argtype[1] = __PA_NOARG; +#ifdef NL_ARGMAX + maxposarg = ppfs->maxposarg; +#endif /* NL_ARGMAX */ + +#ifdef __UCLIBC_HAS_WCHAR__ + /* This is somewhat lame, but saves a lot of code. If we're dealing with + * a wide stream, that means the format is a wchar string. So, copy it + * char-by-char into a normal char buffer for processing. Make the buffer + * (buf) big enough so that any reasonable format specifier will fit. + * While there a legal specifiers that won't, the all involve duplicate + * flags or outrageous field widths/precisions. */ + width = dpoint = 0; + if ((flags = ppfs->info._flags & FLAG_WIDESTREAM) == 0) { + fmt = ppfs->fmtpos; + } else { + fmt = buf + 1; + i = 0; + do { + if ((buf[i] = (char) (((wchar_t *) ppfs->fmtpos)[i-1])) + != (((wchar_t *) ppfs->fmtpos)[i-1]) + ) { + return -1; + } + } while (buf[i++]); + buf[sizeof(buf)-1] = 0; + } +#else /* __UCLIBC_HAS_WCHAR__ */ + width = flags = dpoint = 0; + fmt = ppfs->fmtpos; +#endif /* __UCLIBC_HAS_WCHAR__ */ + + assert(fmt[-1] == '%'); + assert(fmt[0] != '%'); + + /* Process arg pos and/or flags and/or width and/or precision. */ + width_precision: + p = fmt; + if (*fmt == '*') { + argtype[-dpoint] = PA_INT; + ++fmt; + } + i = 0; + while (isdigit(*fmt)) { + if (i < MAX_FIELD_WIDTH) { /* Avoid overflow. */ + i = (i * 10) + (*fmt - '0'); + } + ++fmt; + } + if (p[-1] == '%') { /* Check for a position. */ + + /* TODO: if val not in range, then error */ + +#ifdef NL_ARGMAX + if ((*fmt == '$') && (i > 0)) {/* Positional spec. */ + ++fmt; + if (maxposarg == 0) { + return -1; + } + if ((argnumber[2] = i) > maxposarg) { + maxposarg = i; + } + /* Now fall through to check flags. */ + } else { + if (maxposarg > 0) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Support prec and width for %m when positional args used + /* Actually, positional arg processing will fail in general + * for specifiers that don't require an arg. */ +#endif /* __UCLIBC_MJN3_ONLY__ */ + if (*fmt == 'm') { + goto PREC_WIDTH; + } +#endif /* __UCLIBC_HAS_PRINTF_M_SPEC__ */ + return -1; + } + maxposarg = 0; /* Possible redundant store, but cuts size. */ + + if ((fmt > p) && (*p != '0')) { + goto PREC_WIDTH; + } + + fmt = p; /* Back up for possible '0's flag. */ + /* Now fall through to check flags. */ + } +#else /* NL_ARGMAX */ + if (*fmt == '$') { /* Positional spec. */ + return -1; + } + + if ((fmt > p) && (*p != '0')) { + goto PREC_WIDTH; + } + + fmt = p; /* Back up for possible '0's flag. */ + /* Now fall through to check flags. */ +#endif /* NL_ARGMAX */ + + restart_flags: /* Process flags. */ + i = 1; + p = spec_flags; + + do { + if (*fmt == *p++) { + ++fmt; + flags |= i; + goto restart_flags; + } + i += i; /* Better than i <<= 1 for bcc */ + } while (*p); + i = 0; + + /* If '+' then ignore ' ', and if '-' then ignore '0'. */ + /* Note: Need to ignore '0' when prec is an arg with val < 0, */ + /* but that test needs to wait until the arg is retrieved. */ + flags &= ~((flags & (FLAG_PLUS|FLAG_MINUS)) >> 1); + /* Note: Ignore '0' when prec is specified < 0 too (in printf). */ + + if (fmt[-1] != '%') { /* If we've done anything, loop for width. */ + goto width_precision; + } + } + PREC_WIDTH: + if (*p == '*') { /* Prec or width takes an arg. */ +#ifdef NL_ARGMAX + if (maxposarg) { + if ((*fmt++ != '$') || (i <= 0)) { + /* Using pos args and no $ or invalid arg number. */ + return -1; + } + argnumber[-dpoint] = i; + } else +#endif /* NL_ARGMAX */ + if (++p != fmt) { + /* Not using pos args but digits followed *. */ + return -1; + } + i = INT_MIN; + } + + if (!dpoint) { + width = i; + if (*fmt == '.') { + ++fmt; + dpoint = -1; /* To use as default precison. */ + goto width_precision; + } + } else { + preci = i; + } + + /* Process qualifier. */ + p = qual_chars; + do { + if (*fmt == *p) { + ++fmt; + break; + } + } while (*++p); + if ((p - qual_chars < 2) && (*fmt == *p)) { + p += ((sizeof(qual_chars)-2) / 2); + ++fmt; + } + dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; + + /* Process conversion specifier. */ + if (!*fmt) { + return -1; + } + + p = spec_chars; + + do { + if (*fmt == *p) { + p_m_spec_chars = p - spec_chars; + + if ((p_m_spec_chars >= CONV_c) + && (dataargtype & PA_FLAG_LONG)) { + p_m_spec_chars -= 2; /* lc -> C and ls -> S */ + } + + ppfs->conv_num = p_m_spec_chars; + p = spec_ranges-1; + while (p_m_spec_chars > *++p) {} + + i = p - spec_ranges; + argtype[2] = (dataargtype | spec_or_mask[i]) & spec_and_mask[i]; + p = spec_chars; + break; + } + } while(*++p); + + ppfs->info.spec = *fmt; + ppfs->info.prec = preci; + ppfs->info.width = width; + ppfs->info.pad = ((flags & FLAG_ZERO) ? '0' : ' '); + ppfs->info._flags = (flags & ~FLAG_ZERO) | (dataargtype & __PA_INTMASK); + ppfs->num_data_args = 1; + + if (!*p) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + if (*fmt == 'm') { + ppfs->conv_num = CONV_m; + ppfs->num_data_args = 0; + goto DONE; + } +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + + /* Handle custom arg -- WARNING -- overwrites p!!! */ + ppfs->conv_num = CONV_custom0; + p = _custom_printf_spec; + do { + if (*p == *fmt) { + if ((ppfs->num_data_args + = ((*_custom_printf_arginfo[(int)(p-_custom_printf_spec)]) + (&(ppfs->info), MAX_ARGS_PER_SPEC, argtype+2))) + > MAX_ARGS_PER_SPEC) { + break; /* Error -- too many args! */ + } + goto DONE; + } + } while (++p < (_custom_printf_spec + MAX_USER_SPEC)); +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + /* Otherwise error. */ + return -1; + } + +#if defined(__UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__) || defined(__UCLIBC_HAS_PRINTF_M_SPEC__) + DONE: +#endif + +#ifdef NL_ARGMAX + if (maxposarg > 0) { + i = 0; + do { + /* Update maxposarg and check that NL_ARGMAX is not exceeded. */ + n = ((i <= 2) + ? (ppfs->argnumber[i] = argnumber[i]) + : argnumber[2] + (i-2)); + if (n > maxposarg) { + if ((maxposarg = n) > NL_ARGMAX) { + return -1; + } + } + --n; + /* Record argtype with largest size (current, new). */ + if (_is_equal_or_bigger_arg(ppfs->argtype[n], argtype[i])) { + ppfs->argtype[n] = argtype[i]; + } + } while (++i < ppfs->num_data_args + 2); + } else { +#endif /* NL_ARGMAX */ + ppfs->argnumber[2] = 1; + memcpy(ppfs->argtype, argtype + 2, ppfs->num_data_args * sizeof(int)); +#ifdef NL_ARGMAX + } + + ppfs->maxposarg = maxposarg; +#endif /* NL_ARGMAX */ + +#ifdef __UCLIBC_HAS_WCHAR__ + if ((flags = ppfs->info._flags & FLAG_WIDESTREAM) == 0) { + ppfs->fmtpos = ++fmt; + } else { + ppfs->fmtpos = (const char *) (((const wchar_t *)(ppfs->fmtpos)) + + (fmt - buf) ); + } +#else /* __UCLIBC_HAS_WCHAR__ */ + ppfs->fmtpos = ++fmt; +#endif /* __UCLIBC_HAS_WCHAR__ */ + + return ppfs->num_data_args + 2; +} + +#endif +/**********************************************************************/ +#ifdef L_register_printf_function + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + +int register_printf_function(int spec, printf_function handler, + printf_arginfo_function arginfo) +{ + register char *r; + register char *p; + + if (spec && (arginfo != NULL)) { /* TODO -- check if spec is valid char */ + r = NULL; + p = _custom_printf_spec + MAX_USER_SPEC; + do { + --p; + if (!*p) { + r = p; + } +#ifdef __BCC__ + else /* bcc generates less code with fall-through */ +#endif + if (*p == spec) { + r = p; + p = _custom_printf_spec; + } + } while (p > _custom_printf_spec); + + if (r) { + if (handler) { + *r = spec; + _custom_printf_handler[(int)(r - p)] = handler; + _custom_printf_arginfo[(int)(r - p)] = arginfo; + } else { + *r = 0; + } + return 0; + } + /* TODO -- if asked to unregister a non-existent spec, return what? */ + } + return -1; +} + +#endif + +#endif +/**********************************************************************/ +#if defined(L_vfprintf) || defined(L_vfwprintf) + +/* We only support ascii digits (or their USC equivalent codes) in + * precision and width settings in *printf (wide) format strings. + * In other words, we don't currently support glibc's 'I' flag. + * We do accept it, but it is currently ignored. */ + +static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad); + +#ifdef L_vfprintf + +#define VFPRINTF vfprintf +#define FMT_TYPE char +#define OUTNSTR _outnstr +#define STRLEN strlen +#define _PPFS_init _ppfs_init +#define OUTPUT(F,S) fputs_unlocked(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 + +#ifdef __STDIO_PRINTF_FLOAT + +static size_t _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +{ + size_t r = 0; + + if (type & 0x80) { /* Some type of padding needed. */ + int buflen = strlen((const char *) buf); + if ((len -= buflen) > 0) { + if ((r = _charpad(fp, (type & 0x7f), len)) != len) { + return r; + } + } + len = buflen; + } + return r + OUTNSTR(fp, (const char *) buf, len); +} + +#endif /* __STDIO_PRINTF_FLOAT */ + +#else /* L_vfprintf */ + +#define VFPRINTF vfwprintf +#define FMT_TYPE wchar_t +#define OUTNSTR _outnwcs +#define STRLEN wcslen +#define _PPFS_init _ppwfs_init +#define OUTPUT(F,S) fputws(S,F) +#define _outnwcs(stream, wstring, len) _wstdio_fwrite(wstring, len, stream) +#define FP_OUT _fp_out_wide + +#ifdef __UCLIBC_HAS_LOCALE__ +libc_hidden_proto(__global_locale) +#endif + +static size_t _outnstr(FILE *stream, const char *s, size_t wclen) +{ + /* NOTE!!! len here is the number of wchars we want to generate!!! */ + wchar_t wbuf[64]; + mbstate_t mbstate; + size_t todo, r, n; + + mbstate.__mask = 0; + todo = wclen; + + while (todo) { + r = mbsrtowcs(wbuf, &s, + ((todo <= sizeof(wbuf)/sizeof(wbuf[0])) + ? todo + : sizeof(wbuf)/sizeof(wbuf[0])), + &mbstate); + assert(((ssize_t)r) > 0); + n = _outnwcs(stream, wbuf, r); + todo -= n; + if (n != r) { + break; + } + } + + return wclen - todo; +} + +#ifdef __STDIO_PRINTF_FLOAT + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move defines from _fpmaxtostr. Put them in a common header. +#endif + +/* The following defines are from _fpmaxtostr.*/ +#define DIGITS_PER_BLOCK 9 +#define NUM_DIGIT_BLOCKS ((DECIMAL_DIG+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK) +#define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK ) + +static size_t _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +{ + wchar_t wbuf[BUF_SIZE]; + const char *s = (const char *) buf; + size_t r = 0; + int i; + + if (type & 0x80) { /* Some type of padding needed */ + int buflen = strlen(s); + if ((len -= buflen) > 0) { + if ((r = _charpad(fp, (type & 0x7f), len)) != len) { + return r; + } + } + len = buflen; + } + + if (len > 0) { + i = 0; + do { +#ifdef __LOCALE_C_ONLY + wbuf[i] = s[i]; +#else /* __LOCALE_C_ONLY */ + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (s[i] == ',') { + wbuf[i] = __UCLIBC_CURLOCALE_DATA.thousands_sep_wc; + } else +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + if (s[i] == '.') { + wbuf[i] = __UCLIBC_CURLOCALE_DATA.decimal_point_wc; + } else { + wbuf[i] = s[i]; + } +#endif /* __LOCALE_C_ONLY */ + + } while (++i < len); + + r += OUTNSTR(fp, wbuf, len); + } + + return r; +} + +#endif /* __STDIO_PRINTF_FLOAT */ + +static int _ppwfs_init(register ppfs_t *ppfs, const wchar_t *fmt0) +{ + static const wchar_t invalid_wcs[] = L"Invalid wide format string."; + int r; + + /* First, zero out everything... argnumber[], argtype[], argptr[] */ + memset(ppfs, 0, sizeof(ppfs_t)); /* TODO: nonportable???? */ +#ifdef NL_ARGMAX + --ppfs->maxposarg; /* set to -1 */ +#endif /* NL_ARGMAX */ + ppfs->fmtpos = (const char *) fmt0; + ppfs->info._flags = FLAG_WIDESTREAM; + + { + mbstate_t mbstate; + const wchar_t *p; + mbstate.__mask = 0; /* Initialize the mbstate. */ + p = fmt0; + if (wcsrtombs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { + ppfs->fmtpos = (const char *) invalid_wcs; + return -1; + } + } + + /* now set all argtypes to no-arg */ + { +#if 1 + /* TODO - use memset here since already "paid for"? */ + register int *p = ppfs->argtype; + + r = MAX_ARGS; + do { + *p++ = __PA_NOARG; + } while (--r); +#else + /* TODO -- get rid of this?? */ + register char *p = (char *) ((MAX_ARGS-1) * sizeof(int)); + + do { + *((int *)(((char *)ppfs) + ((int)p) + offsetof(ppfs_t,argtype))) = __PA_NOARG; + p -= sizeof(int); + } while (p); +#endif + } + + /* + * Run through the entire format string to validate it and initialize + * the positional arg numbers (if any). + */ + { + register const wchar_t *fmt = fmt0; + + while (*fmt) { + if ((*fmt == '%') && (*++fmt != '%')) { + ppfs->fmtpos = (const char *) fmt; /* back up to the '%' */ + if ((r = _ppfs_parsespec(ppfs)) < 0) { + return -1; + } + fmt = (const wchar_t *) ppfs->fmtpos; /* update to one past end of spec */ + } else { + ++fmt; + } + } + ppfs->fmtpos = (const char *) fmt0; /* rewind */ + } + +#ifdef NL_ARGMAX + /* If we have positional args, make sure we know all the types. */ + { + register int *p = ppfs->argtype; + r = ppfs->maxposarg; + while (--r >= 0) { + if ( *p == __PA_NOARG ) { /* missing arg type!!! */ + return -1; + } + ++p; + } + } +#endif /* NL_ARGMAX */ + + return 0; +} + +#endif /* L_vfprintf */ + +static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad) +{ + size_t todo = numpad; + + /* TODO -- Use a buffer to cut down on function calls... */ + FMT_TYPE pad[1]; + + *pad = padchar; + while (todo && (OUTNSTR(stream, pad, 1) == 1)) { + --todo; + } + + return numpad - todo; +} + +/* TODO -- Dynamically allocate work space to accomodate stack-poor archs? */ +static int _do_one_spec(FILE * __restrict stream, + register ppfs_t *ppfs, int *count) +{ + static const char spec_base[] = SPEC_BASE; +#ifdef L_vfprintf + static const char prefix[] = "+\0-\0 \0000x\0000X"; + /* 0 2 4 6 9 11*/ +#else /* L_vfprintf */ + static const wchar_t prefix[] = L"+\0-\0 \0000x\0000X"; +#endif /* L_vfprintf */ + enum { + PREFIX_PLUS = 0, + PREFIX_MINUS = 2, + PREFIX_SPACE = 4, + PREFIX_LWR_X = 6, + PREFIX_UPR_X = 9, + PREFIX_NONE = 11 + }; + +#ifdef __va_arg_ptr + const void * const *argptr; +#else + const void * argptr[MAX_ARGS_PER_SPEC]; +#endif + int *argtype; +#ifdef __UCLIBC_HAS_WCHAR__ + const wchar_t *ws = NULL; + mbstate_t mbstate; +#endif /* __UCLIBC_HAS_WCHAR__ */ + size_t slen; +#ifdef L_vfprintf +#define SLEN slen +#else + size_t SLEN; + wchar_t wbuf[2]; +#endif + int base; + int numpad; + int alphacase; + int numfill = 0; /* TODO: fix */ + int prefix_num = PREFIX_NONE; + char padchar = ' '; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Determine appropriate buf size. +#endif /* __UCLIBC_MJN3_ONLY__ */ + /* TODO: buf needs to be big enough for any possible error return strings + * and also for any locale-grouped long long integer strings generated. + * This should be large enough for any of the current archs/locales, but + * eventually this should be handled robustly. */ + char buf[128]; + +#ifdef NDEBUG + _ppfs_parsespec(ppfs); +#else + if (_ppfs_parsespec(ppfs) < 0) { /* TODO: just for debugging */ + abort(); + } +#endif + _ppfs_setargs(ppfs); + + argtype = ppfs->argtype + ppfs->argnumber[2] - 1; + /* Deal with the argptr vs argvalue issue. */ +#ifdef __va_arg_ptr + argptr = (const void * const *) ppfs->argptr; +#ifdef NL_ARGMAX + if (ppfs->maxposarg > 0) { /* Using positional args... */ + argptr += ppfs->argnumber[2] - 1; + } +#endif /* NL_ARGMAX */ +#else + /* Need to build a local copy... */ + { + register argvalue_t *p = ppfs->argvalue; + int i; +#ifdef NL_ARGMAX + if (ppfs->maxposarg > 0) { /* Using positional args... */ + p += ppfs->argnumber[2] - 1; + } +#endif /* NL_ARGMAX */ + for (i = 0 ; i < ppfs->num_data_args ; i++ ) { + argptr[i] = (void *) p++; + } + } +#endif + { + register char *s = NULL; /* TODO: Should s be unsigned char * ? */ + + if (ppfs->conv_num == CONV_n) { + _store_inttype(*(void **)*argptr, + ppfs->info._flags & __PA_INTMASK, + (intmax_t) (*count)); + return 0; + } + if (ppfs->conv_num <= CONV_i) { /* pointer or (un)signed int */ + alphacase = __UIM_LOWER; + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_vfprintf +#warning CONSIDER: Should we ignore these flags if stub locale? What about custom specs? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + if ((base = spec_base[(int)(ppfs->conv_num - CONV_p)]) == 10) { + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),group)) { + alphacase = __UIM_GROUP; + } + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),i18n)) { + alphacase |= 0x80; + } + } + + if (ppfs->conv_num <= CONV_u) { /* pointer or unsigned int */ + if (ppfs->conv_num == CONV_X) { + alphacase = __UIM_UPPER; + } + if (ppfs->conv_num == CONV_p) { /* pointer */ + prefix_num = PREFIX_LWR_X; + } else { /* unsigned int */ + } + } else { /* signed int */ + base = -base; + } + if (ppfs->info.prec < 0) { /* Ignore '0' flag if prec specified. */ + padchar = ppfs->info.pad; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_vfprintf +#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, + *argptr, base), base, alphacase); + if (ppfs->conv_num > CONV_u) { /* signed int */ + if (*s == '-') { + PRINT_INFO_SET_FLAG(&(ppfs->info),showsign); + ++s; /* handle '-' in the prefix string */ + prefix_num = PREFIX_MINUS; + } else if (PRINT_INFO_FLAG_VAL(&(ppfs->info),showsign)) { + prefix_num = PREFIX_PLUS; + } else if (PRINT_INFO_FLAG_VAL(&(ppfs->info),space)) { + prefix_num = PREFIX_SPACE; + } + } + slen = (char *)(buf + sizeof(buf) - 1) - s; +#ifdef L_vfwprintf + { + const char *q = s; + mbstate.__mask = 0; /* Initialize the mbstate. */ + SLEN = mbsrtowcs(NULL, &q, 0, &mbstate); + } +#endif + numfill = ((ppfs->info.prec < 0) ? 1 : ppfs->info.prec); + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),alt)) { + if (ppfs->conv_num <= CONV_x) { /* x or p */ + prefix_num = PREFIX_LWR_X; + } + if (ppfs->conv_num == CONV_X) { + prefix_num = PREFIX_UPR_X; + } + if ((ppfs->conv_num == CONV_o) && (numfill <= SLEN)) { + numfill = ((*s == '0') ? 1 : SLEN + 1); + } + } + if (*s == '0') { + if (prefix_num >= PREFIX_LWR_X) { + prefix_num = PREFIX_NONE; + } + if (ppfs->conv_num == CONV_p) {/* null pointer */ + s = "(nil)"; +#ifdef L_vfwprintf + SLEN = +#endif + slen = 5; + numfill = 0; + } else if (numfill == 0) { /* if precision 0, no output */ +#ifdef L_vfwprintf + SLEN = +#endif + slen = 0; + } + } + numfill = ((numfill > SLEN) ? numfill - SLEN : 0); + } else if (ppfs->conv_num <= CONV_A) { /* floating point */ +#ifdef __STDIO_PRINTF_FLOAT + ssize_t nf; + nf = _fpmaxtostr(stream, + (__fpmax_t) + (PRINT_INFO_FLAG_VAL(&(ppfs->info),is_long_double) + ? *(long double *) *argptr + : (long double) (* (double *) *argptr)), + &ppfs->info, FP_OUT ); + if (nf < 0) { + return -1; + } + *count += nf; + + return 0; +#else /* __STDIO_PRINTF_FLOAT */ + 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 __UCLIBC_HAS_WCHAR__ + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (ppfs->conv_num == CONV_S) { /* wide string */ + if (!(ws = *((const wchar_t **) *argptr))) { + goto NULL_STRING; + } + /* We use an awful uClibc-specific hack here, passing + * (char*) &ws as the conversion destination. This signals + * uClibc's wcsrtombs that we want a "restricted" length + * such that the mbs fits in a buffer of the specified + * size with no partial conversions. */ + if ((slen = wcsrtombs((char *) &ws, &ws, /* Use awful hack! */ + ((ppfs->info.prec >= 0) + ? ppfs->info.prec + : SIZE_MAX), &mbstate)) + == ((size_t)-1) + ) { + return -1; /* EILSEQ */ + } + } else { /* wide char */ + s = buf; + slen = wcrtomb(s, (*((const wchar_t *) *argptr)), &mbstate); + if (slen == ((size_t)-1)) { + return -1; /* EILSEQ */ + } + s[slen] = 0; /* TODO - Is this necessary? */ + } +#else /* __UCLIBC_HAS_WCHAR__ */ + return -1; +#endif /* __UCLIBC_HAS_WCHAR__ */ + } else if (ppfs->conv_num <= CONV_s) { /* char or string */ + if (ppfs->conv_num == CONV_s) { /* string */ + s = *((char **) (*argptr)); + if (s) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + SET_STRING_LEN: +#endif + slen = strnlen(s, ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX)); + } else { +#ifdef __UCLIBC_HAS_WCHAR__ + NULL_STRING: +#endif + s = "(null)"; + slen = 6; + } + } else { /* char */ + s = buf; + *s = (unsigned char)(*((const int *) *argptr)); + s[1] = 0; + slen = 1; + } + +#else /* L_vfprintf */ + + if (ppfs->conv_num == CONV_S) { /* wide string */ + ws = *((wchar_t **) (*argptr)); + if (!ws) { + goto NULL_STRING; + } + SLEN = wcsnlen(ws, ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX)); + } else { /* wide char */ + *wbuf = (wchar_t)(*((const wint_t *) *argptr)); + CHAR_CASE: + ws = wbuf; + wbuf[1] = 0; + SLEN = 1; + } + + } else if (ppfs->conv_num <= CONV_s) { /* char or string */ + + if (ppfs->conv_num == CONV_s) { /* string */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix %s for vfwprintf... output upto illegal sequence? +#endif /* __UCLIBC_MJN3_ONLY__ */ + s = *((char **) (*argptr)); + if (s) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + SET_STRING_LEN: +#endif + /* We use an awful uClibc-specific hack here, passing + * (wchar_t*) &mbstate as the conversion destination. + * This signals uClibc's mbsrtowcs that we want a + * "restricted" length such that the mbs fits in a buffer + * of the specified size with no partial conversions. */ + { + const char *q = s; + mbstate.__mask = 0; /* Initialize the mbstate. */ + SLEN = mbsrtowcs((wchar_t *) &mbstate, &q, + ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX), + &mbstate); + } + if (SLEN == ((size_t)(-1))) { + return -1; /* EILSEQ */ + } + } else { + NULL_STRING: + s = "(null)"; + SLEN = slen = 6; + } + } else { /* char */ + *wbuf = btowc( (unsigned char)(*((const int *) *argptr)) ); + goto CHAR_CASE; + } + +#endif /* L_vfprintf */ + +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + } else if (ppfs->conv_num == CONV_m) { + s = __glibc_strerror_r(errno, buf, sizeof(buf)); + goto SET_STRING_LEN; +#endif + } else { +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + assert(ppfs->conv_num == CONV_custom0); + + s = _custom_printf_spec; + do { + if (*s == ppfs->info.spec) { + int rv; + /* TODO -- check return value for sanity? */ + rv = (*_custom_printf_handler + [(int)(s-_custom_printf_spec)]) + (stream, &ppfs->info, argptr); + if (rv < 0) { + return -1; + } + *count += rv; + return 0; + } + } while (++s < (_custom_printf_spec + MAX_USER_SPEC)); +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + assert(0); + return -1; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_vfprintf +#warning CONSIDER: If using outdigits and/or grouping, how should we pad? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + { + size_t t; + + t = SLEN + numfill; + if (prefix_num != PREFIX_NONE) { + t += ((prefix_num < PREFIX_LWR_X) ? 1 : 2); + } + numpad = ((ppfs->info.width > t) ? (ppfs->info.width - t) : 0); + *count += t + numpad; + } + if (padchar == '0') { /* TODO: check this */ + numfill += numpad; + numpad = 0; + } + + /* Now handle the output itself. */ + if (!PRINT_INFO_FLAG_VAL(&(ppfs->info),left)) { + if (_charpad(stream, ' ', numpad) != numpad) { + return -1; + } + numpad = 0; + } + OUTPUT(stream, prefix + prefix_num); + if (_charpad(stream, '0', numfill) != numfill) { + return -1; + } + +#ifdef L_vfprintf + +#ifdef __UCLIBC_HAS_WCHAR__ + if (!ws) { + assert(s); + if (_outnstr(stream, s, slen) != slen) { + return -1; + } + } else { /* wide string */ + size_t t; + mbstate.__mask = 0; /* Initialize the mbstate. */ + while (slen) { + t = (slen <= sizeof(buf)) ? slen : sizeof(buf); + t = wcsrtombs(buf, &ws, t, &mbstate); + assert (t != ((size_t)(-1))); + if (_outnstr(stream, buf, t) != t) { + return -1; + } + slen -= t; + } + } +#else /* __UCLIBC_HAS_WCHAR__ */ + if (_outnstr(stream, s, slen) != slen) { + return -1; + } +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#else /* L_vfprintf */ + + if (!ws) { + assert(s); + if (_outnstr(stream, s, SLEN) != SLEN) { + return -1; + } + } else { + if (_outnwcs(stream, ws, SLEN) != SLEN) { + return -1; + } + } + +#endif /* L_vfprintf */ + if (_charpad(stream, ' ', numpad) != numpad) { + return -1; + } + } + + return 0; +} + +libc_hidden_proto(fprintf) + +libc_hidden_proto(VFPRINTF) +int VFPRINTF (FILE * __restrict stream, + register 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, + STRLEN((const FMT_TYPE *)(ppfs.fmtpos))); +#if defined(L_vfprintf) && !defined(NDEBUG) + fprintf(stderr,"\nIMbS: \"%s\"\n\n", format); +#endif + count = -1; + } else { + _ppfs_prepargs(&ppfs, arg); /* This did a va_copy!!! */ + + do { + while (*format && (*format != '%')) { + ++format; + } + + if (format-s) { /* output any literal text in format string */ + if ( (r = OUTNSTR(stream, s, format-s)) != (format-s)) { + count = -1; + break; + } + count += r; + } + + if (!*format) { /* we're done */ + break; + } + + if (format[1] != '%') { /* if we get here, *format == '%' */ + /* TODO: _do_one_spec needs to know what the output funcs are!!! */ + ppfs.fmtpos = (const char *)(++format); + /* TODO: check -- should only fail on stream error */ + if ( (r = _do_one_spec(stream, &ppfs, &count)) < 0) { + count = -1; + break; + } + s = format = (const FMT_TYPE *) ppfs.fmtpos; + } else { /* %% means literal %, so start new string */ + s = ++format; + ++format; + } + } while (1); + + va_end(ppfs.arg); /* Need to clean up after va_copy! */ + } + +/* #if defined(L_vfprintf) && defined(__UCLIBC_HAS_WCHAR__) */ +/* DONE: */ +/* #endif */ + + __STDIO_AUTO_THREADUNLOCK(stream); + + return count; +} +libc_hidden_def(VFPRINTF) +#endif +/**********************************************************************/ diff --git a/libc/stdio/_wfwrite.c b/libc/stdio/_wfwrite.c index 792cff604..fb5c6b3ee 100644 --- a/libc/stdio/_wfwrite.c +++ b/libc/stdio/_wfwrite.c @@ -5,8 +5,6 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define wmemcpy __wmemcpy - #include "_stdio.h" #include <wchar.h> @@ -17,9 +15,9 @@ #ifdef __UCLIBC_MJN3_ONLY__ #warning TODO: Fix prototype. #endif -extern size_t __wcsnrtombs(char *__restrict dst, - const wchar_t **__restrict src, - size_t NWC, size_t len, mbstate_t *__restrict ps) attribute_hidden; + +libc_hidden_proto(wmemcpy) +libc_hidden_proto(wcsnrtombs) size_t attribute_hidden _wstdio_fwrite(const wchar_t *__restrict ws, size_t n, register FILE *__restrict stream) @@ -55,7 +53,7 @@ size_t attribute_hidden _wstdio_fwrite(const wchar_t *__restrict ws, size_t n, pw = ws; while (n > count) { - r = __wcsnrtombs(buf, &pw, n-count, sizeof(buf), &stream->__state); + r = wcsnrtombs(buf, &pw, n-count, sizeof(buf), &stream->__state); if (r != ((size_t) -1)) { /* No encoding errors */ if (!r) { ++r; /* 0 is returned when nul is reached. */ diff --git a/libc/stdio/asprintf.c b/libc/stdio/asprintf.c index 207b35a3c..3f1992559 100644 --- a/libc/stdio/asprintf.c +++ b/libc/stdio/asprintf.c @@ -5,16 +5,21 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define vasprintf __vasprintf +#include <features.h> +#ifdef __USE_GNU #include "_stdio.h" #include <stdarg.h> +libc_hidden_proto(asprintf) + +libc_hidden_proto(vasprintf) + #ifndef __STDIO_HAS_VSNPRINTF #warning Skipping asprintf and __asprintf since no vsnprintf! #else -int attribute_hidden __asprintf(char **__restrict buf, const char * __restrict format, ...) +int asprintf(char **__restrict buf, const char * __restrict format, ...) { va_list arg; int rv; @@ -25,7 +30,7 @@ int attribute_hidden __asprintf(char **__restrict buf, const char * __restrict f return rv; } +libc_hidden_def(asprintf) -strong_alias(__asprintf,asprintf) - +#endif #endif diff --git a/libc/stdio/clearerr.c b/libc/stdio/clearerr.c index cf1e623c7..a96ecaa89 100644 --- a/libc/stdio/clearerr.c +++ b/libc/stdio/clearerr.c @@ -7,18 +7,19 @@ #include "_stdio.h" +#undef clearerr #ifdef __DO_UNLOCKED -void __clearerr_unlocked(register FILE *stream) +#undef clearerr_unlocked +void clearerr_unlocked(register FILE *stream) { __STDIO_STREAM_VALIDATE(stream); __CLEARERR_UNLOCKED(stream); } -weak_alias(__clearerr_unlocked,clearerr_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__clearerr_unlocked,clearerr) +strong_alias(clearerr_unlocked,clearerr) #endif #elif defined __UCLIBC_HAS_THREADS__ diff --git a/libc/stdio/clearerr_unlocked.c b/libc/stdio/clearerr_unlocked.c new file mode 100644 index 000000000..1728d0378 --- /dev/null +++ b/libc/stdio/clearerr_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "clearerr.c" diff --git a/libc/stdio/ctermid.c b/libc/stdio/ctermid.c index 11e43f336..1cb8a0845 100644 --- a/libc/stdio/ctermid.c +++ b/libc/stdio/ctermid.c @@ -7,6 +7,8 @@ #include "_stdio.h" +libc_hidden_proto(strcpy) + char *ctermid(register char *s) { static char sbuf[L_ctermid]; @@ -21,6 +23,6 @@ char *ctermid(register char *s) return s; #else /* glibc always returns /dev/tty for linux. */ - return __strcpy((s ? s : sbuf), "/dev/tty"); + return strcpy((s ? s : sbuf), "/dev/tty"); #endif } diff --git a/libc/stdio/dprintf.c b/libc/stdio/dprintf.c index 1fc46c722..a8b2704b2 100644 --- a/libc/stdio/dprintf.c +++ b/libc/stdio/dprintf.c @@ -5,11 +5,14 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define vdprintf __vdprintf +#include <features.h> +#ifdef __USE_GNU #include "_stdio.h" #include <stdarg.h> +libc_hidden_proto(vdprintf) + int dprintf(int filedes, const char * __restrict format, ...) { va_list arg; @@ -21,3 +24,4 @@ int dprintf(int filedes, const char * __restrict format, ...) return rv; } +#endif diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c index e019ad53e..843599c0f 100644 --- a/libc/stdio/fclose.c +++ b/libc/stdio/fclose.c @@ -5,12 +5,13 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define close __close - #include "_stdio.h" +libc_hidden_proto(fclose) + +libc_hidden_proto(close) +libc_hidden_proto(fflush_unlocked) -#undef fclose -int attribute_hidden __fclose(register FILE *stream) +int fclose(register FILE *stream) { int rv = 0; __STDIO_AUTO_THREADLOCK_VAR; @@ -47,7 +48,7 @@ int attribute_hidden __fclose(register FILE *stream) #ifdef __STDIO_BUFFERS /* Write any pending buffered chars. */ if (__STDIO_STREAM_IS_WRITING(stream)) { - rv = __fflush_unlocked(stream); + rv = fflush_unlocked(stream); } #endif @@ -87,4 +88,4 @@ int attribute_hidden __fclose(register FILE *stream) return rv; } -strong_alias(__fclose,fclose) +libc_hidden_def(fclose) diff --git a/libc/stdio/fcloseall.c b/libc/stdio/fcloseall.c index dbb600067..7d2422562 100644 --- a/libc/stdio/fcloseall.c +++ b/libc/stdio/fcloseall.c @@ -5,8 +5,13 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ +#include <features.h> + +#ifdef __USE_GNU #include "_stdio.h" +libc_hidden_proto(fclose) + /* NOTE: GLIBC difference!!! -- fcloseall * According to the info pages, glibc actually fclose()s all open files. * Apparently, glibc's new version only fflush()s and unbuffers all @@ -38,3 +43,4 @@ int fcloseall (void) #endif } +#endif diff --git a/libc/stdio/fdopen.c b/libc/stdio/fdopen.c index bca7f23fb..acf6231b2 100644 --- a/libc/stdio/fdopen.c +++ b/libc/stdio/fdopen.c @@ -7,12 +7,15 @@ #include "_stdio.h" -FILE attribute_hidden *__fdopen(int filedes, const char *mode) +libc_hidden_proto(fdopen) +libc_hidden_proto(fcntl) + +FILE *fdopen(int filedes, const char *mode) { intptr_t cur_mode; - return (((cur_mode = __fcntl(filedes, F_GETFL))) != -1) + return (((cur_mode = fcntl(filedes, F_GETFL))) != -1) ? _stdio_fopen(cur_mode, mode, NULL, filedes) : NULL; } -strong_alias(__fdopen,fdopen) +libc_hidden_def(fdopen) diff --git a/libc/stdio/feof.c b/libc/stdio/feof.c index b0528d5ae..e5f03b720 100644 --- a/libc/stdio/feof.c +++ b/libc/stdio/feof.c @@ -7,18 +7,19 @@ #include "_stdio.h" +#undef feof #ifdef __DO_UNLOCKED -int __feof_unlocked(register FILE *stream) +#undef feof_unlocked +int feof_unlocked(register FILE *stream) { __STDIO_STREAM_VALIDATE(stream); return __FEOF_UNLOCKED(stream); } -weak_alias(__feof_unlocked,feof_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__feof_unlocked,feof) +strong_alias(feof_unlocked,feof) #endif #elif defined __UCLIBC_HAS_THREADS__ diff --git a/libc/stdio/feof_unlocked.c b/libc/stdio/feof_unlocked.c new file mode 100644 index 000000000..4553f306b --- /dev/null +++ b/libc/stdio/feof_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "feof.c" diff --git a/libc/stdio/ferror.c b/libc/stdio/ferror.c index e8d19bfa4..947b89ed1 100644 --- a/libc/stdio/ferror.c +++ b/libc/stdio/ferror.c @@ -7,18 +7,19 @@ #include "_stdio.h" +#undef ferror #ifdef __DO_UNLOCKED -int __ferror_unlocked(register FILE *stream) +#undef ferror_unlocked +int ferror_unlocked(register FILE *stream) { __STDIO_STREAM_VALIDATE(stream); return __FERROR_UNLOCKED(stream); } -weak_alias(__ferror_unlocked,ferror_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__ferror_unlocked,ferror) +strong_alias(ferror_unlocked,ferror) #endif #elif defined __UCLIBC_HAS_THREADS__ diff --git a/libc/stdio/ferror_unlocked.c b/libc/stdio/ferror_unlocked.c new file mode 100644 index 000000000..19722b8bb --- /dev/null +++ b/libc/stdio/ferror_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "ferror.c" diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c index 0a74afe3f..a2e1cf916 100644 --- a/libc/stdio/fflush.c +++ b/libc/stdio/fflush.c @@ -7,6 +7,8 @@ #include "_stdio.h" +libc_hidden_proto(fflush_unlocked) + #ifdef __DO_UNLOCKED #ifdef __UCLIBC_MJN3_ONLY__ @@ -14,6 +16,7 @@ #endif /* __UCLIBC_MJN3_ONLY__ */ #ifdef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(_stdio_user_locking) /* 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) \ @@ -31,7 +34,7 @@ #endif -int attribute_hidden __fflush_unlocked(register FILE *stream) +int fflush_unlocked(register FILE *stream) { #ifdef __STDIO_BUFFERS @@ -125,16 +128,18 @@ int attribute_hidden __fflush_unlocked(register FILE *stream) return 0; #endif /* __STDIO_BUFFERS */ } +libc_hidden_def(fflush_unlocked) -weak_alias(__fflush_unlocked,fflush_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fflush_unlocked,__fflush) -weak_alias(__fflush_unlocked,fflush) +libc_hidden_proto(fflush) +strong_alias(fflush_unlocked,fflush) +libc_hidden_def(fflush) #endif #elif defined __UCLIBC_HAS_THREADS__ -int attribute_hidden __fflush(register FILE *stream) +libc_hidden_proto(fflush) +int fflush(register FILE *stream) { int retval; __STDIO_AUTO_THREADLOCK_VAR; @@ -147,15 +152,15 @@ int attribute_hidden __fflush(register FILE *stream) __STDIO_AUTO_THREADLOCK(stream); - retval = __fflush_unlocked(stream); + retval = fflush_unlocked(stream); __STDIO_AUTO_THREADUNLOCK(stream); } else { - retval = __fflush_unlocked(stream); + retval = fflush_unlocked(stream); } return retval; } -strong_alias(__fflush,fflush) +libc_hidden_def(fflush) #endif diff --git a/libc/stdio/fflush_unlocked.c b/libc/stdio/fflush_unlocked.c new file mode 100644 index 000000000..a6adb59c2 --- /dev/null +++ b/libc/stdio/fflush_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fflush.c" diff --git a/libc/stdio/fgetc.c b/libc/stdio/fgetc.c index d83b6c92a..7eb2b6ea2 100644 --- a/libc/stdio/fgetc.c +++ b/libc/stdio/fgetc.c @@ -1,6 +1,7 @@ /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> * - * GNU Library General Public License (LGPL) version 2 or later. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. * * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ @@ -12,9 +13,13 @@ #undef getc #undef getc_unlocked +libc_hidden_proto(__fgetc_unlocked) + #ifdef __DO_UNLOCKED -int attribute_hidden __fgetc_unlocked_internal(FILE *stream) +libc_hidden_proto(fflush_unlocked) + +int __fgetc_unlocked(FILE *stream) { __STDIO_STREAM_VALIDATE(stream); @@ -68,20 +73,32 @@ int attribute_hidden __fgetc_unlocked_internal(FILE *stream) return EOF; } +libc_hidden_def(__fgetc_unlocked) + +libc_hidden_proto(fgetc_unlocked) +strong_alias(__fgetc_unlocked,fgetc_unlocked) +libc_hidden_def(fgetc_unlocked) + +//libc_hidden_proto(__getc_unlocked) +//strong_alias(__fgetc_unlocked,__getc_unlocked) +//libc_hidden_def(__getc_unlocked) + +libc_hidden_proto(getc_unlocked) +strong_alias(__fgetc_unlocked,getc_unlocked) +libc_hidden_def(getc_unlocked) -strong_alias(__fgetc_unlocked_internal,__fgetc_unlocked) -weak_alias(__fgetc_unlocked_internal,fgetc_unlocked) -hidden_strong_alias(__fgetc_unlocked_internal,__getc_unlocked) -weak_alias(__fgetc_unlocked_internal,getc_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fgetc_unlocked_internal,__fgetc) -weak_alias(__fgetc_unlocked_internal,fgetc) -weak_alias(__fgetc_unlocked_internal,getc) +libc_hidden_proto(fgetc) +strong_alias(__fgetc_unlocked,fgetc) +libc_hidden_def(fgetc) + +strong_alias(__fgetc_unlocked,getc) #endif #elif defined __UCLIBC_HAS_THREADS__ -int attribute_hidden __fgetc(register FILE *stream) +libc_hidden_proto(fgetc) +int fgetc(register FILE *stream) { if (stream->__user_locking != 0) { return __GETC_UNLOCKED_MACRO(stream); @@ -93,7 +110,8 @@ int attribute_hidden __fgetc(register FILE *stream) return retval; } } -strong_alias(__fgetc,fgetc) -weak_alias(__fgetc,getc) +libc_hidden_def(fgetc) + +strong_alias(fgetc,getc) #endif diff --git a/libc/stdio/fgetc_unlocked.c b/libc/stdio/fgetc_unlocked.c new file mode 100644 index 000000000..a20c7eef2 --- /dev/null +++ b/libc/stdio/fgetc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetc.c" diff --git a/libc/stdio/fgetpos.c b/libc/stdio/fgetpos.c index 03c18ab93..610737d36 100644 --- a/libc/stdio/fgetpos.c +++ b/libc/stdio/fgetpos.c @@ -8,9 +8,11 @@ #include "_stdio.h" #ifndef __DO_LARGEFILE -#define FTELL __ftell +#define FTELL ftell #endif +libc_hidden_proto(FTELL) + int fgetpos(FILE * __restrict stream, register fpos_t * __restrict pos) { #ifdef __STDIO_MBSTATE diff --git a/libc/stdio/fgetpos64.c b/libc/stdio/fgetpos64.c index 6f46746b1..32b7120aa 100644 --- a/libc/stdio/fgetpos64.c +++ b/libc/stdio/fgetpos64.c @@ -10,5 +10,5 @@ #define __DO_LARGEFILE #define fgetpos fgetpos64 #define fpos_t fpos64_t -#define FTELL __ftello64 +#define FTELL ftello64 #include "fgetpos.c" diff --git a/libc/stdio/fgets.c b/libc/stdio/fgets.c index 5baf63a58..5acaf91ed 100644 --- a/libc/stdio/fgets.c +++ b/libc/stdio/fgets.c @@ -7,9 +7,13 @@ #include "_stdio.h" +libc_hidden_proto(fgets_unlocked) + #ifdef __DO_UNLOCKED -char attribute_hidden *__fgets_unlocked(char *__restrict s, int n, +libc_hidden_proto(__fgetc_unlocked) + +char *fgets_unlocked(char *__restrict s, int n, register FILE * __restrict stream) { register char *p; @@ -34,7 +38,7 @@ char attribute_hidden *__fgets_unlocked(char *__restrict s, int n, break; } } else { - if ((c = __fgetc_unlocked_internal(stream)) == EOF) { + if ((c = __fgetc_unlocked(stream)) == EOF) { if (__FERROR_UNLOCKED(stream)) { goto ERROR; } @@ -57,17 +61,18 @@ char attribute_hidden *__fgets_unlocked(char *__restrict s, int n, ERROR: return NULL; } - -weak_alias(__fgets_unlocked,fgets_unlocked) +libc_hidden_def(fgets_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fgets_unlocked,__fgets) -weak_alias(__fgets_unlocked,fgets) +libc_hidden_proto(fgets) +strong_alias(fgets_unlocked,fgets) +libc_hidden_def(fgets) #endif #elif defined __UCLIBC_HAS_THREADS__ -char attribute_hidden *__fgets(char *__restrict s, int n, +libc_hidden_proto(fgets) +char *fgets(char *__restrict s, int n, register FILE * __restrict stream) { char *retval; @@ -75,12 +80,12 @@ char attribute_hidden *__fgets(char *__restrict s, int n, __STDIO_AUTO_THREADLOCK(stream); - retval = __fgets_unlocked(s, n, stream); + retval = fgets_unlocked(s, n, stream); __STDIO_AUTO_THREADUNLOCK(stream); return retval; } -strong_alias(__fgets,fgets) +libc_hidden_def(fgets) #endif diff --git a/libc/stdio/fgets_unlocked.c b/libc/stdio/fgets_unlocked.c new file mode 100644 index 000000000..db0191305 --- /dev/null +++ b/libc/stdio/fgets_unlocked.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include <features.h> + +#ifdef __USE_GNU +# define __DO_UNLOCKED +# include "fgets.c" +#endif diff --git a/libc/stdio/fgetwc.c b/libc/stdio/fgetwc.c index 45ff86b80..062d825d6 100644 --- a/libc/stdio/fgetwc.c +++ b/libc/stdio/fgetwc.c @@ -5,10 +5,12 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define mbrtowc __mbrtowc - #include "_stdio.h" +libc_hidden_proto(fgetwc_unlocked) + +libc_hidden_proto(mbrtowc) + #ifdef __DO_UNLOCKED static void munge_stream(register FILE *stream, unsigned char *buf) @@ -19,7 +21,7 @@ static void munge_stream(register FILE *stream, unsigned char *buf) __STDIO_STREAM_DISABLE_PUTC(stream); } -wint_t attribute_hidden __fgetwc_unlocked(register FILE *stream) +wint_t fgetwc_unlocked(register FILE *stream) { wint_t wi; wchar_t wc[1]; @@ -107,31 +109,34 @@ wint_t attribute_hidden __fgetwc_unlocked(register FILE *stream) return wi; } +libc_hidden_def(fgetwc_unlocked) -weak_alias(__fgetwc_unlocked,fgetwc_unlocked) -weak_alias(__fgetwc_unlocked,getwc_unlocked) +strong_alias(fgetwc_unlocked,getwc_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fgetwc_unlocked,__fgetwc) -weak_alias(__fgetwc_unlocked,fgetwc) -weak_alias(__fgetwc_unlocked,getwc) +libc_hidden_proto(fgetwc) +strong_alias(fgetwc_unlocked,fgetwc) +libc_hidden_def(fgetwc) + +strong_alias(fgetwc_unlocked,getwc) #endif #elif defined __UCLIBC_HAS_THREADS__ -wint_t attribute_hidden __fgetwc(register FILE *stream) +libc_hidden_proto(fgetwc) +wint_t fgetwc(register FILE *stream) { wint_t retval; __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); - retval = __fgetwc_unlocked(stream); + retval = fgetwc_unlocked(stream); __STDIO_AUTO_THREADUNLOCK(stream); return retval; } -strong_alias(__fgetwc,fgetwc) -weak_alias(__fgetwc,getwc) +libc_hidden_def(fgetwc) +strong_alias(fgetwc,getwc) #endif diff --git a/libc/stdio/fgetwc_unlocked.c b/libc/stdio/fgetwc_unlocked.c new file mode 100644 index 000000000..8eab84393 --- /dev/null +++ b/libc/stdio/fgetwc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetwc.c" diff --git a/libc/stdio/fgetws.c b/libc/stdio/fgetws.c index fe8da002d..c7dcc7d2b 100644 --- a/libc/stdio/fgetws.c +++ b/libc/stdio/fgetws.c @@ -7,12 +7,13 @@ #include "_stdio.h" -extern wchar_t *__fgetws_unlocked(wchar_t *__restrict ws, int n, - FILE *__restrict stream) attribute_hidden; +libc_hidden_proto(fgetws_unlocked) + +libc_hidden_proto(fgetwc_unlocked) #ifdef __DO_UNLOCKED -wchar_t attribute_hidden *__fgetws_unlocked(wchar_t *__restrict ws, int n, +wchar_t *fgetws_unlocked(wchar_t *__restrict ws, int n, FILE *__restrict stream) { register wchar_t *p = ws; @@ -21,7 +22,7 @@ wchar_t attribute_hidden *__fgetws_unlocked(wchar_t *__restrict ws, int n, __STDIO_STREAM_VALIDATE(stream); while ((n > 1) - && ((wi = __fgetwc_unlocked(stream)) != WEOF) + && ((wi = fgetwc_unlocked(stream)) != WEOF) && ((*p++ = wi) != '\n') ) { --n; @@ -36,10 +37,10 @@ wchar_t attribute_hidden *__fgetws_unlocked(wchar_t *__restrict ws, int n, *p = 0; return ws; } +libc_hidden_def(fgetws_unlocked) -weak_alias(__fgetws_unlocked,fgetws_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__fgetws_unlocked,fgetws) +strong_alias(fgetws_unlocked,fgetws) #endif #elif defined __UCLIBC_HAS_THREADS__ @@ -51,7 +52,7 @@ wchar_t *fgetws(wchar_t *__restrict ws, int n, FILE *__restrict stream) __STDIO_AUTO_THREADLOCK(stream); - retval = __fgetws_unlocked(ws, n, stream); + retval = fgetws_unlocked(ws, n, stream); __STDIO_AUTO_THREADUNLOCK(stream); diff --git a/libc/stdio/fgetws_unlocked.c b/libc/stdio/fgetws_unlocked.c new file mode 100644 index 000000000..6dd58f20a --- /dev/null +++ b/libc/stdio/fgetws_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetws.c" diff --git a/libc/stdio/fileno.c b/libc/stdio/fileno.c index bc1ade952..929936bfd 100644 --- a/libc/stdio/fileno.c +++ b/libc/stdio/fileno.c @@ -7,9 +7,11 @@ #include "_stdio.h" +libc_hidden_proto(fileno_unlocked) + #ifdef __DO_UNLOCKED -int attribute_hidden __fileno_unlocked(register FILE *stream) +int fileno_unlocked(register FILE *stream) { __STDIO_STREAM_VALIDATE(stream); @@ -20,27 +22,30 @@ int attribute_hidden __fileno_unlocked(register FILE *stream) __set_errno(EBADF); return -1; } +libc_hidden_def(fileno_unlocked) -weak_alias(__fileno_unlocked,fileno_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_weak_alias(__fileno_unlocked,__fileno) -weak_alias(__fileno_unlocked,fileno) +libc_hidden_proto(fileno) +strong_alias(fileno_unlocked,fileno) +libc_hidden_def(fileno) #endif #elif defined __UCLIBC_HAS_THREADS__ -int attribute_hidden __fileno(register FILE *stream) +libc_hidden_proto(fileno) +int fileno(register FILE *stream) { int retval; __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); - retval = __fileno_unlocked(stream); + retval = fileno_unlocked(stream); __STDIO_AUTO_THREADUNLOCK(stream); return retval; } -strong_alias(__fileno,fileno) +libc_hidden_def(fileno) + #endif diff --git a/libc/stdio/fileno_unlocked.c b/libc/stdio/fileno_unlocked.c new file mode 100644 index 000000000..e50059296 --- /dev/null +++ b/libc/stdio/fileno_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fileno.c" diff --git a/libc/stdio/fmemopen.c b/libc/stdio/fmemopen.c index fc7870258..a78d56efc 100644 --- a/libc/stdio/fmemopen.c +++ b/libc/stdio/fmemopen.c @@ -5,10 +5,14 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define fopencookie __fopencookie +#include <features.h> +#ifdef __USE_GNU #include "_stdio.h" +libc_hidden_proto(memcpy) +libc_hidden_proto(fopencookie) + #ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ #error no custom streams! #endif @@ -37,7 +41,7 @@ static ssize_t fmo_read(register void *cookie, char *buf, size_t bufsize) bufsize = count; } - __memcpy(buf, COOKIE->buf + COOKIE->pos, bufsize); + memcpy(buf, COOKIE->buf + COOKIE->pos, bufsize); COOKIE->pos += bufsize; return bufsize; @@ -64,7 +68,7 @@ static ssize_t fmo_write(register void *cookie, const char *buf, size_t bufsize) } } - __memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize); + memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize); COOKIE->pos += bufsize; if (COOKIE->pos > COOKIE->eof) { @@ -176,3 +180,4 @@ FILE *fmemopen(void *s, size_t len, const char *modes) return NULL; } +#endif diff --git a/libc/stdio/fopen.c b/libc/stdio/fopen.c index ad5d1aa92..ec14b5956 100644 --- a/libc/stdio/fopen.c +++ b/libc/stdio/fopen.c @@ -9,15 +9,14 @@ #ifndef __DO_LARGEFILE # define FILEDES_ARG (-1) -#undef __fopen #undef fopen #else -#undef __fopen64 #undef fopen64 #endif -FILE attribute_hidden *__fopen(const char * __restrict filename, const char * __restrict mode) +libc_hidden_proto(fopen) +FILE *fopen(const char * __restrict filename, const char * __restrict mode) { return _stdio_fopen(((intptr_t) filename), mode, NULL, FILEDES_ARG); } -strong_alias(__fopen,fopen) +libc_hidden_def(fopen) diff --git a/libc/stdio/fopen64.c b/libc/stdio/fopen64.c index c65e9a4e9..cbdb03d68 100644 --- a/libc/stdio/fopen64.c +++ b/libc/stdio/fopen64.c @@ -8,7 +8,6 @@ #include "_stdio.h" #define __DO_LARGEFILE -#define __fopen __fopen64 #undef fopen #define fopen fopen64 #define FILEDES_ARG (-2) diff --git a/libc/stdio/fopencookie.c b/libc/stdio/fopencookie.c index a70e17b80..0b7ed84b1 100644 --- a/libc/stdio/fopencookie.c +++ b/libc/stdio/fopencookie.c @@ -5,6 +5,9 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ +#include <features.h> + +#ifdef __USE_GNU #include "_stdio.h" #ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ @@ -28,7 +31,8 @@ /* Currently no real reentrancy issues other than a possible double close(). */ #ifndef __BCC__ -FILE attribute_hidden *__fopencookie(void * __restrict cookie, const char * __restrict mode, +libc_hidden_proto(fopencookie) +FILE *fopencookie(void * __restrict cookie, const char * __restrict mode, cookie_io_functions_t io_functions) #else FILE *_fopencookie(void * __restrict cookie, const char * __restrict mode, @@ -58,5 +62,6 @@ FILE *_fopencookie(void * __restrict cookie, const char * __restrict mode, return stream; } #ifndef __BCC__ -strong_alias(__fopencookie,fopencookie) +libc_hidden_def(fopencookie) +#endif #endif diff --git a/libc/stdio/fprintf.c b/libc/stdio/fprintf.c index ee19c85a5..4f73441e1 100644 --- a/libc/stdio/fprintf.c +++ b/libc/stdio/fprintf.c @@ -8,16 +8,18 @@ #include "_stdio.h" #include <stdarg.h> -#undef fprintf -int attribute_hidden __fprintf(FILE * __restrict stream, const char * __restrict format, ...) +libc_hidden_proto(vfprintf) + +libc_hidden_proto(fprintf) +int fprintf(FILE * __restrict stream, const char * __restrict format, ...) { va_list arg; int rv; va_start(arg, format); - rv = __vfprintf(stream, format, arg); + rv = vfprintf(stream, format, arg); va_end(arg); return rv; } -strong_alias(__fprintf,fprintf) +libc_hidden_def(fprintf) diff --git a/libc/stdio/fputc.c b/libc/stdio/fputc.c index 4cc396e08..8c80bff27 100644 --- a/libc/stdio/fputc.c +++ b/libc/stdio/fputc.c @@ -12,9 +12,11 @@ #undef putc #undef putc_unlocked +libc_hidden_proto(__fputc_unlocked) + #ifdef __DO_UNLOCKED -int attribute_hidden __fputc_unlocked_internal(int c, register FILE *stream) +int __fputc_unlocked(int c, register FILE *stream) { __STDIO_STREAM_VALIDATE(stream); @@ -68,20 +70,25 @@ int attribute_hidden __fputc_unlocked_internal(int c, register FILE *stream) BAD: return EOF; } +libc_hidden_def(__fputc_unlocked) + +strong_alias(__fputc_unlocked,fputc_unlocked) -strong_alias(__fputc_unlocked_internal,__fputc_unlocked) -weak_alias(__fputc_unlocked_internal,fputc_unlocked) -weak_alias(__fputc_unlocked_internal,putc_unlocked) +libc_hidden_proto(putc_unlocked) +strong_alias(__fputc_unlocked,putc_unlocked) +libc_hidden_def(putc_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fputc_unlocked_internal,__fputc) -weak_alias(__fputc_unlocked_internal,fputc) -hidden_strong_alias(__fputc_unlocked_internal,__putc) -weak_alias(__fputc_unlocked_internal,putc) +strong_alias(__fputc_unlocked,fputc) + +libc_hidden_proto(putc) +strong_alias(__fputc_unlocked,putc) +libc_hidden_def(putc) #endif #elif defined __UCLIBC_HAS_THREADS__ -int attribute_hidden __fputc(int c, register FILE *stream) +libc_hidden_proto(fputc) +int fputc(int c, register FILE *stream) { if (stream->__user_locking != 0) { return __PUTC_UNLOCKED_MACRO(c, stream); @@ -93,8 +100,10 @@ int attribute_hidden __fputc(int c, register FILE *stream) return retval; } } -strong_alias(__fputc,fputc) -hidden_strong_alias(__fputc,__putc) -weak_alias(__fputc,putc) +libc_hidden_def(fputc) + +libc_hidden_proto(putc) +strong_alias(fputc,putc) +libc_hidden_def(putc) #endif diff --git a/libc/stdio/fputc_unlocked.c b/libc/stdio/fputc_unlocked.c new file mode 100644 index 000000000..dc4c77a51 --- /dev/null +++ b/libc/stdio/fputc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputc.c" diff --git a/libc/stdio/fputs.c b/libc/stdio/fputs.c index 64e7fd57f..4111491d6 100644 --- a/libc/stdio/fputs.c +++ b/libc/stdio/fputs.c @@ -7,6 +7,11 @@ #include "_stdio.h" +libc_hidden_proto(fputs_unlocked) + +libc_hidden_proto(strlen) +libc_hidden_proto(fwrite_unlocked) + /* Note: The standard says fputs returns a nonnegative number on * success. In this implementation, we return the length of the * string written on success. @@ -14,35 +19,37 @@ #ifdef __DO_UNLOCKED -int attribute_hidden __fputs_unlocked(register const char * __restrict s, +int fputs_unlocked(register const char * __restrict s, FILE * __restrict stream) { - size_t n = __strlen(s); + size_t n = strlen(s); - return ((__fwrite_unlocked(s, 1, n, stream) == n) ? n : EOF); + return ((fwrite_unlocked(s, 1, n, stream) == n) ? n : EOF); } +libc_hidden_def(fputs_unlocked) -weak_alias(__fputs_unlocked,fputs_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fputs_unlocked,__fputs) -weak_alias(__fputs_unlocked,fputs) +libc_hidden_proto(fputs) +strong_alias(fputs_unlocked,fputs) +libc_hidden_def(fputs) #endif #elif defined __UCLIBC_HAS_THREADS__ -int attribute_hidden __fputs(const char * __restrict s, register FILE * __restrict stream) +libc_hidden_proto(fputs) +int fputs(const char * __restrict s, register FILE * __restrict stream) { int retval; __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); - retval = __fputs_unlocked(s, stream); + retval = fputs_unlocked(s, stream); __STDIO_AUTO_THREADUNLOCK(stream); return retval; } -strong_alias(__fputs,fputs) +libc_hidden_def(fputs) #endif diff --git a/libc/stdio/fputs_unlocked.c b/libc/stdio/fputs_unlocked.c new file mode 100644 index 000000000..c7ff3f59b --- /dev/null +++ b/libc/stdio/fputs_unlocked.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include <features.h> + +#ifdef __USE_GNU +# define __DO_UNLOCKED +# include "fputs.c" +#endif diff --git a/libc/stdio/fputwc.c b/libc/stdio/fputwc.c index 8f1178710..240c1e9c4 100644 --- a/libc/stdio/fputwc.c +++ b/libc/stdio/fputwc.c @@ -7,18 +7,20 @@ #include "_stdio.h" +libc_hidden_proto(fputwc_unlocked) + #ifdef __DO_UNLOCKED -wint_t attribute_hidden __fputwc_unlocked(wchar_t wc, FILE *stream) +wint_t fputwc_unlocked(wchar_t wc, FILE *stream) { return _wstdio_fwrite(&wc, 1, stream) ? wc : WEOF; } +libc_hidden_def(fputwc_unlocked) -weak_alias(__fputwc_unlocked,fputwc_unlocked) -weak_alias(__fputwc_unlocked,putwc_unlocked) +strong_alias(fputwc_unlocked,putwc_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__fputwc_unlocked,fputwc) -weak_alias(__fputwc_unlocked,putwc) +strong_alias(fputwc_unlocked,fputwc) +strong_alias(fputwc_unlocked,putwc) #endif #elif defined __UCLIBC_HAS_THREADS__ @@ -30,13 +32,13 @@ wint_t fputwc(wchar_t wc, register FILE *stream) __STDIO_AUTO_THREADLOCK(stream); - retval = __fputwc_unlocked(wc, stream); + retval = fputwc_unlocked(wc, stream); __STDIO_AUTO_THREADUNLOCK(stream); return retval; } -weak_alias(fputwc,putwc) +strong_alias(fputwc,putwc) #endif diff --git a/libc/stdio/fputwc_unlocked.c b/libc/stdio/fputwc_unlocked.c new file mode 100644 index 000000000..757cbd0d2 --- /dev/null +++ b/libc/stdio/fputwc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputwc.c" diff --git a/libc/stdio/fputws.c b/libc/stdio/fputws.c index 74919d6ea..ecbc121dd 100644 --- a/libc/stdio/fputws.c +++ b/libc/stdio/fputws.c @@ -5,44 +5,45 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define wcslen __wcslen - #include "_stdio.h" +libc_hidden_proto(fputws_unlocked) + +libc_hidden_proto(wcslen) + #ifdef __DO_UNLOCKED -int attribute_hidden __fputws_unlocked(const wchar_t *__restrict ws, +int fputws_unlocked(const wchar_t *__restrict ws, register FILE *__restrict stream) { size_t n = wcslen(ws); return (_wstdio_fwrite(ws, n, stream) == n) ? 0 : -1; } +libc_hidden_def(fputws_unlocked) -weak_alias(__fputws_unlocked,fputws_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fputws_unlocked,__fputws) -weak_alias(__fputws_unlocked,fputws) +libc_hidden_proto(fputws) +strong_alias(fputws_unlocked,fputws) +libc_hidden_def(fputws) #endif #elif defined __UCLIBC_HAS_THREADS__ -extern int __fputws_unlocked(const wchar_t *__restrict ws, - FILE *__restrict stream) attribute_hidden; - -int attribute_hidden __fputws(const wchar_t *__restrict ws, register FILE *__restrict stream) +libc_hidden_proto(fputws) +int fputws(const wchar_t *__restrict ws, register FILE *__restrict stream) { int retval; __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); - retval = __fputws_unlocked(ws, stream); + retval = fputws_unlocked(ws, stream); __STDIO_AUTO_THREADUNLOCK(stream); return retval; } -strong_alias(__fputws,fputws) +libc_hidden_def(fputws) #endif diff --git a/libc/stdio/fputws_unlocked.c b/libc/stdio/fputws_unlocked.c new file mode 100644 index 000000000..b3a037771 --- /dev/null +++ b/libc/stdio/fputws_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputws.c" diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c index 0defb36a0..c603a9d2e 100644 --- a/libc/stdio/fread.c +++ b/libc/stdio/fread.c @@ -7,9 +7,14 @@ #include "_stdio.h" +libc_hidden_proto(fread_unlocked) + #ifdef __DO_UNLOCKED -size_t attribute_hidden __fread_unlocked(void * __restrict ptr, size_t size, size_t nmemb, +libc_hidden_proto(memcpy) +libc_hidden_proto(fflush_unlocked) + +size_t fread_unlocked(void * __restrict ptr, size_t size, size_t nmemb, FILE * __restrict stream) { __STDIO_STREAM_VALIDATE(stream); @@ -44,7 +49,7 @@ size_t attribute_hidden __fread_unlocked(void * __restrict ptr, size_t size, siz if (avail > todo) { avail = todo; } - __memcpy(buffer, stream->__bufpos, avail); + memcpy(buffer, stream->__bufpos, avail); buffer += avail; stream->__bufpos += avail; if (!(todo -= avail)) { @@ -82,16 +87,18 @@ size_t attribute_hidden __fread_unlocked(void * __restrict ptr, size_t size, siz __STDIO_STREAM_VALIDATE(stream); return 0; } +libc_hidden_def(fread_unlocked) -weak_alias(__fread_unlocked,fread_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fread_unlocked,__fread) -weak_alias(__fread_unlocked,fread) +libc_hidden_proto(fread) +strong_alias(fread_unlocked,fread) +libc_hidden_def(fread) #endif #elif defined __UCLIBC_HAS_THREADS__ -size_t attribute_hidden __fread(void * __restrict ptr, size_t size, size_t nmemb, +libc_hidden_proto(fread) +size_t fread(void * __restrict ptr, size_t size, size_t nmemb, register FILE * __restrict stream) { size_t retval; @@ -99,12 +106,12 @@ size_t attribute_hidden __fread(void * __restrict ptr, size_t size, size_t nmemb __STDIO_AUTO_THREADLOCK(stream); - retval = __fread_unlocked(ptr, size, nmemb, stream); + retval = fread_unlocked(ptr, size, nmemb, stream); __STDIO_AUTO_THREADUNLOCK(stream); return retval; } -strong_alias(__fread,fread) +libc_hidden_def(fread) #endif diff --git a/libc/stdio/fread_unlocked.c b/libc/stdio/fread_unlocked.c new file mode 100644 index 000000000..441edbb64 --- /dev/null +++ b/libc/stdio/fread_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fread.c" diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c index 7df035d48..7314807d3 100644 --- a/libc/stdio/freopen.c +++ b/libc/stdio/freopen.c @@ -7,6 +7,8 @@ #include "_stdio.h" +libc_hidden_proto(fclose) + #ifndef __DO_LARGEFILE # define FILEDES_ARG (-1) #endif diff --git a/libc/stdio/fscanf.c b/libc/stdio/fscanf.c new file mode 100644 index 000000000..102cb8d59 --- /dev/null +++ b/libc/stdio/fscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_fscanf +#include "_scanf.c" diff --git a/libc/stdio/fseeko.c b/libc/stdio/fseeko.c index 190485775..f63ebad4e 100644 --- a/libc/stdio/fseeko.c +++ b/libc/stdio/fseeko.c @@ -12,15 +12,20 @@ #endif #ifndef __DO_LARGEFILE -# define FSEEK __fseek +# define FSEEK fseek # define OFFSET_TYPE long int #endif -int attribute_hidden FSEEK(register FILE *stream, OFFSET_TYPE offset, int whence) +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(fseeko64) +#endif +libc_hidden_proto(fseek) + +int FSEEK(register FILE *stream, OFFSET_TYPE offset, int whence) { #if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE) - return __fseeko64(stream, offset, whence); + return fseeko64(stream, offset, whence); #else @@ -74,8 +79,8 @@ int attribute_hidden FSEEK(register FILE *stream, OFFSET_TYPE offset, int whence } #ifdef __DO_LARGEFILE -strong_alias(__fseeko64,fseeko64) +libc_hidden_def(fseeko64) #else -strong_alias(__fseek,fseek) -weak_alias(__fseek,fseeko) +libc_hidden_def(fseek) +strong_alias(fseek,fseeko) #endif diff --git a/libc/stdio/fseeko64.c b/libc/stdio/fseeko64.c index 5bc4ae34e..78cab1b5c 100644 --- a/libc/stdio/fseeko64.c +++ b/libc/stdio/fseeko64.c @@ -8,6 +8,6 @@ #include "_stdio.h" #define __DO_LARGEFILE -#define FSEEK __fseeko64 +#define FSEEK fseeko64 #define OFFSET_TYPE __off64_t #include "fseeko.c" diff --git a/libc/stdio/fsetpos.c b/libc/stdio/fsetpos.c index f33043f3b..d63adc024 100644 --- a/libc/stdio/fsetpos.c +++ b/libc/stdio/fsetpos.c @@ -8,9 +8,11 @@ #include "_stdio.h" #ifndef __DO_LARGEFILE -#define FSEEK __fseek +#define FSEEK fseek #endif +libc_hidden_proto(FSEEK) + int fsetpos(FILE *stream, register const fpos_t *pos) { #ifdef __STDIO_MBSTATE diff --git a/libc/stdio/fsetpos64.c b/libc/stdio/fsetpos64.c index bf7d574cb..82819a4fe 100644 --- a/libc/stdio/fsetpos64.c +++ b/libc/stdio/fsetpos64.c @@ -10,5 +10,5 @@ #define __DO_LARGEFILE #define fsetpos fsetpos64 #define fpos_t fpos64_t -#define FSEEK __fseeko64 +#define FSEEK fseeko64 #include "fsetpos.c" diff --git a/libc/stdio/ftello.c b/libc/stdio/ftello.c index 7f5c53126..4445471a4 100644 --- a/libc/stdio/ftello.c +++ b/libc/stdio/ftello.c @@ -7,16 +7,21 @@ #include "_stdio.h" +#ifdef __UCLIBC_HAS_LFS__ +libc_hidden_proto(ftello64) +#endif +libc_hidden_proto(ftell) + #ifndef __DO_LARGEFILE -# define FTELL __ftell +# define FTELL ftell # define OFFSET_TYPE long int #endif -OFFSET_TYPE attribute_hidden FTELL(register FILE *stream) +OFFSET_TYPE FTELL(register FILE *stream) { #if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE) - __offmax_t pos = __ftello64(stream); + __offmax_t pos = ftello64(stream); if ((sizeof(long) >= sizeof(__offmax_t)) || (((long) pos) == pos)) { return ((long) pos); @@ -47,8 +52,8 @@ OFFSET_TYPE attribute_hidden FTELL(register FILE *stream) } #ifdef __DO_LARGEFILE -weak_alias(__ftello64,ftello64) +libc_hidden_def(ftello64) #else -weak_alias(__ftell,ftell) -weak_alias(ftell,ftello) +libc_hidden_def(ftell) +strong_alias(ftell,ftello) #endif diff --git a/libc/stdio/ftello64.c b/libc/stdio/ftello64.c index 32a37d368..905834f39 100644 --- a/libc/stdio/ftello64.c +++ b/libc/stdio/ftello64.c @@ -8,6 +8,6 @@ #include "_stdio.h" #define __DO_LARGEFILE -#define FTELL __ftello64 +#define FTELL ftello64 #define OFFSET_TYPE __off64_t #include "ftello.c" diff --git a/libc/stdio/fwprintf.c b/libc/stdio/fwprintf.c index c81d40482..f2a1afbec 100644 --- a/libc/stdio/fwprintf.c +++ b/libc/stdio/fwprintf.c @@ -9,13 +9,15 @@ #include <stdarg.h> #include <wchar.h> +libc_hidden_proto(vfwprintf) + int fwprintf(FILE * __restrict stream, const wchar_t * __restrict format, ...) { va_list arg; int rv; va_start(arg, format); - rv = __vfwprintf(stream, format, arg); + rv = vfwprintf(stream, format, arg); va_end(arg); return rv; diff --git a/libc/stdio/fwrite.c b/libc/stdio/fwrite.c index abe24fbb7..7be794ab4 100644 --- a/libc/stdio/fwrite.c +++ b/libc/stdio/fwrite.c @@ -7,9 +7,11 @@ #include "_stdio.h" +libc_hidden_proto(fwrite_unlocked) + #ifdef __DO_UNLOCKED -size_t attribute_hidden __fwrite_unlocked(const void * __restrict ptr, size_t size, +size_t fwrite_unlocked(const void * __restrict ptr, size_t size, size_t nmemb, register FILE * __restrict stream) { __STDIO_STREAM_VALIDATE(stream); @@ -33,16 +35,18 @@ size_t attribute_hidden __fwrite_unlocked(const void * __restrict ptr, size_t si return 0; } +libc_hidden_def(fwrite_unlocked) -weak_alias(__fwrite_unlocked,fwrite_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -hidden_strong_alias(__fwrite_unlocked,__fwrite) -weak_alias(__fwrite_unlocked,fwrite) +libc_hidden_proto(fwrite) +strong_alias(fwrite_unlocked,fwrite) +libc_hidden_def(fwrite) #endif #elif defined __UCLIBC_HAS_THREADS__ -size_t attribute_hidden __fwrite(const void * __restrict ptr, size_t size, +libc_hidden_proto(fwrite) +size_t fwrite(const void * __restrict ptr, size_t size, size_t nmemb, register FILE * __restrict stream) { size_t retval; @@ -50,12 +54,12 @@ size_t attribute_hidden __fwrite(const void * __restrict ptr, size_t size, __STDIO_AUTO_THREADLOCK(stream); - retval = __fwrite_unlocked(ptr, size, nmemb, stream); + retval = fwrite_unlocked(ptr, size, nmemb, stream); __STDIO_AUTO_THREADUNLOCK(stream); return retval; } -strong_alias(__fwrite,fwrite) +libc_hidden_def(fwrite) #endif diff --git a/libc/stdio/fwrite_unlocked.c b/libc/stdio/fwrite_unlocked.c new file mode 100644 index 000000000..0f9e026c0 --- /dev/null +++ b/libc/stdio/fwrite_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fwrite.c" diff --git a/libc/stdio/fwscanf.c b/libc/stdio/fwscanf.c new file mode 100644 index 000000000..3409d00a0 --- /dev/null +++ b/libc/stdio/fwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_fwscanf +#include "_scanf.c" diff --git a/libc/stdio/getchar.c b/libc/stdio/getchar.c index d17704056..6da8307b6 100644 --- a/libc/stdio/getchar.c +++ b/libc/stdio/getchar.c @@ -7,21 +7,21 @@ #include "_stdio.h" -#undef getchar_unlocked -#undef getchar +libc_hidden_proto(__fgetc_unlocked) +#undef getchar #ifdef __DO_UNLOCKED -int attribute_hidden __getchar_unlocked(void) +#undef getchar_unlocked +int getchar_unlocked(void) { register FILE *stream = stdin; return __GETC_UNLOCKED_MACRO(stream); } -weak_alias(__getchar_unlocked,getchar_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__getchar_unlocked,getchar) +strong_alias(getchar_unlocked,getchar) #endif #elif defined __UCLIBC_HAS_THREADS__ diff --git a/libc/stdio/getchar_unlocked.c b/libc/stdio/getchar_unlocked.c new file mode 100644 index 000000000..60ea25129 --- /dev/null +++ b/libc/stdio/getchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "getchar.c" diff --git a/libc/stdio/getdelim.c b/libc/stdio/getdelim.c index e1b808340..21c86f400 100644 --- a/libc/stdio/getdelim.c +++ b/libc/stdio/getdelim.c @@ -5,8 +5,15 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ +#include <features.h> + +#ifdef __USE_GNU #include "_stdio.h" +libc_hidden_proto(getdelim) + +libc_hidden_proto(__fgetc_unlocked) + /* Note: There is a defect in this function. (size_t vs ssize_t). */ /* glibc function -- @@ -20,7 +27,7 @@ #define GETDELIM_GROWBY 64 -ssize_t attribute_hidden __getdelim(char **__restrict lineptr, size_t *__restrict n, +ssize_t getdelim(char **__restrict lineptr, size_t *__restrict n, int delimiter, register FILE *__restrict stream) { register char *buf; @@ -73,5 +80,5 @@ ssize_t attribute_hidden __getdelim(char **__restrict lineptr, size_t *__restric return pos; } - -strong_alias(__getdelim,getdelim) +libc_hidden_def(getdelim) +#endif diff --git a/libc/stdio/getline.c b/libc/stdio/getline.c index 943526abe..22b67b831 100644 --- a/libc/stdio/getline.c +++ b/libc/stdio/getline.c @@ -5,13 +5,19 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define getdelim __getdelim +#include <features.h> +#ifdef __USE_GNU #include "_stdio.h" -ssize_t attribute_hidden __getline(char **__restrict lineptr, size_t *__restrict n, +libc_hidden_proto(getline) + +libc_hidden_proto(getdelim) + +ssize_t getline(char **__restrict lineptr, size_t *__restrict n, FILE *__restrict stream) { return getdelim(lineptr, n, '\n', stream); } -strong_alias(__getline,getline) +libc_hidden_def(getline) +#endif diff --git a/libc/stdio/gets.c b/libc/stdio/gets.c index 1badd8152..5ff7869dc 100644 --- a/libc/stdio/gets.c +++ b/libc/stdio/gets.c @@ -11,6 +11,14 @@ link_warning(gets, "the 'gets' function is dangerous and should not be used.") /* UNSAFE FUNCTION -- do not bother optimizing */ +libc_hidden_proto(getchar_unlocked) +libc_hidden_proto(__fgetc_unlocked) +#ifdef __STDIO_GETC_MACRO +libc_hidden_proto(__stdin) +#else +#define __stdin stdin +#endif + char *gets(char *s) { register char *p = s; @@ -21,7 +29,7 @@ char *gets(char *s) /* Note: don't worry about performance here... this shouldn't be used! * Therefore, force actual function call. */ - while (((c = __getchar_unlocked()) != EOF) && ((*p = c) != '\n')) { + while (((c = getchar_unlocked()) != EOF) && ((*p = c) != '\n')) { ++p; } if ((c == EOF) || (s == p)) { diff --git a/libc/stdio/getw.c b/libc/stdio/getw.c index 6b3b9e5e7..e3aeda92c 100644 --- a/libc/stdio/getw.c +++ b/libc/stdio/getw.c @@ -7,12 +7,14 @@ #include "_stdio.h" +libc_hidden_proto(fread_unlocked) + /* SUSv2 Legacy function -- need not be reentrant. */ int getw(FILE *stream) { int aw; - return (__fread_unlocked((void *) &aw, sizeof(int), 1, stream) != 0) + return (fread_unlocked((void *) &aw, sizeof(int), 1, stream) != 0) ? aw : EOF; } diff --git a/libc/stdio/getwchar.c b/libc/stdio/getwchar.c index 90e5a032e..9c480b564 100644 --- a/libc/stdio/getwchar.c +++ b/libc/stdio/getwchar.c @@ -9,23 +9,24 @@ #ifdef __DO_UNLOCKED -wint_t __getwchar_unlocked(void) +libc_hidden_proto(fgetwc_unlocked) + +wint_t getwchar_unlocked(void) { - return __fgetwc_unlocked(stdin); + return fgetwc_unlocked(stdin); } -weak_alias(__getwchar_unlocked,getwchar_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__getwchar_unlocked,getwchar) +strong_alias(getwchar_unlocked,getwchar) #endif #elif defined __UCLIBC_HAS_THREADS__ -extern wint_t __fgetwc (__FILE *__stream) attribute_hidden; +libc_hidden_proto(fgetwc) wint_t getwchar(void) { - return __fgetwc(stdin); + return fgetwc(stdin); } #endif diff --git a/libc/stdio/getwchar_unlocked.c b/libc/stdio/getwchar_unlocked.c new file mode 100644 index 000000000..af4a9e888 --- /dev/null +++ b/libc/stdio/getwchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "getwchar.c" diff --git a/libc/stdio/old_vfprintf.c b/libc/stdio/old_vfprintf.c index ce6bde1a4..f81ef8688 100644 --- a/libc/stdio/old_vfprintf.c +++ b/libc/stdio/old_vfprintf.c @@ -127,10 +127,7 @@ /**************************************************************************/ -#define strnlen __strnlen - #define _ISOC99_SOURCE /* for ULLONG primarily... */ -#define _GNU_SOURCE /* for strnlen */ #include "_stdio.h" /* #include <stdio.h> */ #include <stdarg.h> @@ -148,6 +145,13 @@ #include <pthread.h> #endif /* __UCLIBC_HAS_THREADS__ */ +libc_hidden_proto(strlen) +libc_hidden_proto(strnlen) +libc_hidden_proto(memcpy) +libc_hidden_proto(putc_unlocked) +libc_hidden_proto(__fputc_unlocked) +libc_hidden_proto(__glibc_strerror_r) + /* #undef __UCLIBC_HAS_FLOATS__ */ /* #undef WANT_FLOAT_ERROR */ /* #define WANT_FLOAT_ERROR 1 */ @@ -166,7 +170,7 @@ #ifdef __STDIO_BUFFERS -#define PUTC(C,F) __putc_unlocked((C),(F)) +#define PUTC(C,F) putc_unlocked((C),(F)) #define OUTNSTR _outnstr #define _outnstr(stream, string, len) __stdio_fwrite(string, len, stream) @@ -190,7 +194,7 @@ static void _outnstr(FILE *stream, const unsigned char *s, size_t n) if (r > n) { r = n; } - __memcpy(f->bufpos, s, r); + memcpy(f->bufpos, s, r); f->bufpos += r; } } @@ -199,7 +203,7 @@ static void _outnstr(FILE *stream, const unsigned char *s, size_t n) static void putc_unlocked_sprintf(int c, __FILE_vsnprintf *f) { if (!__STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(&f->f)) { - __putc_unlocked(c, &f->f); + putc_unlocked(c, &f->f); } else if (f->bufpos < f->bufend) { *f->bufpos++ = c; } @@ -236,7 +240,7 @@ static void _charpad(FILE * __restrict stream, int padchar, size_t numpad) static void _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) { if (type & 0x80) { /* Some type of padding needed. */ - int buflen = __strlen((const char *) buf); + int buflen = strlen((const char *) buf); if ((len -= buflen) > 0) { _charpad(fp, (type & 0x7f), len); } @@ -341,7 +345,8 @@ static const char u_spec[] = "%nbopxXudics"; /* u_radix[i] <-> u_spec[i+2] for unsigned entries only */ static const char u_radix[] = "\x02\x08\x10\x10\x10\x0a"; -int attribute_hidden __vfprintf(FILE * __restrict op, register const char * __restrict fmt, +libc_hidden_proto(vfprintf) +int vfprintf(FILE * __restrict op, register const char * __restrict fmt, va_list ap) { union { @@ -450,7 +455,7 @@ int attribute_hidden __vfprintf(FILE * __restrict op, register const char * __re if (*fmt == 'm') { flag[FLAG_PLUS] = '\0'; flag[FLAG_0_PAD] = ' '; - p = __glibc_strerror_r_internal(errno, tmp, sizeof(tmp)); + p = __glibc_strerror_r(errno, tmp, sizeof(tmp)); goto print; } #endif @@ -711,4 +716,4 @@ int attribute_hidden __vfprintf(FILE * __restrict op, register const char * __re return i; } -strong_alias(__vfprintf,vfprintf) +libc_hidden_def(vfprintf) diff --git a/libc/stdio/open_memstream.c b/libc/stdio/open_memstream.c index f750cd11c..25c2f9f61 100644 --- a/libc/stdio/open_memstream.c +++ b/libc/stdio/open_memstream.c @@ -5,10 +5,15 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define fopencookie __fopencookie +#include <features.h> +#ifdef __USE_GNU #include "_stdio.h" +libc_hidden_proto(memcpy) +libc_hidden_proto(memset) +libc_hidden_proto(fopencookie) + #ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ #error no custom streams! #endif @@ -53,7 +58,7 @@ static ssize_t oms_write(register void *cookie, const char *buf, size_t bufsize) } } - __memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize); + memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize); COOKIE->pos += bufsize; if (COOKIE->pos > COOKIE->eof) { @@ -92,7 +97,7 @@ static int oms_seek(register void *cookie, __offmax_t *pos, int whence) if (buf) { *COOKIE->bufloc = COOKIE->buf = buf; COOKIE->len = leastlen; - __memset(buf + COOKIE->eof, leastlen - COOKIE->eof, 0); /* 0-fill */ + memset(buf + COOKIE->eof, leastlen - COOKIE->eof, 0); /* 0-fill */ } else { /* TODO: check glibc errno setting... */ return -1; @@ -102,7 +107,7 @@ static int oms_seek(register void *cookie, __offmax_t *pos, int whence) *pos = COOKIE->pos = --leastlen; if (leastlen > COOKIE->eof) { - __memset(COOKIE->buf + COOKIE->eof, leastlen - COOKIE->eof, 0); + memset(COOKIE->buf + COOKIE->eof, leastlen - COOKIE->eof, 0); *COOKIE->sizeloc = COOKIE->eof; } @@ -126,7 +131,8 @@ static const cookie_io_functions_t _oms_io_funcs = { * (ie replace the FILE buffer with the cookie buffer and update FILE bufstart, * etc. whenever we seek). */ -FILE attribute_hidden *__open_memstream(char **__restrict bufloc, size_t *__restrict sizeloc) +libc_hidden_proto(open_memstream) +FILE *open_memstream(char **__restrict bufloc, size_t *__restrict sizeloc) { register __oms_cookie *cookie; register FILE *fp; @@ -162,4 +168,5 @@ FILE attribute_hidden *__open_memstream(char **__restrict bufloc, size_t *__rest return NULL; } -strong_alias(__open_memstream,open_memstream) +libc_hidden_def(open_memstream) +#endif diff --git a/libc/stdio/parse_printf_format.c b/libc/stdio/parse_printf_format.c new file mode 100644 index 000000000..38266b3de --- /dev/null +++ b/libc/stdio/parse_printf_format.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_parse_printf_format +#include "_vfprintf.c" diff --git a/libc/stdio/perror.c b/libc/stdio/perror.c index 9edcf4efb..2c3cbbdb5 100644 --- a/libc/stdio/perror.c +++ b/libc/stdio/perror.c @@ -7,11 +7,16 @@ #include "_stdio.h" +libc_hidden_proto(fprintf) +libc_hidden_proto(__glibc_strerror_r) +libc_hidden_proto(stderr) + #ifdef __UCLIBC_MJN3_ONLY__ #warning CONSIDER: Increase buffer size for error message (non-%m case)? #endif -void attribute_hidden __perror(register const char *s) +libc_hidden_proto(perror) +void perror(register const char *s) { /* If the program is calling perror, it's a safe bet that printf and * friends are used as well. It is also possible that the calling @@ -30,8 +35,8 @@ void attribute_hidden __perror(register const char *s) { char buf[64]; fprintf(stderr, "%s%s%s\n", s, sep, - __glibc_strerror_r_internal(errno, buf, sizeof(buf))); + __glibc_strerror_r(errno, buf, sizeof(buf))); } #endif } -strong_alias(__perror,perror) +libc_hidden_def(perror) diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c index f84a27a3c..2163d7f8c 100644 --- a/libc/stdio/popen.c +++ b/libc/stdio/popen.c @@ -1,6 +1,7 @@ /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> * - * GNU Library General Public License (LGPL) version 2 or later. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. * * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ @@ -14,26 +15,29 @@ * Fix failure exit code for failed execve(). */ -#define waitpid __waitpid -#define execl __execl -#define dup2 __dup2 -#define fdopen __fdopen -#define pipe __pipe -#define vfork __vfork -#define fork __fork - #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <sys/wait.h> +libc_hidden_proto(close) +libc_hidden_proto(_exit) +libc_hidden_proto(waitpid) +libc_hidden_proto(execl) +libc_hidden_proto(dup2) +libc_hidden_proto(fdopen) +libc_hidden_proto(pipe) +libc_hidden_proto(vfork) +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_LOCK ((void) 0) # define VFORK_UNLOCK ((void) 0) +libc_hidden_proto(fork) #endif #ifdef __UCLIBC_HAS_THREADS__ @@ -88,36 +92,36 @@ FILE *popen(const char *command, const char *modes) parent_fd = pipe_fd[1-child_writing]; if (!(fp = fdopen(parent_fd, modes))) { - __close(parent_fd); - __close(child_fd); + close(parent_fd); + close(child_fd); goto FREE_PI; } VFORK_LOCK; if ((pid = vfork()) == 0) { /* Child of vfork... */ - __close(parent_fd); + close(parent_fd); if (child_fd != child_writing) { dup2(child_fd, child_writing); - __close(child_fd); + close(child_fd); } /* SUSv3 requires that any previously popen()'d streams in the * parent shall be closed in the child. */ for (po = popen_list ; po ; po = po->next) { - __close(po->f->__filedes); + close(po->f->__filedes); } execl("/bin/sh", "sh", "-c", command, (char *)0); /* SUSv3 mandates an exit code of 127 for the child if the * command interpreter can not be invoked. */ - _exit_internal(127); + _exit(127); } VFORK_UNLOCK; /* We need to close the child filedes whether vfork failed or * it succeeded and we're in the parent. */ - __close(child_fd); + close(child_fd); if (pid > 0) { /* Parent of vfork... */ pi->pid = pid; diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c index 82326a9c3..617561fec 100644 --- a/libc/stdio/printf.c +++ b/libc/stdio/printf.c @@ -8,15 +8,18 @@ #include "_stdio.h" #include <stdarg.h> -int attribute_hidden __printf(const char * __restrict format, ...) +libc_hidden_proto(vfprintf) + +libc_hidden_proto(printf) +int printf(const char * __restrict format, ...) { va_list arg; int rv; va_start(arg, format); - rv = __vfprintf(stdout, format, arg); + rv = vfprintf(stdout, format, arg); va_end(arg); return rv; } -strong_alias(__printf,printf) +libc_hidden_def(printf) diff --git a/libc/stdio/putchar.c b/libc/stdio/putchar.c index e503b9484..b54a7a815 100644 --- a/libc/stdio/putchar.c +++ b/libc/stdio/putchar.c @@ -7,21 +7,21 @@ #include "_stdio.h" -#undef putchar_unlocked -#undef putchar +libc_hidden_proto(__fputc_unlocked) +#undef putchar #ifdef __DO_UNLOCKED -int __putchar_unlocked(int c) +#undef putchar_unlocked +int putchar_unlocked(int c) { register FILE *stream = stdout; return __PUTC_UNLOCKED_MACRO(c, stream); } -weak_alias(__putchar_unlocked,putchar_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__putchar_unlocked,putchar) +strong_alias(putchar_unlocked,putchar) #endif #elif defined __UCLIBC_HAS_THREADS__ diff --git a/libc/stdio/putchar_unlocked.c b/libc/stdio/putchar_unlocked.c new file mode 100644 index 000000000..6d6ec471a --- /dev/null +++ b/libc/stdio/putchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "putchar.c" diff --git a/libc/stdio/puts.c b/libc/stdio/puts.c index 3a510325b..08525b2f6 100644 --- a/libc/stdio/puts.c +++ b/libc/stdio/puts.c @@ -7,6 +7,9 @@ #include "_stdio.h" +libc_hidden_proto(__fputc_unlocked) +libc_hidden_proto(fputs_unlocked) + int puts(register const char * __restrict s) { register FILE *stream = stdout; /* This helps bcc optimize. */ @@ -20,9 +23,9 @@ int puts(register const char * __restrict s) * then we could have a newline in the buffer of an LBF stream. */ /* Note: Nonportable as fputs need only return nonnegative on success. */ - if ((n = __fputs_unlocked(s, stream)) != EOF) { + if ((n = fputs_unlocked(s, stream)) != EOF) { ++n; - if (__fputc_unlocked_internal('\n', stream) == EOF) { + if (__fputc_unlocked('\n', stream) == EOF) { n = EOF; } } diff --git a/libc/stdio/putw.c b/libc/stdio/putw.c index 5dfa06890..469e44aea 100644 --- a/libc/stdio/putw.c +++ b/libc/stdio/putw.c @@ -7,6 +7,8 @@ #include "_stdio.h" +libc_hidden_proto(fwrite_unlocked) + /* SUSv2 Legacy function -- need not be reentrant. */ int putw(int w, FILE *stream) @@ -20,9 +22,9 @@ int putw(int w, FILE *stream) #endif #if EOF == -1 - return __fwrite_unlocked((void *) PW, sizeof(int), 1, stream) - 1; + return fwrite_unlocked((void *) PW, sizeof(int), 1, stream) - 1; #else - return (__fwrite_unlocked((void *) PW, sizeof(int), 1, stream) != 0) + return (fwrite_unlocked((void *) PW, sizeof(int), 1, stream) != 0) ? 0 : EOF; #endif } diff --git a/libc/stdio/putwchar.c b/libc/stdio/putwchar.c index d093656e6..7a6501c28 100644 --- a/libc/stdio/putwchar.c +++ b/libc/stdio/putwchar.c @@ -9,23 +9,26 @@ #ifdef __DO_UNLOCKED -wint_t __putwchar_unlocked(wchar_t wc) +libc_hidden_proto(fputwc_unlocked) + +wint_t putwchar_unlocked(wchar_t wc) { - return __fputwc_unlocked(wc, stdout); + return fputwc_unlocked(wc, stdout); } -weak_alias(__putwchar_unlocked,putwchar_unlocked) #ifndef __UCLIBC_HAS_THREADS__ -weak_alias(__putwchar_unlocked,putwchar) +strong_alias(putwchar_unlocked,putwchar) #endif #elif defined __UCLIBC_HAS_THREADS__ -extern int __fputc (int __c, FILE *__stream) attribute_hidden; +libc_hidden_proto(__fputc_unlocked) +/* psm: should this be fputwc? */ +libc_hidden_proto(fputc) wint_t putwchar(wchar_t wc) { - return __fputc(wc, stdout); + return fputc(wc, stdout); } #endif diff --git a/libc/stdio/putwchar_unlocked.c b/libc/stdio/putwchar_unlocked.c new file mode 100644 index 000000000..5b0c60006 --- /dev/null +++ b/libc/stdio/putwchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "putwchar.c" diff --git a/libc/stdio/register_printf_function.c b/libc/stdio/register_printf_function.c new file mode 100644 index 000000000..c6b3240a7 --- /dev/null +++ b/libc/stdio/register_printf_function.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_register_printf_function +#include "_vfprintf.c" diff --git a/libc/stdio/remove.c b/libc/stdio/remove.c index 2d4fedcc1..04ab12edb 100644 --- a/libc/stdio/remove.c +++ b/libc/stdio/remove.c @@ -5,21 +5,22 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define rmdir __rmdir -#define unlink __unlink - #include "_stdio.h" #include <unistd.h> #include <errno.h> +libc_hidden_proto(rmdir) +libc_hidden_proto(unlink) + /* SUSv3 states: * If path does not name a directory, remove(path) shall be equivalent * to unlink(path). If path names a directory, remove(path) shall be * equivalent to rmdir(path). */ -int attribute_hidden __remove(register const char *filename) +libc_hidden_proto(remove) +int remove(register const char *filename) { int saved_errno = errno; int rv; @@ -30,4 +31,4 @@ int attribute_hidden __remove(register const char *filename) } return rv; } -strong_alias(__remove,remove) +libc_hidden_def(remove) diff --git a/libc/stdio/rewind.c b/libc/stdio/rewind.c index 8e0acc2d0..e04d7a086 100644 --- a/libc/stdio/rewind.c +++ b/libc/stdio/rewind.c @@ -7,15 +7,18 @@ #include "_stdio.h" -void attribute_hidden __rewind(register FILE *stream) +libc_hidden_proto(fseek) + +libc_hidden_proto(rewind) +void rewind(register FILE *stream) { __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_CLEAR_ERROR(stream); /* Clear the error indicator */ - __fseek(stream, 0L, SEEK_SET); /* first since fseek could set it. */ + fseek(stream, 0L, SEEK_SET); /* first since fseek could set it. */ __STDIO_AUTO_THREADUNLOCK(stream); } -strong_alias(__rewind,rewind) +libc_hidden_def(rewind) diff --git a/libc/stdio/scanf.c b/libc/stdio/scanf.c index ddc2bd75f..4943c88df 100644 --- a/libc/stdio/scanf.c +++ b/libc/stdio/scanf.c @@ -1,2258 +1,9 @@ -/* Copyright (C) 2002-2004 Manuel Novoa III +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Aug 1, 2003 - * New *scanf implementation with lots of bug fixes and *wscanf support. - * Also now optionally supports hexadecimal float notation, positional - * args, and glibc locale-specific digit grouping. Should now be - * standards compliant. - * - * Aug 18, 2003 - * Bug fix: scanf %lc,%ls,%l[ would always set mb_fail on eof or error, - * even when just starting a new mb char. - * Bug fix: wscanf would incorrectly unget in certain situations. - * - * Sep 5, 2003 - * Bug fix: store flag wasn't respected if no positional args. - * Implement vs{n}scanf for the non-buffered stdio no-wchar case. - * - * Sep 13, 2003 - * Bug fix: Fix a problem reported by Atsushi Nemoto <anemo@mba.ocn.ne.jp> - * for environments where long and long long are the same. - * - * Sep 21, 2003 - * Ugh... EOF handling by scanf was completely broken. :-( Regretably, - * I got my mind fixed in one mode and didn't comply with the standards. - * Things should be fixed now, but comparision testing is difficult when - * glibc's scanf is broken and they stubbornly refuse to even acknowledge - * that it is... even when confronted by specific examples from the C99 - * standards and from an official C standard defect report. - */ - -#define wcslen __wcslen -#define mbsrtowcs __mbsrtowcs -#define mbrtowc __mbrtowc -#define ungetc __ungetc -#define ungetwc __ungetwc -#define iswspace __iswspace -#define wcrtomb __wcrtomb - -#define _ISOC99_SOURCE /* for LLONG_MAX primarily... */ -#define _GNU_SOURCE -#include <features.h> -#include "_stdio.h" -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> -#include <string.h> -#include <stdarg.h> -#include <stdint.h> -#include <errno.h> -#include <printf.h> - -#ifdef __UCLIBC_HAS_WCHAR__ -#include <bits/uClibc_uwchar.h> -#include <wchar.h> -#include <wctype.h> -#endif /* __UCLIBC_HAS_WCHAR__ */ - -#include <langinfo.h> -#include <locale.h> - -#include <assert.h> -#include <limits.h> - -#ifdef __UCLIBC_HAS_THREADS__ -#include <stdio_ext.h> -#include <pthread.h> -#endif /* __UCLIBC_HAS_THREADS__ */ - -#ifdef __UCLIBC_HAS_FLOATS__ -#include <float.h> -#include <bits/uClibc_fpmax.h> -#endif /* __UCLIBC_HAS_FLOATS__ */ - -#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ -#ifdef L_vfscanf -/* only emit this once */ -#warning Forcing undef of __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ until implemented! -#endif -#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ -#endif - -#undef __STDIO_HAS_VSSCANF -#if defined(__STDIO_BUFFERS) || !defined(__UCLIBC_HAS_WCHAR__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) -#define __STDIO_HAS_VSSCANF 1 - -#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) -typedef struct { - FILE f; - unsigned char *bufread; /* pointer to 1 past end of buffer */ - unsigned char *bufpos; -} __FILE_vsscanf; -#endif - -#endif - -extern void _store_inttype(void *dest, int desttype, uintmax_t val); - -#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) - -extern unsigned long long -_stdlib_strto_ll(register const char * __restrict str, - char ** __restrict endptr, int base, int sflag); -#if (ULLONG_MAX == UINTMAX_MAX) -#define STRTOUIM(s,e,b,sf) _stdlib_strto_ll(s,e,b,sf) -#endif - -#else /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ - -extern unsigned long -_stdlib_strto_l(register const char * __restrict str, - char ** __restrict endptr, int base, int sflag); - -#if (ULONG_MAX == UINTMAX_MAX) -#define STRTOUIM(s,e,b,sf) _stdlib_strto_l(s,e,b,sf) -#endif - -#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ - -#ifndef STRTOUIM -#error STRTOUIM conversion function is undefined! -#endif - -/**********************************************************************/ - -/* The standards require EOF < 0. */ -#if EOF >= CHAR_MIN -#define __isdigit_char_or_EOF(C) __isdigit_char((C)) -#else -#define __isdigit_char_or_EOF(C) __isdigit_int((C)) -#endif - -/**********************************************************************/ -#ifdef L_fscanf - -int attribute_hidden __fscanf(FILE * __restrict stream, const char * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = __vfscanf(stream, format, arg); - va_end(arg); - - return rv; -} -strong_alias(__fscanf,fscanf) - -#endif -/**********************************************************************/ -#ifdef L_scanf - -int scanf(const char * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = __vfscanf(stdin, format, arg); - va_end(arg); - - return rv; -} - -#endif -/**********************************************************************/ -#ifdef L_sscanf - -#ifdef __STDIO_HAS_VSSCANF - -int attribute_hidden __sscanf(const char * __restrict str, const char * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = __vsscanf(str, format, arg); - va_end(arg); - - return rv; -} -strong_alias(__sscanf,sscanf) - -#else /* __STDIO_HAS_VSSCANF */ -#warning Skipping sscanf since no vsscanf! -#endif /* __STDIO_HAS_VSSCANF */ - -#endif -/**********************************************************************/ -#ifdef L_vscanf - -int attribute_hidden __vscanf(const char * __restrict format, va_list arg) -{ - return __vfscanf(stdin, format, arg); -} -strong_alias(__vscanf,vscanf) - -#endif -/**********************************************************************/ -#ifdef L_vsscanf - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning WISHLIST: Implement vsscanf for non-buf and no custom stream case. -#endif /* __UCLIBC_MJN3_ONLY__ */ - -#ifdef __STDIO_BUFFERS - -int attribute_hidden __vsscanf(__const char *sp, __const char *fmt, va_list ap) -{ - FILE f; - -/* __STDIO_STREAM_RESET_GCS(&f); */ -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ - f.__cookie = &(f.__filedes); - f.__gcs.read = NULL; - f.__gcs.write = NULL; - f.__gcs.seek = NULL; - f.__gcs.close = NULL; -#endif - - f.__filedes = __STDIO_STREAM_FAKE_VSSCANF_FILEDES; - f.__modeflags = (__FLAG_NARROW|__FLAG_READONLY|__FLAG_READING); - -#ifdef __UCLIBC_HAS_WCHAR__ - f.__ungot_width[0] = 0; -#endif -#ifdef __STDIO_MBSTATE - __INIT_MBSTATE(&(f.__state)); -#endif - -#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; - - /* Set these last since __bufgetc initialization depends on - * __user_locking and only gets set if user locking is on. */ - f.__bufstart = - f.__bufpos = (unsigned char *) ((void *) sp); - f.__bufread = - f.__bufend = f.__bufstart + __strlen(sp); - __STDIO_STREAM_ENABLE_GETC(&f); - __STDIO_STREAM_DISABLE_PUTC(&f); - - return __vfscanf(&f, fmt, ap); -} -strong_alias(__vsscanf,vsscanf) - -#elif !defined(__UCLIBC_HAS_WCHAR__) - -int attribute_hidden __vsscanf(__const char *sp, __const char *fmt, va_list ap) -{ - __FILE_vsscanf f; - - f.bufpos = (unsigned char *) ((void *) sp); - f.bufread = f.bufpos + __strlen(sp); - -/* __STDIO_STREAM_RESET_GCS(&f.f); */ -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ - f.f.__cookie = &(f.f.__filedes); - f.f.__gcs.read = NULL; - f.f.__gcs.write = NULL; - f.f.__gcs.seek = NULL; - f.f.__gcs.close = NULL; -#endif - - f.f.__filedes = __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB; - f.f.__modeflags = (__FLAG_NARROW|__FLAG_READONLY|__FLAG_READING); - -/* #ifdef __UCLIBC_HAS_WCHAR__ */ -/* f.f.__ungot_width[0] = 0; */ -/* #endif */ -#ifdef __STDIO_MBSTATE -#error __STDIO_MBSTATE is defined! -/* __INIT_MBSTATE(&(f.f.__state)); */ -#endif - -#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 -#endif - f.f.__nextopen = NULL; - - return __vfscanf(&f.f, fmt, ap); -} -strong_alias(__vsscanf,vsscanf) - -#elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) - -int attribute_hidden __vsscanf(__const char *sp, __const char *fmt, va_list ap) -{ - FILE *f; - int rv = EOF; - - if ((f = fmemopen((char *)sp, __strlen(sp), "r")) != NULL) { - rv = __vfscanf(f, fmt, ap); - fclose(f); - } - - return rv; -} -strong_alias(__vsscanf,vsscanf) - -#else -#warning Skipping vsscanf since no buffering, no custom streams, and wchar enabled! -#ifdef __STDIO_HAS_VSSCANF -#error WHOA! __STDIO_HAS_VSSCANF is defined! -#endif -#endif - -#endif -/**********************************************************************/ -#ifdef L_fwscanf - -int fwscanf(FILE * __restrict stream, const wchar_t * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = __vfwscanf(stream, format, arg); - va_end(arg); - - return rv; -} - -#endif -/**********************************************************************/ -#ifdef L_wscanf - -int wscanf(const wchar_t * __restrict format, ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = __vfwscanf(stdin, format, arg); - va_end(arg); - - return rv; -} - -#endif -/**********************************************************************/ -#ifdef L_swscanf - -#ifdef __STDIO_BUFFERS - -int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, - ...) -{ - va_list arg; - int rv; - - va_start(arg, format); - rv = __vswscanf(str, format, arg); - va_end(arg); - - return rv; -} -#else /* __STDIO_BUFFERS */ -#warning Skipping swscanf since no buffering! -#endif /* __STDIO_BUFFERS */ - -#endif -/**********************************************************************/ -#ifdef L_vwscanf - -int vwscanf(const wchar_t * __restrict format, va_list arg) -{ - return __vfwscanf(stdin, format, arg); -} - -#endif -/**********************************************************************/ -#ifdef L_vswscanf - -#ifdef __STDIO_BUFFERS - -int attribute_hidden __vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, - va_list arg) -{ - FILE f; - - f.__bufstart = - f.__bufpos = (char *) str; - f.__bufread = - f.__bufend = (char *)(str + wcslen(str)); - __STDIO_STREAM_DISABLE_GETC(&f); - __STDIO_STREAM_DISABLE_PUTC(&f); - -/* __STDIO_STREAM_RESET_GCS(&f); */ -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ - f.__cookie = &(f.__filedes); - f.__gcs.read = NULL; - f.__gcs.write = NULL; - f.__gcs.seek = NULL; - f.__gcs.close = NULL; -#endif - - f.__filedes = __STDIO_STREAM_FAKE_VSWSCANF_FILEDES; - f.__modeflags = (__FLAG_WIDE|__FLAG_READONLY|__FLAG_READING); - -#ifdef __UCLIBC_HAS_WCHAR__ - f.__ungot_width[0] = 0; -#endif /* __UCLIBC_HAS_WCHAR__ */ -#ifdef __STDIO_MBSTATE - __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; - - return __vfwscanf(&f, format, arg); -} -strong_alias(__vswscanf,vswscanf) -#else /* __STDIO_BUFFERS */ -#warning Skipping vswscanf since no buffering! -#endif /* __STDIO_BUFFERS */ - -#endif -/**********************************************************************/ -/**********************************************************************/ - - - -/* float layout 0123456789012345678901 repeat n for "l[" */ -#define SPEC_CHARS "npxXoudifFeEgGaACSncs[" -/* npxXoudif eEgG CS cs[ */ - -/* NOTE: Ordering is important! In particular, CONV_LEFTBRACKET - * must immediately precede CONV_c. */ - -enum { - CONV_n = 0, - CONV_p, - CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i, - CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A, - CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_c, CONV_s, CONV_leftbracket, - CONV_percent, CONV_whitespace /* not in SPEC_* and no flags */ -}; - -#ifdef __UCLIBC_HAS_FLOATS__ -#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ -/* p x X o u d i f F e E g G a A */ -#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -#else -/* p x X o u d i f F e E g G a A */ -#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10 } -#endif -#else /* __UCLIBC_HAS_FLOATS__ */ -/* p x X o u d i f F e E g G a A */ -#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0 } -#endif /* __UCLIBC_HAS_FLOATS__ */ - -#ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_vfscanf -/* emit once */ -#warning CONSIDER: Add a '0' flag to eat 0 padding when grouping? -#endif -#endif /* __UCLIBC_MJN3_ONLY__ */ - -#define SPEC_FLAGS "*'I" - -enum { - FLAG_SURPRESS = 0x10, /* MUST BE 1ST!! See DO_FLAGS. */ - 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, \ - CONV_C, CONV_LEFTBRACKET, \ - CONV_c, CONV_leftbracket } - -/* Note: We treat L and ll as synonymous... for ints and floats. */ - -#define SPEC_ALLOWED_FLAGS { \ - /* n */ (0x0f|FLAG_SURPRESS), \ - /* p */ ( 0|FLAG_SURPRESS), \ - /* oxXudi */ (0x0f|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \ - /* fFeEgGaA */ (0x0c|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \ - /* C */ ( 0|FLAG_SURPRESS), \ - /* S and l[ */ ( 0|FLAG_SURPRESS|FLAG_MALLOC), \ - /* c */ (0x04|FLAG_SURPRESS), \ - /* s and [ */ (0x04|FLAG_SURPRESS|FLAG_MALLOC), \ -} - - -/**********************************************************************/ -/* - * In order to ease translation to what arginfo and _print_info._flags expect, - * we map: 0:int 1:char 2:longlong 4:long 8:short - * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) - */ - -/* TODO -- Fix the table below to take into account stdint.h. */ -/* #ifndef LLONG_MAX */ -/* #error fix QUAL_CHARS for no long long! Affects 'L', 'j', 'q', 'll'. */ -/* #else */ -/* #if LLONG_MAX != INTMAX_MAX */ -/* #error fix QUAL_CHARS intmax_t entry 'j'! */ -/* #endif */ -/* #endif */ - -#ifdef PDS -#error PDS already defined! -#endif -#ifdef SS -#error SS already defined! -#endif -#ifdef IMS -#error IMS already defined! -#endif - -#if PTRDIFF_MAX == INT_MAX -#define PDS 0 -#elif PTRDIFF_MAX == LONG_MAX -#define PDS 4 -#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) -#define PDS 8 -#else -#error fix QUAL_CHARS ptrdiff_t entry 't'! -#endif - -#if SIZE_MAX == UINT_MAX -#define SS 0 -#elif SIZE_MAX == ULONG_MAX -#define SS 4 -#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) -#define SS 8 -#else -#error fix QUAL_CHARS size_t entries 'z', 'Z'! -#endif - -#if INTMAX_MAX == INT_MAX -#define IMS 0 -#elif INTMAX_MAX == LONG_MAX -#define IMS 4 -#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) -#define IMS 8 -#else -#error fix QUAL_CHARS ptrdiff_t entry 't'! -#endif - -#define QUAL_CHARS { \ - /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int q:long_long */ \ - 'h', 'l', 'L', 'j', 'z', 't', 'q', 0, \ - 2, 4, 8, IMS, SS, PDS, 8, 0, /* TODO -- fix!!! */\ - 1, 8 } - - -/**********************************************************************/ - -#ifdef L_vfwscanf -#if WINT_MIN > EOF -#error Unfortunately, we currently need wint_t to be able to store EOF. Sorry. -#endif -#define W_EOF WEOF -#define Wint wint_t -#define Wchar wchar_t -#define Wuchar __uwchar_t -#define ISSPACE(C) iswspace((C)) -#define HIDDEN_VFSCANF __vfwscanf -#define VFSCANF vfwscanf -#define GETC(SC) (SC)->sc_getc((SC)) -#else -typedef unsigned char __uchar_t; -#define W_EOF EOF -#define Wint int -#define Wchar char -#define Wuchar __uchar_t -#define ISSPACE(C) isspace((C)) -#define HIDDEN_VFSCANF __vfscanf -#define VFSCANF vfscanf -#ifdef __UCLIBC_HAS_WCHAR__ -#define GETC(SC) (SC)->sc_getc((SC)) -#else /* __UCLIBC_HAS_WCHAR__ */ -#define GETC(SC) __getc_unlocked((SC)->fp) -#endif /* __UCLIBC_HAS_WCHAR__ */ -#endif - -struct scan_cookie { - Wint cc; - Wint ungot_char; - FILE *fp; - int nread; - int width; - -#ifdef __UCLIBC_HAS_WCHAR__ - wchar_t app_ungot; /* Match FILE struct member type. */ - unsigned char ungot_wchar_width; -#else /* __UCLIBC_HAS_WCHAR__ */ - unsigned char app_ungot; /* Match FILE struct member type. */ -#endif /* __UCLIBC_HAS_WCHAR__ */ - - char ungot_flag; - -#ifdef __UCLIBC_HAS_WCHAR__ - char ungot_wflag; /* vfwscanf */ - char mb_fail; /* vfscanf */ - mbstate_t mbstate; /* vfscanf */ - wint_t wc; - wint_t ungot_wchar; /* to support __scan_getc */ - int (*sc_getc)(struct scan_cookie *); -#endif /* __UCLIBC_HAS_WCHAR__ */ - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - const char *grouping; - const unsigned char *thousands_sep; - int tslen; -#ifdef __UCLIBC_HAS_WCHAR__ - wchar_t thousands_sep_wc; -#endif /* __UCLIBC_HAS_WCHAR__ */ -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - -#ifdef __UCLIBC_HAS_FLOATS__ - const unsigned char *decpt; - int decpt_len; -#ifdef __UCLIBC_HAS_WCHAR__ - wchar_t decpt_wc; -#endif /* __UCLIBC_HAS_WCHAR__ */ - const unsigned char *fake_decpt; -#endif /* __UCLIBC_HAS_FLOATS__ */ - -}; - -typedef struct { -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) -#if NL_ARGMAX > 10 -#warning NL_ARGMAX > 10, and space is allocated on the stack for positional args. -#endif - void *pos_args[NL_ARGMAX]; - int num_pos_args; /* Must start at -1. */ - int cur_pos_arg; -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - void *cur_ptr; - const unsigned char *fmt; - int cnt, dataargtype, conv_num, max_width; - unsigned char store, flags; -} psfs_t; /* parse scanf format state */ - - -/**********************************************************************/ -/**********************************************************************/ - -extern void __init_scan_cookie(register struct scan_cookie *sc, - register FILE *fp) attribute_hidden; -extern int __scan_getc(register struct scan_cookie *sc) attribute_hidden; -extern void __scan_ungetc(register struct scan_cookie *sc) attribute_hidden; - -#ifdef __UCLIBC_HAS_FLOATS__ -extern int __scan_strtold(long double *ld, struct scan_cookie *sc); -#endif /* __UCLIBC_HAS_FLOATS__ */ - -extern int __psfs_parse_spec(psfs_t *psfs) attribute_hidden; -extern int __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) attribute_hidden; - -/**********************************************************************/ -#ifdef L___scan_cookie - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Remove dependence on decpt_str and fake_decpt in stub locale mode. -#endif -#ifndef __UCLIBC_HAS_LOCALE__ -static const char decpt_str[] = "."; -#endif - -void attribute_hidden __init_scan_cookie(register struct scan_cookie *sc, - register FILE *fp) -{ - sc->fp = fp; - sc->nread = 0; - sc->ungot_flag = 0; - sc->app_ungot = ((fp->__modeflags & __FLAG_UNGOT) ? fp->__ungot[1] : 0); -#ifdef __UCLIBC_HAS_WCHAR__ - sc->ungot_wflag = 0; /* vfwscanf */ - sc->mb_fail = 0; -#endif /* __UCLIBC_HAS_WCHAR__ */ - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - if (*(sc->grouping = __UCLIBC_CURLOCALE_DATA.grouping)) { - sc->thousands_sep = __UCLIBC_CURLOCALE_DATA.thousands_sep; - sc->tslen = __UCLIBC_CURLOCALE_DATA.thousands_sep_len; -#ifdef __UCLIBC_HAS_WCHAR__ - sc->thousands_sep_wc = __UCLIBC_CURLOCALE_DATA.thousands_sep_wc; -#endif /* __UCLIBC_HAS_WCHAR__ */ - } -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - -#ifdef __UCLIBC_HAS_FLOATS__ -#ifdef __UCLIBC_HAS_LOCALE__ - 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->decpt_len = 1; -#endif /* __UCLIBC_HAS_LOCALE__ */ -#ifdef __UCLIBC_HAS_WCHAR__ -#ifdef __UCLIBC_HAS_LOCALE__ - sc->decpt_wc = __UCLIBC_CURLOCALE_DATA.decimal_point_wc; -#else - sc->decpt_wc = '.'; -#endif -#endif /* __UCLIBC_HAS_WCHAR__ */ -#endif /* __UCLIBC_HAS_FLOATS__ */ - -} - -int attribute_hidden __scan_getc(register struct scan_cookie *sc) -{ - int c; - -#ifdef __UCLIBC_HAS_WCHAR__ - assert(!sc->mb_fail); -#endif /* __UCLIBC_HAS_WCHAR__ */ - - sc->cc = EOF; - - if (--sc->width < 0) { - sc->ungot_flag |= 2; - return -1; - } - - if (sc->ungot_flag == 0) { -#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) - if (!__STDIO_STREAM_IS_FAKE_VSSCANF_NB(sc->fp)) { - c = GETC(sc); - } else { - __FILE_vsscanf *fv = (__FILE_vsscanf *)(sc->fp); - if (fv->bufpos < fv->bufread) { - c = *fv->bufpos++; - } else { - c = EOF; - sc->fp->__modeflags |= __FLAG_EOF; - } - } - if (c == EOF) { - sc->ungot_flag |= 2; - return -1; - } -#else - if ((c = GETC(sc)) == EOF) { - sc->ungot_flag |= 2; - return -1; - } -#endif - sc->ungot_char = c; - } else { - assert(sc->ungot_flag == 1); - sc->ungot_flag = 0; - } - - ++sc->nread; - return sc->cc = sc->ungot_char; -} - -void attribute_hidden __scan_ungetc(register struct scan_cookie *sc) -{ - ++sc->width; - if (sc->ungot_flag == 2) { /* last was EOF */ - sc->ungot_flag = 0; - sc->cc = sc->ungot_char; - } else if (sc->ungot_flag == 0) { - sc->ungot_flag = 1; - --sc->nread; - } else { - assert(0); - } -} - -#endif -/**********************************************************************/ -#ifdef L___psfs_parse_spec - -#ifdef SPEC_FLAGS -static const unsigned char spec_flags[] = SPEC_FLAGS; -#endif /* SPEC_FLAGS */ -static const unsigned char spec_chars[] = SPEC_CHARS; -static const unsigned char qual_chars[] = QUAL_CHARS; -static const unsigned char spec_ranges[] = SPEC_RANGES; -static const unsigned short spec_allowed[] = SPEC_ALLOWED_FLAGS; - -int attribute_hidden __psfs_parse_spec(register psfs_t *psfs) -{ - const unsigned char *p; - const unsigned char *fmt0 = psfs->fmt; - int i; -#ifdef SPEC_FLAGS - int j; -#endif -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) - unsigned char fail = 0; - - i = 0; /* Do this here to avoid a warning. */ - - if (!__isdigit_char(*psfs->fmt)) { /* Not a positional arg. */ - fail = 1; - goto DO_FLAGS; - } - - /* parse the positional arg (or width) value */ - do { - if (i <= ((INT_MAX - 9)/10)) { - i = (i * 10) + (*psfs->fmt++ - '0'); - } - } while (__isdigit_char(*psfs->fmt)); - - if (*psfs->fmt != '$') { /* This is a max field width. */ - if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */ - goto ERROR_EINVAL; - } - psfs->max_width = i; - psfs->num_pos_args = -2; - goto DO_QUALIFIER; - } - ++psfs->fmt; /* Advance past '$'. */ -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - -#if defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) - DO_FLAGS: -#endif /* defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) */ -#ifdef SPEC_FLAGS - p = spec_flags; - j = FLAG_SURPRESS; - do { - if (*p == *psfs->fmt) { - ++psfs->fmt; - psfs->flags |= j; - goto DO_FLAGS; - } - j += j; - } while (*++p); - - if (psfs->flags & FLAG_SURPRESS) { /* Suppress assignment. */ - psfs->store = 0; - goto DO_WIDTH; - } -#else /* SPEC_FLAGS */ - if (*psfs->fmt == '*') { /* Suppress assignment. */ - ++psfs->fmt; - psfs->store = 0; - goto DO_WIDTH; - } -#endif /* SPEC_FLAGS */ - - -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) - if (fail) { - /* Must be a non-positional arg */ - if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */ - goto ERROR_EINVAL; - } - psfs->num_pos_args = -2; - } else { - if ((psfs->num_pos_args == -2) || (((unsigned int)(--i)) >= NL_ARGMAX)) { - /* Already saw a non-pos arg or (0-based) num too large. */ - goto ERROR_EINVAL; - } - psfs->cur_pos_arg = i; - } -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - - DO_WIDTH: - for (i = 0 ; __isdigit_char(*psfs->fmt) ; ) { - if (i <= ((INT_MAX - 9)/10)) { - i = (i * 10) + (*psfs->fmt++ - '0'); - psfs->max_width = i; - } - } - -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) - DO_QUALIFIER: -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - p = qual_chars; - do { - if (*psfs->fmt == *p) { - ++psfs->fmt; - break; - } - } while (*++p); - if ((p - qual_chars < 2) && (*psfs->fmt == *p)) { - p += ((sizeof(qual_chars)-2) / 2); - ++psfs->fmt; - } - psfs->dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning CONSIDER: Should we validate that psfs->max_width > 0 in __psfs_parse_spec()? It would avoid whitespace consumption... -#warning CONSIDER: Should INT_MAX be a valid width (%c/%C)? See __psfs_parse_spec(). -#endif /* __UCLIBC_MJN3_ONLY__ */ - - p = spec_chars; - do { - if (*psfs->fmt == *p) { - int p_m_spec_chars = p - spec_chars; - -#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ -#error implement gnu a flag - if ((*p == 'a') - && ((psfs->fmt[1] == '[') || ((psfs->fmt[1]|0x20) == 's')) - ) { /* Assumes ascii for 's' and 'S' test. */ - psfs->flags |= FLAG_MALLOC; - ++psfs->fmt; - ++p; - continue; /* The related conversions follow 'a'. */ - } -#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */ - - for (p = spec_ranges; p_m_spec_chars > *p ; ++p) {} - if (((psfs->dataargtype >> 8) | psfs->flags) - & ~spec_allowed[(int)(p - spec_ranges)] - ) { - goto ERROR_EINVAL; - } - - if ((p_m_spec_chars >= CONV_c) - && (psfs->dataargtype & PA_FLAG_LONG)) { - p_m_spec_chars -= 3; /* lc -> C, ls -> S, l[ -> ?? */ - } - - psfs->conv_num = p_m_spec_chars; - return psfs->fmt - fmt0; - } - if (!*++p) { - ERROR_EINVAL: - __set_errno(EINVAL); - return -1; - } - } while(1); - - assert(0); -} - -#endif -/**********************************************************************/ -#if defined(L_vfscanf) || defined(L_vfwscanf) - -#ifdef __UCLIBC_HAS_WCHAR__ -#ifdef L_vfscanf -static int sc_getc(register struct scan_cookie *sc) -{ - return (__getc_unlocked)(sc->fp); /* Disable the macro. */ -} - -static int scan_getwc(register struct scan_cookie *sc) -{ - size_t r; - int width; - wchar_t wc[1]; - char b[1]; - - if (--sc->width < 0) { - sc->ungot_flag |= 2; - return -1; - } - - width = sc->width; /* Preserve width. */ - sc->width = INT_MAX; /* MB_CUR_MAX can invoke a function. */ - - assert(!sc->mb_fail); - - r = (size_t)(-3); - while (__scan_getc(sc) >= 0) { - *b = sc->cc; - - r = mbrtowc(wc, b, 1, &sc->mbstate); - if (((ssize_t) r) >= 0) { /* Successful completion of a wc. */ - sc->wc = *wc; - goto SUCCESS; - } else if (r == ((size_t) -2)) { - /* Potentially valid but incomplete. */ - continue; - } - break; - } - - if (r == ((size_t)(-3))) { /* EOF or ERROR on first read */ - sc->wc = WEOF; - r = (size_t)(-1); - } else { - /* If we reach here, either r == ((size_t)-1) and - * mbrtowc set errno to EILSEQ, or r == ((size_t)-2) - * and stream is in an error state or at EOF with a - * partially complete wchar. */ - __set_errno(EILSEQ); /* In case of incomplete conversion. */ - sc->mb_fail = 1; - } - - SUCCESS: - sc->width = width; /* Restore width. */ - - return (int)((ssize_t) r); -} - -#endif /* L_vfscanf */ - -#ifdef L_vfwscanf - -/* This gets called by __scan_getc. __scan_getc is called by vfwscanf - * when the next wide char is expected to be valid ascii (digits). + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -static int sc_getc(register struct scan_cookie *sc) -{ - wint_t wc; - - if (__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp)) { - if (sc->fp->__bufpos < sc->fp->__bufend) { - wc = *((wchar_t *)(sc->fp->__bufpos)); - sc->fp->__bufpos += sizeof(wchar_t); - } else { - sc->fp->__modeflags |= __FLAG_EOF; - return EOF; - } - } else if ((wc = __fgetwc_unlocked(sc->fp)) == WEOF) { - return EOF; - } - - sc->ungot_wflag = 1; - sc->ungot_wchar = wc; - sc->ungot_wchar_width = sc->fp->__ungot_width[0]; - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - if (wc == sc->thousands_sep_wc) { - wc = ','; - } else -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ -#ifdef __UCLIBC_HAS_FLOATS__ - if (wc == sc->decpt_wc) { - wc = '.'; - } else -#endif /* __UCLIBC_HAS_FLOATS__ */ - if (!__isascii(wc)) { - wc = '?'; - } - sc->wc = sc->ungot_char = wc; - - return (int) wc; -} - -static int scan_getwc(register struct scan_cookie *sc) -{ - wint_t wc; - - sc->wc = WEOF; - - if (--sc->width < 0) { - sc->ungot_flag |= 2; - return -1; - } - - if (sc->ungot_flag == 0) { - if (__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp)) { - if (sc->fp->__bufpos < sc->fp->__bufend) { - wc = *((wchar_t *)(sc->fp->__bufpos)); - sc->fp->__bufpos += sizeof(wchar_t); - } else { - sc->ungot_flag |= 2; - return -1; - } - } else if ((wc = __fgetwc_unlocked(sc->fp)) == WEOF) { - sc->ungot_flag |= 2; - return -1; - } - sc->ungot_wflag = 1; - sc->ungot_char = wc; - sc->ungot_wchar_width = sc->fp->__ungot_width[0]; - } else { - assert(sc->ungot_flag == 1); - sc->ungot_flag = 0; - } - - ++sc->nread; - sc->wc = sc->ungot_char; - - return 0; -} - - -#endif /* L_vfwscanf */ -#endif /* __UCLIBC_HAS_WCHAR__ */ - -static __inline void kill_scan_cookie(register struct scan_cookie *sc) -{ -#ifdef L_vfscanf - - if (sc->ungot_flag & 1) { -#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) - if (!__STDIO_STREAM_IS_FAKE_VSSCANF_NB(sc->fp)) { - ungetc(sc->ungot_char, sc->fp); - } -#else - ungetc(sc->ungot_char, sc->fp); -#endif - /* Deal with distiction between user and scanf ungots. */ - if (sc->nread == 0) { /* Only one char was read... app ungot? */ - sc->fp->__ungot[1] = sc->app_ungot; /* restore ungot state. */ - } else { - sc->fp->__ungot[1] = 0; - } - } - -#else - - if ((sc->ungot_flag & 1) && (sc->ungot_wflag & 1) - && !__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp) - && (sc->fp->__state.__mask == 0) - ) { - ungetwc(sc->ungot_char, sc->fp); - /* Deal with distiction between user and scanf ungots. */ - if (sc->nread == 0) { /* Only one char was read... app ungot? */ - sc->fp->__ungot[1] = sc->app_ungot; /* restore ungot state. */ - } else { - sc->fp->__ungot[1] = 0; - } - sc->fp->__ungot_width[1] = sc->ungot_wchar_width; - } - -#endif -} - -#ifdef L_vfwscanf -#ifdef __UCLIBC_HAS_FLOATS__ -static const char fake_decpt_str[] = "."; -#endif -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ -static const char fake_thousands_sep_str[] = ","; -#endif -#endif /* L_vfwscanf */ - - -int attribute_hidden HIDDEN_VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) -{ - const Wuchar *fmt; - unsigned char *b; - - -#ifdef L_vfwscanf - wchar_t wbuf[1]; - wchar_t *wb; -#endif /* L_vfwscanf */ - -#ifdef __UCLIBC_HAS_WCHAR__ - mbstate_t mbstate; -#endif /* __UCLIBC_HAS_WCHAR__ */ - - struct scan_cookie sc; - psfs_t psfs; - - int i; - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Fix MAX_DIGITS. We do not do binary, so...! -#endif -#define MAX_DIGITS 65 /* Allow one leading 0. */ - unsigned char buf[MAX_DIGITS+2]; -#ifdef L_vfscanf - unsigned char scanset[UCHAR_MAX + 1]; - unsigned char invert; /* Careful! Meaning changes. */ -#endif /* L_vfscanf */ - unsigned char fail; - unsigned char zero_conversions = 1; - __STDIO_AUTO_THREADLOCK_VAR; - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Make checking of the format string in C locale an option. -#endif - /* To support old programs, don't check mb validity if in C locale. */ -#if defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) - /* ANSI/ISO C99 requires format string to be a valid multibyte string - * beginning and ending in its initial shift state. */ - if (((__UCLIBC_CURLOCALE_DATA).encoding) != __ctype_encoding_7_bit) { - const char *p = format; - mbstate.__mask = 0; /* Initialize the mbstate. */ - if (mbsrtowcs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { - __set_errno(EINVAL); /* Format string is invalid. */ - return 0; - } - } -#endif /* defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) */ - -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) - psfs.num_pos_args = -1; /* Must start at -1. */ - /* Initialize positional arg ptrs to NULL. */ - __memset(psfs.pos_args, 0, sizeof(psfs.pos_args)); -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - - __STDIO_AUTO_THREADLOCK(fp); - - __STDIO_STREAM_VALIDATE(fp); - - __init_scan_cookie(&sc,fp); -#ifdef __UCLIBC_HAS_WCHAR__ - sc.sc_getc = sc_getc; - sc.ungot_wchar_width = sc.fp->__ungot_width[1]; - -#ifdef L_vfwscanf - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - if (*sc.grouping) { - sc.thousands_sep = fake_thousands_sep_str; - sc.tslen = 1; - } -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - -#ifdef __UCLIBC_HAS_FLOATS__ - sc.fake_decpt = fake_decpt_str; -#endif /* __UCLIBC_HAS_FLOATS__ */ - -#else /* L_vfwscanf */ - -#ifdef __UCLIBC_HAS_FLOATS__ - sc.fake_decpt = sc.decpt; -#endif /* __UCLIBC_HAS_FLOATS__ */ - -#endif /* L_vfwscanf */ - -#endif /* __UCLIBC_HAS_WCHAR__ */ - psfs.cnt = 0; - - /* Note: If we ever wanted to support non-nice codesets, we - * would really need to do a mb->wc conversion here in the - * vfscanf case. Related changes would have to be made in - * the code that follows... basicly wherever fmt appears. */ - for (fmt = (const Wuchar *) format ; *fmt ; /* ++fmt */) { - - psfs.store = 1; - psfs.flags = 0; -#ifndef NDEBUG - psfs.cur_ptr = NULL; /* Debugging aid. */ -#endif /* NDEBUG */ - - - sc.ungot_flag &= 1; /* Clear (possible fake) EOF. */ - sc.width = psfs.max_width = INT_MAX; - - /* Note: According to the standards, vfscanf does use isspace - * here. So, if we did a mb->wc conversion, we would have to do - * something like - * ((((__uwchar_t)wc) < UCHAR_MAX) && isspace(wc)) - * because wc might not be in the allowed domain. */ - if (ISSPACE(*fmt)) { - do { - ++fmt; - } while (ISSPACE(*fmt)); - --fmt; - psfs.conv_num = CONV_whitespace; - goto DO_WHITESPACE; - } - - if (*fmt == '%') { /* Conversion specification. */ - if (*++fmt == '%') { /* Remember, '%' eats whitespace too. */ - /* Note: The standard says no conversion occurs. - * So do not reset zero_conversions flag. */ - psfs.conv_num = CONV_percent; - goto DO_CONVERSION; - } - - -#ifdef L_vfscanf - psfs.fmt = fmt; -#else /* L_vfscanf */ - { - const __uwchar_t *wf = fmt; - psfs.fmt = b = buf; - - while (*wf && __isascii(*wf) && (b < buf + sizeof(buf) - 1)) { - *b++ = *wf++; - } -#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ -#error this is wrong... we need to ched in __psfs_parse_spec instead since this checks last char in buffer and conversion my have stopped before it. - if ((*b == 'a') && ((*wf == '[') || ((*wf|0x20) == 's'))) { - goto DONE; /* Spec was excessively long. */ - } -#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */ - *b = 0; - if (b == buf) { /* Bad conversion specifier! */ - goto DONE; - } - } -#endif /* L_vfscanf */ - if ((i = __psfs_parse_spec(&psfs)) < 0) { /* Bad conversion specifier! */ - goto DONE; - } - fmt += i; - - if (psfs.store) { -#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) - if (psfs.num_pos_args == -2) { - psfs.cur_ptr = va_arg(arg, void *); - } else { - while (psfs.cur_pos_arg > psfs.num_pos_args) { - psfs.pos_args[++psfs.num_pos_args] = va_arg(arg, void *); - } - psfs.cur_ptr = psfs.pos_args[psfs.cur_pos_arg]; - } -#else /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - psfs.cur_ptr = va_arg(arg, void *); -#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ - } - - DO_CONVERSION: - /* First, consume white-space if not n, c, [, C, or l[. */ - if ((((1L << CONV_n)|(1L << CONV_C)|(1L << CONV_c) - |(1L << CONV_LEFTBRACKET)|(1L << CONV_leftbracket)) - & (1L << psfs.conv_num)) == 0 - ) { - DO_WHITESPACE: - while ((__scan_getc(&sc) >= 0) -#ifdef L_vfscanf - && isspace(sc.cc) -#else /* L_vfscanf */ - && iswspace(sc.wc) -#endif /* L_vfscanf */ - ) {} - __scan_ungetc(&sc); - if (psfs.conv_num == CONV_whitespace) { - goto NEXT_FMT; - } - } - - sc.width = psfs.max_width; /* Now limit the max width. */ - - if (sc.width == 0) { /* 0 width is forbidden. */ - goto DONE; - } - - - if (psfs.conv_num == CONV_percent) { - goto MATCH_CHAR; - } - - if (psfs.conv_num == CONV_n) { -#ifdef __UCLIBC_MJN3_ONLY__ -#warning CONSIDER: Should %n count as a conversion as far as EOF return value? -#endif -/* zero_conversions = 0; */ - if (psfs.store) { - _store_inttype(psfs.cur_ptr, psfs.dataargtype, - (uintmax_t) sc.nread); - } - goto NEXT_FMT; - } - - if (psfs.conv_num <= CONV_A) { /* pointer, integer, or float spec */ - int r = __psfs_do_numeric(&psfs, &sc); -#ifndef L_vfscanf - if (sc.ungot_wflag == 1) { /* fix up '?', '.', and ',' hacks */ - sc.cc = sc.ungot_char = sc.ungot_wchar; - } -#endif - if (r != -1) { /* Either success or a matching failure. */ - zero_conversions = 0; - } - if (r < 0) { - goto DONE; - } - goto NEXT_FMT; - } - - /* Do string conversions here since they are not common code. */ - - -#ifdef L_vfscanf - - if -#ifdef __UCLIBC_HAS_WCHAR__ - (psfs.conv_num >= CONV_LEFTBRACKET) -#else /* __UCLIBC_HAS_WCHAR__ */ - (psfs.conv_num >= CONV_c) -#endif /* __UCLIBC_HAS_WCHAR__ */ - { - b = (psfs.store ? ((unsigned char *) psfs.cur_ptr) : buf); - fail = 1; - - - if (psfs.conv_num == CONV_c) { - if (sc.width == INT_MAX) { - sc.width = 1; - } - - while (__scan_getc(&sc) >= 0) { - zero_conversions = 0; - *b = sc.cc; - b += psfs.store; - } - __scan_ungetc(&sc); - if (sc.width > 0) { /* Failed to read all required. */ - goto DONE; - } - psfs.cnt += psfs.store; - goto NEXT_FMT; - } - - if (psfs.conv_num == CONV_s) { - /* Yes, believe it or not, a %s conversion can store nuls. */ - while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) { - zero_conversions = 0; - *b = sc.cc; - b += psfs.store; - fail = 0; - } - } else { -#ifdef __UCLIBC_HAS_WCHAR__ - assert((psfs.conv_num == CONV_LEFTBRACKET) || \ - (psfs.conv_num == CONV_leftbracket)); -#else /* __UCLIBC_HAS_WCHAR__ */ - assert((psfs.conv_num == CONV_leftbracket)); -#endif /* __UCLIBC_HAS_WCHAR__ */ - - invert = 0; - - if (*++fmt == '^') { - ++fmt; - invert = 1; - } - __memset(scanset, invert, sizeof(scanset)); - invert = 1-invert; - - if (*fmt == ']') { - scanset[(int)(']')] = invert; - ++fmt; - } - - while (*fmt != ']') { - if (!*fmt) { /* No closing ']'. */ - goto DONE; - } - if ((*fmt == '-') && (fmt[1] != ']') - && (fmt[-1] < fmt[1]) /* sorted? */ - ) { /* range */ - ++fmt; - i = fmt[-2]; - /* Note: scanset[i] should already have been done - * in the previous iteration. */ - do { - scanset[++i] = invert; - } while (i < *fmt); - /* Safe to fall through, and a bit smaller. */ - } - /* literal char */ - scanset[(int) *fmt] = invert; - ++fmt; - } - -#ifdef __UCLIBC_HAS_WCHAR__ - if (psfs.conv_num == CONV_LEFTBRACKET) { - goto DO_LEFTBRACKET; - } -#endif /* __UCLIBC_HAS_WCHAR__ */ - - - while (__scan_getc(&sc) >= 0) { - zero_conversions = 0; - if (!scanset[sc.cc]) { - break; - } - *b = sc.cc; - b += psfs.store; - fail = 0; - } - } - /* Common tail for processing of %s and %[. */ - - __scan_ungetc(&sc); - if (fail) { /* nothing stored! */ - goto DONE; - } - *b = 0; /* Nul-terminate string. */ - psfs.cnt += psfs.store; - goto NEXT_FMT; - } - -#ifdef __UCLIBC_HAS_WCHAR__ - DO_LEFTBRACKET: /* Need to do common wide init. */ - if (psfs.conv_num >= CONV_C) { - wchar_t wbuf[1]; - wchar_t *wb; - - sc.mbstate.__mask = 0; - - 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; - } - - while (scan_getwc(&sc) >= 0) { - zero_conversions = 0; - assert(sc.width >= 0); - *wb = sc.wc; - wb += psfs.store; - } - - __scan_ungetc(&sc); - if (sc.width > 0) { /* Failed to read all required. */ - goto DONE; - } - psfs.cnt += psfs.store; - goto NEXT_FMT; - } - - - if (psfs.conv_num == CONV_S) { - /* Yes, believe it or not, a %s conversion can store nuls. */ - while (scan_getwc(&sc) >= 0) { - zero_conversions = 0; - if ((((__uwchar_t)(sc.wc)) <= UCHAR_MAX) && isspace(sc.wc)) { - break; - } - *wb = sc.wc; - wb += psfs.store; - fail = 0; - } - } else { - assert(psfs.conv_num == CONV_LEFTBRACKET); - - while (scan_getwc(&sc) >= 0) { - zero_conversions = 0; - if (((__uwchar_t) sc.wc) <= UCHAR_MAX) { - if (!scanset[sc.wc]) { - break; - } - } else if (invert) { - break; - } - *wb = sc.wc; - wb += psfs.store; - fail = 0; - } - } - /* Common tail for processing of %ls and %l[. */ - - __scan_ungetc(&sc); - if (fail || sc.mb_fail) { /* Nothing stored or mb error. */ - goto DONE; - } - *wb = 0; /* Nul-terminate string. */ - psfs.cnt += psfs.store; - goto NEXT_FMT; - - } - -#endif /* __UCLIBC_HAS_WCHAR__ */ -#else /* L_vfscanf */ - - if (psfs.conv_num >= CONV_C) { - b = buf; - wb = wbuf; - if (psfs.conv_num >= CONV_c) { - mbstate.__mask = 0; /* Initialize the mbstate. */ - if (psfs.store) { - b = (unsigned char *) psfs.cur_ptr; - } - } else { - if (psfs.store) { - wb = (wchar_t *) psfs.cur_ptr; - } - } - fail = 1; - - - if ((psfs.conv_num == CONV_C) || (psfs.conv_num == CONV_c)) { - if (sc.width == INT_MAX) { - sc.width = 1; - } - - while (scan_getwc(&sc) >= 0) { - zero_conversions = 0; - if (psfs.conv_num == CONV_C) { - *wb = sc.wc; - wb += psfs.store; - } else { - i = wcrtomb(b, sc.wc, &mbstate); - if (i < 0) { /* Conversion failure. */ - goto DONE_DO_UNGET; - } - if (psfs.store) { - b += i; - } - } - } - __scan_ungetc(&sc); - if (sc.width > 0) { /* Failed to read all required. */ - goto DONE; - } - psfs.cnt += psfs.store; - goto NEXT_FMT; - } - - if ((psfs.conv_num == CONV_S) || (psfs.conv_num == CONV_s)) { - /* Yes, believe it or not, a %s conversion can store nuls. */ - while (scan_getwc(&sc) >= 0) { - zero_conversions = 0; - if (iswspace(sc.wc)) { - break; - } - if (psfs.conv_num == CONV_S) { - *wb = sc.wc; - wb += psfs.store; - } else { - i = wcrtomb(b, sc.wc, &mbstate); - if (i < 0) { /* Conversion failure. */ - goto DONE_DO_UNGET; - } - if (psfs.store) { - b += i; - } - } - fail = 0; - } - } else { - const wchar_t *sss; - const wchar_t *ssp; - unsigned char invert = 0; - - assert((psfs.conv_num == CONV_LEFTBRACKET) - || (psfs.conv_num == CONV_leftbracket)); - - if (*++fmt == '^') { - ++fmt; - invert = 1; - } - sss = (const wchar_t *) fmt; - if (*fmt == ']') { - ++fmt; - } - while (*fmt != ']') { - if (!*fmt) { /* No closing ']'. */ - goto DONE; - } - if ((*fmt == '-') && (fmt[1] != ']') - && (fmt[-1] < fmt[1]) /* sorted? */ - ) { /* range */ - ++fmt; - } - ++fmt; - } - /* Ok... a valid scanset spec. */ - - while (scan_getwc(&sc) >= 0) { - zero_conversions = 0; - ssp = sss; - do { /* We know sss < fmt. */ - if (*ssp == '-') { /* possible range... */ - /* Note: We accept a-c-e (ordered) as - * equivalent to a-e. */ - if (ssp > sss) { - if ((++ssp < (const wchar_t *) fmt) - && (ssp[-2] < *ssp) /* sorted? */ - ) { /* yes */ - if ((sc.wc >= ssp[-2]) - && (sc.wc <= *ssp)) { - break; - } - continue; /* not in range */ - } - --ssp; /* oops... '-' at end, so back up */ - } - /* false alarm... a literal '-' */ - } - if (sc.wc == *ssp) { /* Matched literal char. */ - break; - } - } while (++ssp < (const wchar_t *) fmt); - - if ((ssp == (const wchar_t *) fmt) ^ invert) { - /* no match and not inverting - * or match and inverting */ - break; - } - if (psfs.conv_num == CONV_LEFTBRACKET) { - *wb = sc.wc; - wb += psfs.store; - } else { - i = wcrtomb(b, sc.wc, &mbstate); - if (i < 0) { /* Conversion failure. */ - goto DONE_DO_UNGET; - } - if (psfs.store) { - b += i; - } - } - fail = 0; - } - } - /* Common tail for processing of %s and %[. */ - - __scan_ungetc(&sc); - if (fail) { /* nothing stored! */ - goto DONE; - } - *wb = 0; /* Nul-terminate string. */ - *b = 0; - psfs.cnt += psfs.store; - goto NEXT_FMT; - } - -#endif /* L_vfscanf */ - - assert(0); - goto DONE; - } /* conversion specification */ - - MATCH_CHAR: - if (__scan_getc(&sc) != *fmt) { -#ifdef L_vfwscanf - DONE_DO_UNGET: -#endif /* L_vfwscanf */ - __scan_ungetc(&sc); - goto DONE; - } - - NEXT_FMT: - ++fmt; - if (__FERROR_UNLOCKED(fp)) { - break; - } - } - - DONE: - if (__FERROR_UNLOCKED(fp) || (*fmt && zero_conversions && __FEOF_UNLOCKED(fp))) { - psfs.cnt = EOF; /* Yes, vfwscanf also returns EOF. */ - } - - kill_scan_cookie(&sc); - - __STDIO_STREAM_VALIDATE(fp); - - __STDIO_AUTO_THREADUNLOCK(fp); - - return psfs.cnt; -} -strong_alias(HIDDEN_VFSCANF,VFSCANF) -#endif -/**********************************************************************/ -#ifdef L___psfs_do_numeric - -static const unsigned char spec_base[] = SPEC_BASE; -static const unsigned char nil_string[] = "(nil)"; - -int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) -{ - unsigned char *b; - const unsigned char *p; - -#ifdef __UCLIBC_HAS_FLOATS__ - int exp_adjust = 0; -#endif -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Fix MAX_DIGITS. We do not do binary, so...! -#warning TODO: Fix buf! -#endif -#define MAX_DIGITS 65 /* Allow one leading 0. */ - unsigned char buf[MAX_DIGITS+2+ 100]; - 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? -#endif -#ifndef __UCLIBC_HAS_FLOATS__ - if (psfs->conv_num > CONV_i) { /* floating point */ - goto DONE; - } -#endif - - base = spec_base[psfs->conv_num - CONV_p]; - usflag = (psfs->conv_num <= CONV_u); /* (1)0 if (un)signed */ - b = buf; - - - if (psfs->conv_num == CONV_p) { /* Pointer */ - p = nil_string; - do { - if ((__scan_getc(sc) < 0) || (*p != sc->cc)) { - __scan_ungetc(sc); - if (p > nil_string) { - /* We matched at least the '(' so even if we - * are at eof, we can not match a pointer. */ - return -2; /* Matching failure */ - } - break; - } - if (!*++p) { /* Matched (nil), so no unget necessary. */ - if (psfs->store) { - ++psfs->cnt; - _store_inttype(psfs->cur_ptr, psfs->dataargtype, - (uintmax_t) NULL); - } - return 0; - } - } while (1); - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning CONSIDER: Should we require a 0x prefix and disallow +/- for pointer %p? -#endif /* __UCLIBC_MJN3_ONLY__ */ - } - - __scan_getc(sc); - if (sc->cc < 0) { - return -1; /* Input failure (nothing read yet). */ - } - - if ((sc->cc == '+') || (sc->cc == '-')) { /* Handle leading sign.*/ - *b++ = sc->cc; - __scan_getc(sc); - } - - if ((base & 0xef) == 0) { /* 0xef is ~16, so 16 or 0. */ - if (sc->cc == '0') { /* Possibly set base and handle prefix. */ - __scan_getc(sc); - if ((sc->cc|0x20) == 'x') { /* Assumes ascii.. x or X. */ - if (__scan_getc(sc) < 0) { - /* Either EOF or error (including wc outside char range). - * If EOF or error, this is a matching failure (we read 0x). - * If wc outside char range, this is also a matching failure. - * Hence, we do an unget (although not really necessary here - * and fail. */ - goto DONE_DO_UNGET; /* matching failure */ - } - base = 16; /* Base 16 for sure now. */ -#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ - /* The prefix is required for hexadecimal floats. */ - *b++ = '0'; - *b++ = 'x'; -#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ - } else { /* oops... back up */ - __scan_ungetc(sc); - sc->cc = '0'; /* NASTY HACK! */ - - base = (base >> 1) + 8; /* 0->8, 16->16. no 'if' */ -#ifdef __UCLIBC_HAS_FLOATS__ - if (psfs->conv_num > CONV_i) { /* floating point */ - base = 10; - } -#endif - } - } else if (!base) { - base = 10; - } - } - - /***************** digit grouping **********************/ -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - - if ((psfs->flags & FLAG_THOUSANDS) && (base == 10) - && *(p = sc->grouping) - ) { - - int nblk1, nblk2, nbmax, lastblock, pass, i; - - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning CONSIDER: Should we initalize the grouping blocks in __init_scan_cookie()? -#endif /* __UCLIBC_MJN3_ONLY__ */ - nbmax = nblk2 = nblk1 = *p; - if (*++p) { - nblk2 = *p; - if (nbmax < nblk2) { - nbmax = nblk2; - } - assert(!p[1]); - } - - /* Note: for printf, if 0 and \' flags appear then - * grouping is done before 0-padding. Should we - * strip leading 0's first? Or add a 0 flag? */ - - /* For vfwscanf, sc_getc translates, so the value of sc->cc is - * either EOF or a char. */ - - if (!__isdigit_char_or_EOF(sc->cc)) { /* No starting digit! */ -#ifdef __UCLIBC_HAS_FLOATS__ - if (psfs->conv_num > CONV_i) { /* floating point */ - goto NO_STARTING_DIGIT; - } -#endif - goto DONE_DO_UNGET; - } - - if (sc->cc == '0') { - seendigit = 1; - *b++ = '0'; /* Store the first 0. */ -#ifdef __UCLIBC_MJN3_ONLY__ -#warning CONSIDER: Should leading 0s be skipped before digit grouping? (printf 0 pad) -#endif /* __UCLIBC_MJN3_ONLY__ */ -#if 0 - do { /* But ignore all subsequent 0s. */ - __scan_getc(sc); - } while (sc->cc == '0'); -#endif - } - pass = 0; - lastblock = 0; - do { - i = 0; - while (__isdigit_char_or_EOF(sc->cc)) { - seendigit = 1; - if (i == nbmax) { /* too many digits for a block */ -#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ - if (!pass) { /* treat as nongrouped */ - if (nonzero) { - goto DO_NO_GROUP; - } - goto DO_TRIM_LEADING_ZEROS; - } -#endif - if (nbmax > nblk1) { - goto DONE_DO_UNGET; /* matching failure */ - } - goto DONE_GROUPING_DO_UNGET; /* nbmax == nblk1 */ - } - ++i; - - if (nonzero || (sc->cc != '0')) { - if (b < buf + MAX_DIGITS) { - *b++ = sc->cc; - nonzero = 1; -#ifdef __UCLIBC_HAS_FLOATS__ - } else { - ++exp_adjust; -#endif - } - } - - __scan_getc(sc); - } - - if (i) { /* we saw digits digits */ - if ((i == nblk2) || ((i < nblk2) && !pass)) { - /* (possible) outer grp */ - p = sc->thousands_sep; - if (*p == sc->cc) { /* first byte matches... */ - /* so check if grouping mb char */ - /* Since 1st matched, either match or fail now - * unless EOF (yuk) */ - __scan_getc(sc); - MBG_LOOP: - if (!*++p) { /* is a grouping mb char */ - lastblock = i; - ++pass; - continue; - } - if (*p == sc->cc) { - __scan_getc(sc); - goto MBG_LOOP; - } - /* bad grouping mb char! */ - __scan_ungetc(sc); - if ((sc->cc >= 0) || (p > sc->thousands_sep + 1)) { -#ifdef __UCLIBC_HAS_FLOATS__ - /* We failed to match a thousep mb char, and - * we've read too much to recover. But if - * this is a floating point conversion and - * the initial portion of the decpt mb char - * matches, then we may still be able to - * recover. */ - int k = p - sc->thousands_sep - 1; - - if ((psfs->conv_num > CONV_i) /* float conversion */ - && (!pass || (i == nblk1)) /* possible last */ - && !__memcmp(sc->thousands_sep, sc->fake_decpt, k) - /* and prefix matched, so could be decpt */ - ) { - __scan_getc(sc); - p = sc->fake_decpt + k; - do { - if (!*++p) { - __strcpy(b, sc->decpt); - b += sc->decpt_len; - goto GOT_DECPT; - } - if (*p != sc->cc) { - __scan_ungetc(sc); - break; /* failed */ - } - __scan_getc(sc); - } while (1); - } -#endif /* __UCLIBC_HAS_FLOATS__ */ - goto DONE; - } - /* was EOF and 1st, so recoverable. */ - } - } - if ((i == nblk1) || ((i < nblk1) && !pass)) { - /* got an inner group */ - goto DONE_GROUPING_DO_UNGET; - } - goto DONE_DO_UNGET; /* Matching failure. */ - } /* i != 0 */ - - assert(pass); - - goto DONE_DO_UNGET; - } while (1); - - assert(0); /* Should never get here. */ - } - -#endif /***************** digit grouping **********************/ - - /* Not grouping so first trim all but one leading 0. */ -#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ - DO_TRIM_LEADING_ZEROS: -#endif /* __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ */ - if (sc->cc == '0') { - seendigit = 1; - *b++ = '0'; /* Store the first 0. */ - do { /* But ignore all subsequent 0s. */ - __scan_getc(sc); - } while (sc->cc == '0'); - } - -#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ - DO_NO_GROUP: -#endif /* __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ */ - /* At this point, we're ready to start reading digits. */ - -#define valid_digit(cc,base) (isxdigit(cc) && ((base == 16) || (cc - '0' < base))) - - while (valid_digit(sc->cc,base)) { /* Now for significant digits.*/ - if (b - buf < MAX_DIGITS) { - nonzero = seendigit = 1; /* Set nonzero too 0s trimmed above. */ - *b++ = sc->cc; -#ifdef __UCLIBC_HAS_FLOATS__ - } else { - ++exp_adjust; -#endif - } - __scan_getc(sc); - } - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - DONE_GROUPING_DO_UNGET: -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - if (psfs->conv_num <= CONV_i) { /* integer conversion */ - __scan_ungetc(sc); - *b = 0; /* null-terminate */ - if (!seendigit) { - goto DONE; /* No digits! */ - } - if (psfs->store) { - if (*buf == '-') { - usflag = 0; - } - ++psfs->cnt; - _store_inttype(psfs->cur_ptr, psfs->dataargtype, - (uintmax_t) STRTOUIM(buf, NULL, base, 1-usflag)); - } - return 0; - } - -#ifdef __UCLIBC_HAS_FLOATS__ - - /* At this point, we have everything left of the decimal point or exponent. */ -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - NO_STARTING_DIGIT: -#endif - p = sc->fake_decpt; - do { - if (!*p) { - __strcpy(b, sc->decpt); - b += sc->decpt_len; - break; - } - if (*p != sc->cc) { - if (p > sc->fake_decpt) { - goto DONE_DO_UNGET; /* matching failure (read some of decpt) */ - } - goto DO_DIGIT_CHECK; - } - ++p; - __scan_getc(sc); - } while (1); - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - GOT_DECPT: -#endif - if (!nonzero) { - if (sc->cc == '0') { - assert(exp_adjust == 0); - *b++ = '0'; - ++exp_adjust; - seendigit = 1; - do { - --exp_adjust; - __scan_getc(sc); - } while (sc->cc == '0'); - } - } - - while (valid_digit(sc->cc,base)) { /* Process fractional digits.*/ - if (b - buf < MAX_DIGITS) { - seendigit = 1; - *b++ = sc->cc; - } - __scan_getc(sc); - } - - DO_DIGIT_CHECK: - /* Hmm... no decimal point. */ - if (!seendigit) { - static const unsigned char nan_inf_str[] = "an\0nfinity"; - - if (base == 16) { /* We had a prefix, but no digits! */ - goto DONE_DO_UNGET; /* matching failure */ - } - - /* Avoid tolower problems for INFINITY in the tr_TR locale. (yuk)*/ -#undef TOLOWER -#define TOLOWER(C) ((C)|0x20) - - switch (TOLOWER(sc->cc)) { - case 'i': - p = nan_inf_str + 3; - break; - case 'n': - p = nan_inf_str; - break; - default: - /* No digits and not inf or nan. */ - goto DONE_DO_UNGET; - } - - *b++ = sc->cc; - - do { - __scan_getc(sc); - if (TOLOWER(sc->cc) == *p) { - *b++ = sc->cc; - ++p; - continue; - } - if (!*p || (p == nan_inf_str + 5)) { /* match nan/infinity or inf */ - goto GOT_FLOAT; - } - /* Unrecoverable. Even if on 1st char, we had no digits. */ - goto DONE_DO_UNGET; - } while (1); - } - - /* If we get here, we had some digits. */ - - if ( -#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ - ((base == 16) && (((sc->cc)|0x20) == 'p')) || -#endif - (((sc->cc)|0x20) == 'e') - ) { /* Process an exponent. */ - *b++ = sc->cc; - - __scan_getc(sc); - if (sc->cc < 0) { - goto DONE_DO_UNGET; /* matching failure.. no exponent digits */ - } - - if ((sc->cc == '+') || (sc->cc == '-')) { /* Signed exponent? */ - *b++ = sc->cc; - __scan_getc(sc); - } - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Fix MAX_EXP_DIGITS! -#endif -#define MAX_EXP_DIGITS 20 - assert(seendigit); - seendigit = 0; - nonzero = 0; - - if (sc->cc == '0') { - seendigit = 1; - *b++ = '0'; - do { - __scan_getc(sc); - } while (sc->cc == '0'); - } - - while (__isdigit_char_or_EOF(sc->cc)) { /* Exponent digits (base 10).*/ - if (seendigit < MAX_EXP_DIGITS) { - ++seendigit; - *b++ = sc->cc; - } - __scan_getc(sc); - } - - if (!seendigit) { /* No digits. Unrecoverable. */ - goto DONE_DO_UNGET; - } - } - - - GOT_FLOAT: - *b = 0; - { - __fpmax_t x; - char *e; - x = __strtofpmax(buf, &e, exp_adjust); - assert(!*e); - if (psfs->store) { - if (psfs->dataargtype & PA_FLAG_LONG_LONG) { - *((long double *)psfs->cur_ptr) = (long double) x; - } else if (psfs->dataargtype & PA_FLAG_LONG) { - *((double *)psfs->cur_ptr) = (double) x; - } else { - *((float *)psfs->cur_ptr) = (float) x; - } - ++psfs->cnt; - } - __scan_ungetc(sc); - return 0; - } -#endif /* __UCLIBC_HAS_FLOATS__ */ - - DONE_DO_UNGET: - __scan_ungetc(sc); - DONE: - return -2; /* Matching failure. */ - -} -#endif -/**********************************************************************/ +#define L_scanf +#include "_scanf.c" diff --git a/libc/stdio/setbuf.c b/libc/stdio/setbuf.c index 02a4736ac..6de2c91a1 100644 --- a/libc/stdio/setbuf.c +++ b/libc/stdio/setbuf.c @@ -7,9 +7,11 @@ #include "_stdio.h" +libc_hidden_proto(setvbuf) + void setbuf(FILE * __restrict stream, register char * __restrict buf) { #ifdef __STDIO_BUFFERS - __setvbuf(stream, buf, ((buf != NULL) ? _IOFBF : _IONBF), BUFSIZ); + setvbuf(stream, buf, ((buf != NULL) ? _IOFBF : _IONBF), BUFSIZ); #endif } diff --git a/libc/stdio/setbuffer.c b/libc/stdio/setbuffer.c index d1f12a1af..3ca4fb7f8 100644 --- a/libc/stdio/setbuffer.c +++ b/libc/stdio/setbuffer.c @@ -7,6 +7,8 @@ #include "_stdio.h" +libc_hidden_proto(setvbuf) + /* A BSD function. The implementation matches the linux man page, * except that we do not bother calling setvbuf if not configured * for stream buffering. @@ -16,6 +18,6 @@ void setbuffer(FILE * __restrict stream, register char * __restrict buf, size_t size) { #ifdef __STDIO_BUFFERS - __setvbuf(stream, buf, (buf ? _IOFBF : _IONBF), size); + setvbuf(stream, buf, (buf ? _IOFBF : _IONBF), size); #endif } diff --git a/libc/stdio/setlinebuf.c b/libc/stdio/setlinebuf.c index 56e89e11b..29b2bdeac 100644 --- a/libc/stdio/setlinebuf.c +++ b/libc/stdio/setlinebuf.c @@ -7,6 +7,8 @@ #include "_stdio.h" +libc_hidden_proto(setvbuf) + /* A BSD function. The implementation matches the linux man page, * except that we do not bother calling setvbuf if not configured * for stream buffering. @@ -15,6 +17,6 @@ void setlinebuf(FILE * __restrict stream) { #ifdef __STDIO_BUFFERS - __setvbuf(stream, NULL, _IOLBF, (size_t) 0); + setvbuf(stream, NULL, _IOLBF, (size_t) 0); #endif } diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c index d12d1576a..c1566504a 100644 --- a/libc/stdio/setvbuf.c +++ b/libc/stdio/setvbuf.c @@ -14,7 +14,8 @@ #error Assumption violated for buffering mode flags #endif -int attribute_hidden __setvbuf(register FILE * __restrict stream, register char * __restrict buf, +libc_hidden_proto(setvbuf) +int setvbuf(register FILE * __restrict stream, register char * __restrict buf, int mode, size_t size) { #ifdef __STDIO_BUFFERS @@ -104,4 +105,4 @@ int attribute_hidden __setvbuf(register FILE * __restrict stream, register char #endif } -strong_alias(__setvbuf,setvbuf) +libc_hidden_def(setvbuf) diff --git a/libc/stdio/snprintf.c b/libc/stdio/snprintf.c index a1ea79fc0..ef9c69215 100644 --- a/libc/stdio/snprintf.c +++ b/libc/stdio/snprintf.c @@ -12,17 +12,20 @@ #warning Skipping snprintf since no vsnprintf! #else -int attribute_hidden __snprintf(char *__restrict buf, size_t size, +libc_hidden_proto(vsnprintf) + +libc_hidden_proto(snprintf) +int snprintf(char *__restrict buf, size_t size, const char * __restrict format, ...) { va_list arg; int rv; va_start(arg, format); - rv = __vsnprintf(buf, size, format, arg); + rv = vsnprintf(buf, size, format, arg); va_end(arg); return rv; } -strong_alias(__snprintf,snprintf) +libc_hidden_def(snprintf) #endif diff --git a/libc/stdio/sprintf.c b/libc/stdio/sprintf.c index 5778c011d..360245366 100644 --- a/libc/stdio/sprintf.c +++ b/libc/stdio/sprintf.c @@ -12,17 +12,20 @@ #warning Skipping sprintf since no vsnprintf! #else -int attribute_hidden __sprintf(char *__restrict buf, const char * __restrict format, ...) +libc_hidden_proto(vsnprintf) + +libc_hidden_proto(sprintf) +int sprintf(char *__restrict buf, const char * __restrict format, ...) { va_list arg; int rv; va_start(arg, format); - rv = __vsnprintf(buf, SIZE_MAX, format, arg); + rv = vsnprintf(buf, SIZE_MAX, format, arg); va_end(arg); return rv; } -strong_alias(__sprintf,sprintf) +libc_hidden_def(sprintf) #endif diff --git a/libc/stdio/sscanf.c b/libc/stdio/sscanf.c new file mode 100644 index 000000000..f53c06545 --- /dev/null +++ b/libc/stdio/sscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_sscanf +#include "_scanf.c" diff --git a/libc/stdio/swprintf.c b/libc/stdio/swprintf.c index b373df8bd..0c209fe4b 100644 --- a/libc/stdio/swprintf.c +++ b/libc/stdio/swprintf.c @@ -5,12 +5,12 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define vswprintf __vswprintf - #include "_stdio.h" #include <stdarg.h> #include <wchar.h> +libc_hidden_proto(vswprintf) + #ifndef __STDIO_BUFFERS #warning Skipping swprintf since no buffering! #else /* __STDIO_BUFFERS */ diff --git a/libc/stdio/swscanf.c b/libc/stdio/swscanf.c new file mode 100644 index 000000000..06f8cb75f --- /dev/null +++ b/libc/stdio/swscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_swscanf +#include "_scanf.c" diff --git a/libc/stdio/tempnam.c b/libc/stdio/tempnam.c index d626dc0f8..43cbf781b 100644 --- a/libc/stdio/tempnam.c +++ b/libc/stdio/tempnam.c @@ -20,6 +20,8 @@ #include <string.h> #include "../misc/internals/tempname.h" +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 as follows: First the environment variable "TMPDIR" is checked. @@ -38,6 +40,6 @@ tempnam (const char *dir, const char *pfx) if (__gen_tempname (buf, __GT_NOCREATE)) return NULL; - return __strdup (buf); + return strdup (buf); } diff --git a/libc/stdio/tmpfile.c b/libc/stdio/tmpfile.c index 606fcc436..f83944539 100644 --- a/libc/stdio/tmpfile.c +++ b/libc/stdio/tmpfile.c @@ -16,14 +16,15 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define fdopen __fdopen -#define remove __remove - #include <features.h> #include <stdio.h> #include <unistd.h> #include "../misc/internals/tempname.h" +libc_hidden_proto(fdopen) +libc_hidden_proto(remove) +libc_hidden_proto(close) + /* This returns a new stream opened on a temporary file (generated by tmpnam). The file is opened with mode "w+b" (binary read/write). If we couldn't generate a unique filename or the file couldn't @@ -45,10 +46,10 @@ FILE * tmpfile (void) (void) remove (buf); if ((f = fdopen (fd, "w+b")) == NULL) - __close (fd); + close (fd); return f; } #ifdef __UCLIBC_HAS_LFS__ -weak_alias(tmpfile,tmpfile64) +strong_alias(tmpfile,tmpfile64) #endif diff --git a/libc/stdio/tmpnam.c b/libc/stdio/tmpnam.c index df2399e66..bc4ffeb6a 100644 --- a/libc/stdio/tmpnam.c +++ b/libc/stdio/tmpnam.c @@ -1,48 +1,55 @@ -/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc. +/* Copyright (C) 1991,1993,1996-1999,2000 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ #include <stdio.h> #include <string.h> #include "../misc/internals/tempname.h" +libc_hidden_proto(memcpy) + static char tmpnam_buffer[L_tmpnam]; /* Generate a unique filename in P_tmpdir. - This function is *not* thread safe when S == NULL! -*/ -char * tmpnam (char *s) + + This function is *not* thread safe! */ +char * +tmpnam (char *s) { - /* By using two buffers we manage to be thread safe in the case - where S != NULL. */ - char tmpbuf[L_tmpnam]; + /* By using two buffers we manage to be thread safe in the case + where S != NULL. */ + char tmpbufmem[L_tmpnam]; + char *tmpbuf = s ?: tmpbufmem; - /* In the following call we use the buffer pointed to by S if - non-NULL although we don't know the size. But we limit the size - to L_tmpnam characters in any case. */ - if (__path_search (s ? : tmpbuf, L_tmpnam, NULL, NULL, 0)) - return NULL; + /* In the following call we use the buffer pointed to by S if + non-NULL although we don't know the size. But we limit the size + to L_tmpnam characters in any case. */ + if (__builtin_expect (__path_search (tmpbuf, L_tmpnam, NULL, NULL, 0), + 0)) + return NULL; - if (__gen_tempname (s ? : tmpbuf, __GT_NOCREATE)) - return NULL; + if (__builtin_expect (__gen_tempname (tmpbuf, __GT_NOCREATE), 0)) + return NULL; - if (s == NULL) - return (char *) __memcpy (tmpnam_buffer, tmpbuf, L_tmpnam); + if (s == NULL) + return (char *) memcpy (tmpnam_buffer, tmpbuf, L_tmpnam); - return s; + return s; } +link_warning (tmpnam, + "the use of `tmpnam' is dangerous, better use `mkstemp'") diff --git a/libc/stdio/ungetc.c b/libc/stdio/ungetc.c index de3f1d16b..d900928b2 100644 --- a/libc/stdio/ungetc.c +++ b/libc/stdio/ungetc.c @@ -24,7 +24,8 @@ * (See section 7.19.6.2 of the C9X rationale -- WG14/N897.) */ -int attribute_hidden __ungetc(int c, register FILE *stream) +libc_hidden_proto(ungetc) +int ungetc(int c, register FILE *stream) { __STDIO_AUTO_THREADLOCK_VAR; @@ -75,4 +76,4 @@ int attribute_hidden __ungetc(int c, register FILE *stream) return c; } -strong_alias(__ungetc,ungetc) +libc_hidden_def(ungetc) diff --git a/libc/stdio/ungetwc.c b/libc/stdio/ungetwc.c index c6a99dd9d..579022240 100644 --- a/libc/stdio/ungetwc.c +++ b/libc/stdio/ungetwc.c @@ -12,7 +12,8 @@ * as reset stream->__ungot_width[1] for use by _stdio_adjpos(). */ -wint_t attribute_hidden __ungetwc(wint_t c, register FILE *stream) +libc_hidden_proto(ungetwc) +wint_t ungetwc(wint_t c, register FILE *stream) { __STDIO_AUTO_THREADLOCK_VAR; @@ -46,4 +47,4 @@ wint_t attribute_hidden __ungetwc(wint_t c, register FILE *stream) return c; } -strong_alias(__ungetwc,ungetwc) +libc_hidden_def(ungetwc) diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c index ca110cbd1..7a34f6870 100644 --- a/libc/stdio/vasprintf.c +++ b/libc/stdio/vasprintf.c @@ -5,12 +5,14 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ -#define open_memstream __open_memstream +#include <features.h> +#ifdef __USE_GNU #include "_stdio.h" #include <stdarg.h> #include <bits/uClibc_va_copy.h> + #ifdef __UCLIBC_MJN3_ONLY__ /* Do the memstream stuff inline to avoid fclose and the openlist? */ #warning CONSIDER: avoid open_memstream call? @@ -20,7 +22,16 @@ #warning Skipping vasprintf since no vsnprintf! #else -int attribute_hidden __vasprintf(char **__restrict buf, const char * __restrict format, +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +libc_hidden_proto(open_memstream) +libc_hidden_proto(fclose) +libc_hidden_proto(vfprintf) +#else +libc_hidden_proto(vsnprintf) +#endif + +libc_hidden_proto(vasprintf) +int vasprintf(char **__restrict buf, const char * __restrict format, va_list arg) { #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ @@ -32,7 +43,7 @@ int attribute_hidden __vasprintf(char **__restrict buf, const char * __restrict *buf = NULL; if ((f = open_memstream(buf, &size)) != NULL) { - rv = __vfprintf(f, format, arg); + rv = vfprintf(f, format, arg); fclose(f); if (rv < 0) { free(*buf); @@ -54,14 +65,14 @@ int attribute_hidden __vasprintf(char **__restrict buf, const char * __restrict int rv; va_copy(arg2, arg); - rv = __vsnprintf(NULL, 0, format, arg2); + rv = vsnprintf(NULL, 0, format, arg2); va_end(arg2); *buf = NULL; if (rv >= 0) { if ((*buf = malloc(++rv)) != NULL) { - if ((rv = __vsnprintf(*buf, rv, format, arg)) < 0) { + if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) { free(*buf); *buf = NULL; } @@ -74,6 +85,7 @@ int attribute_hidden __vasprintf(char **__restrict buf, const char * __restrict #endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ } -strong_alias(__vasprintf,vasprintf) +libc_hidden_def(vasprintf) #endif +#endif diff --git a/libc/stdio/vdprintf.c b/libc/stdio/vdprintf.c index 4e066f169..67adf47be 100644 --- a/libc/stdio/vdprintf.c +++ b/libc/stdio/vdprintf.c @@ -5,10 +5,17 @@ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ +#include <features.h> + +#ifdef __USE_GNU #include "_stdio.h" #include <stdarg.h> -int attribute_hidden __vdprintf(int filedes, const char * __restrict format, va_list arg) +libc_hidden_proto(vfprintf) +libc_hidden_proto(fflush_unlocked) + +libc_hidden_proto(vdprintf) +int vdprintf(int filedes, const char * __restrict format, va_list arg) { FILE f; int rv; @@ -51,11 +58,11 @@ int attribute_hidden __vdprintf(int filedes, const char * __restrict format, va_ #endif f.__nextopen = NULL; - rv = __vfprintf(&f, format, arg); + rv = vfprintf(&f, format, arg); #ifdef __STDIO_BUFFERS /* If not buffering, then fflush is unnecessary. */ - if ((rv > 0) && __fflush_unlocked(&f)) { + if ((rv > 0) && fflush_unlocked(&f)) { rv = -1; } #endif @@ -64,4 +71,5 @@ int attribute_hidden __vdprintf(int filedes, const char * __restrict format, va_ return rv; } -strong_alias(__vdprintf,vdprintf) +libc_hidden_def(vdprintf) +#endif diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c index bdbf0c788..78b725fd9 100644 --- a/libc/stdio/vfprintf.c +++ b/libc/stdio/vfprintf.c @@ -1,1929 +1,9 @@ -/* Copyright (C) 2002-2004 Manuel Novoa III - * My stdio library for linux and (soon) elks. +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* This code needs a lot of clean up. Some of that is on hold until uClibc - * gets a better configuration system (on Erik's todo list). - * The other cleanup will take place during the implementation/integration of - * the wide char (un)formatted i/o functions which I'm currently working on. - */ - -/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! - * - * This code is currently under development. Also, I plan to port - * it to elks which is a 16-bit environment with a fairly limited - * compiler. Therefore, please refrain from modifying this code - * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel - * - * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ - - -/* April 1, 2002 - * Initialize thread locks for fake files in vsnprintf and vdprintf. - * reported by Erik Andersen (andersen@codepoet.com) - * Fix an arg promotion handling bug in _do_one_spec for %c. - * reported by Ilguiz Latypov <ilatypov@superbt.com> - * - * May 10, 2002 - * Remove __isdigit and use new ctype.h version. - * Add conditional setting of QUAL_CHARS for size_t and ptrdiff_t. - * - * Aug 16, 2002 - * Fix two problems that showed up with the python 2.2.1 tests; one - * involving %o and one involving %f. - * - * Oct 28, 2002 - * Fix a problem in vasprintf (reported by vodz a while back) when built - * without custom stream support. In that case, it is necessary to do - * a va_copy. - * Make sure each va_copy has a matching va_end, as required by C99. - * - * Nov 4, 2002 - * Add locale-specific grouping support for integer decimal conversion. - * Add locale-specific decimal point support for floating point conversion. - * Note: grouping will have to wait for _dtostr() rewrite. - * Add printf wchar support for %lc (%C) and %ls (%S). - * Require printf format strings to be valid multibyte strings beginning and - * ending in their initial shift state, as per the stds. - * - * Nov 21, 2002 - * Add *wprintf functions. Currently they don't support floating point - * conversions. That will wait until the rewrite of _dtostr. - * - * Aug 1, 2003 - * Optional hexadecimal float notation support for %a/%A. - * Floating point output now works for *wprintf. - * Support for glibc locale-specific digit grouping for floats. - * Misc bug fixes. - * - * Aug 31, 2003 - * Fix precision bug for %g conversion specifier when using %f style. - * - * Sep 5, 2003 - * Implement *s*scanf for the non-buffered stdio case with old_vfprintf. - * - * Sep 23, 2003 - * vfprintf was not always checking for narrow stream orientation. - */ - -/* TODO: - * - * Should we validate that *printf format strings are valid multibyte - * strings in the current locale? ANSI/ISO C99 seems to imply this - * and Plauger's printf implementation in his Standard C Library book - * treats this as an error. - */ - -#define strnlen __strnlen -#define wcslen __wcslen -#define wcsnlen __wcsnlen -#define wcsrtombs __wcsrtombs -#define mbsrtowcs __mbsrtowcs -#define btowc __btowc -#define wcrtomb __wcrtomb -#define fputws __fputws - -#define _ISOC99_SOURCE /* for ULLONG primarily... */ -#define _GNU_SOURCE -#include <features.h> -#include "_stdio.h" -#include <stdlib.h> -#include <string.h> -#include <stddef.h> -#include <ctype.h> -#include <limits.h> -#include <stdarg.h> -#include <assert.h> -#include <stdint.h> -#include <errno.h> -#include <locale.h> - -#define __PRINTF_INFO_NO_BITFIELD -#include <printf.h> - -#ifdef __UCLIBC_HAS_THREADS__ -#include <stdio_ext.h> -#include <pthread.h> -#endif /* __UCLIBC_HAS_THREADS__ */ - -#ifdef __UCLIBC_HAS_WCHAR__ -#include <wchar.h> -#endif /* __UCLIBC_HAS_WCHAR__ */ - -#include <bits/uClibc_uintmaxtostr.h> -#include <bits/uClibc_va_copy.h> - -/* Some older or broken gcc toolchains define LONG_LONG_MAX but not - * LLONG_MAX. Since LLONG_MAX is part of the standard, that's what - * we use. So complain if we do not have it but should. - */ -#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX) -#error Apparently, LONG_LONG_MAX is defined but LLONG_MAX is not. You need to fix your toolchain headers to support the standard macros for (unsigned) long long. -#endif - -/**********************************************************************/ -/* These provide some control over printf's feature set */ - -/* This is undefined below depeding on uClibc's configuration. */ -#define __STDIO_PRINTF_FLOAT 1 - -/* Now controlled by uClibc_stdio.h. */ -/* #define __UCLIBC_HAS_PRINTF_M_SPEC__ */ - - -/**********************************************************************/ - -#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_FLOATS__) -#undef __STDIO_PRINTF_FLOAT -#endif - -#ifdef __BCC__ -#undef __STDIO_PRINTF_FLOAT -#endif - -#ifdef __STDIO_PRINTF_FLOAT -#include <float.h> -#include <bits/uClibc_fpmax.h> -#else /* __STDIO_PRINTF_FLOAT */ -#undef L__fpmaxtostr -#endif /* __STDIO_PRINTF_FLOAT */ - - -#undef __STDIO_HAS_VSNPRINTF -#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) -#define __STDIO_HAS_VSNPRINTF 1 -#endif - -/**********************************************************************/ - -/* Now controlled by uClibc_stdio.h. */ -/* #define __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ - -/* TODO -- move these to a configuration section? */ -#define MAX_FIELD_WIDTH 4095 - -#ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_register_printf_function -/* emit only once */ -#warning WISHLIST: Make MAX_USER_SPEC configurable? -#warning WISHLIST: Make MAX_ARGS_PER_SPEC configurable? -#endif -#endif /* __UCLIBC_MJN3_ONLY__ */ - -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ - -#define MAX_USER_SPEC 10 -#define MAX_ARGS_PER_SPEC 5 - -#else /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ - -#undef MAX_USER_SPEC -#define MAX_ARGS_PER_SPEC 1 - -#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ - -#if MAX_ARGS_PER_SPEC < 1 -#error MAX_ARGS_PER_SPEC < 1! -#undef MAX_ARGS_PER_SPEC -#define MAX_ARGS_PER_SPEC 1 -#endif - -#if defined(NL_ARGMAX) && (NL_ARGMAX < 9) -#error NL_ARGMAX < 9! -#endif - -#if defined(NL_ARGMAX) && (NL_ARGMAX >= (MAX_ARGS_PER_SPEC + 2)) -#define MAX_ARGS NL_ARGMAX -#else -/* N for spec itself, plus 1 each for width and precision */ -#define MAX_ARGS (MAX_ARGS_PER_SPEC + 2) -#endif - -/**********************************************************************/ - -#define __PA_FLAG_INTMASK \ - (__PA_FLAG_CHAR|PA_FLAG_SHORT|__PA_FLAG_INT|PA_FLAG_LONG|PA_FLAG_LONG_LONG) - -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ -extern printf_function _custom_printf_handler[MAX_USER_SPEC]; -extern printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC]; -extern char *_custom_printf_spec; -#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ - -/**********************************************************************/ - -#define SPEC_FLAGS " +0-#'I" -enum { - FLAG_SPACE = 0x01, - FLAG_PLUS = 0x02, /* must be 2 * FLAG_SPACE */ - FLAG_ZERO = 0x04, - FLAG_MINUS = 0x08, /* must be 2 * FLAG_ZERO */ - FLAG_HASH = 0x10, - FLAG_THOUSANDS = 0x20, - FLAG_I18N = 0x40, /* only works for d, i, u */ - FLAG_WIDESTREAM = 0x80 -}; - -/**********************************************************************/ - -/* float layout 01234567890123456789 TODO: B?*/ -#define SPEC_CHARS "npxXoudifFeEgGaACScs" -enum { - CONV_n = 0, - CONV_p, - CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i, - CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A, - CONV_C, CONV_S, CONV_c, CONV_s, -#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ - CONV_m, -#endif - CONV_custom0 /* must be last */ -}; - -/* p x X o u d i */ -#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 10 } - -#define SPEC_RANGES { CONV_n, CONV_p, CONV_i, CONV_A, \ - CONV_C, CONV_S, CONV_c, CONV_s, CONV_custom0 } - -#define SPEC_OR_MASK { \ - /* n */ (PA_FLAG_PTR|PA_INT), \ - /* p */ PA_POINTER, \ - /* oxXudi */ PA_INT, \ - /* fFeEgGaA */ PA_DOUBLE, \ - /* C */ PA_WCHAR, \ - /* S */ PA_WSTRING, \ - /* c */ PA_CHAR, \ - /* s */ PA_STRING, \ -} - -#define SPEC_AND_MASK { \ - /* n */ (PA_FLAG_PTR|__PA_INTMASK), \ - /* p */ PA_POINTER, \ - /* oxXudi */ (__PA_INTMASK), \ - /* fFeEgGaA */ (PA_FLAG_LONG_DOUBLE|PA_DOUBLE), \ - /* C */ (PA_WCHAR), \ - /* S */ (PA_WSTRING), \ - /* c */ (PA_CHAR), \ - /* s */ (PA_STRING), \ -} - -/**********************************************************************/ -/* - * In order to ease translation to what arginfo and _print_info._flags expect, - * we map: 0:int 1:char 2:longlong 4:long 8:short - * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) - */ - -/* TODO -- Fix the table below to take into account stdint.h. */ -/* #ifndef LLONG_MAX */ -/* #error fix QUAL_CHARS for no long long! Affects 'L', 'j', 'q', 'll'. */ -/* #else */ -/* #if LLONG_MAX != INTMAX_MAX */ -/* #error fix QUAL_CHARS intmax_t entry 'j'! */ -/* #endif */ -/* #endif */ - -#ifdef PDS -#error PDS already defined! -#endif -#ifdef SS -#error SS already defined! -#endif -#ifdef IMS -#error IMS already defined! -#endif - -#if PTRDIFF_MAX == INT_MAX -#define PDS 0 -#elif PTRDIFF_MAX == LONG_MAX -#define PDS 4 -#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) -#define PDS 8 -#else -#error fix QUAL_CHARS ptrdiff_t entry 't'! -#endif - -#if SIZE_MAX == UINT_MAX -#define SS 0 -#elif SIZE_MAX == ULONG_MAX -#define SS 4 -#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) -#define SS 8 -#else -#error fix QUAL_CHARS size_t entries 'z', 'Z'! -#endif - -#if INTMAX_MAX == INT_MAX -#define IMS 0 -#elif INTMAX_MAX == LONG_MAX -#define IMS 4 -#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) -#define IMS 8 -#else -#error fix QUAL_CHARS intmax_t entry 'j'! -#endif - -#define QUAL_CHARS { \ - /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int */ \ - /* q:long_long Z:(s)size_t */ \ - 'h', 'l', 'L', 'j', 'z', 't', 'q', 'Z', 0, \ - 2, 4, 8, IMS, SS, PDS, 8, SS, 0, /* TODO -- fix!!! */\ - 1, 8 \ -} - -/**********************************************************************/ - -#ifdef __STDIO_VA_ARG_PTR -#ifdef __BCC__ -#define __va_arg_ptr(ap,type) (((type *)(ap += sizeof(type))) - 1) -#endif - -#if 1 -#ifdef __GNUC__ -/* TODO -- need other than for 386 as well! */ - -#ifndef __va_rounded_size -#define __va_rounded_size(TYPE) \ - (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) -#endif -#define __va_arg_ptr(AP, TYPE) \ - (AP = (va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ - ((void *) ((char *) (AP) - __va_rounded_size (TYPE)))) -#endif -#endif -#endif /* __STDIO_VA_ARG_PTR */ - -#ifdef __va_arg_ptr -#define GET_VA_ARG(AP,F,TYPE,ARGS) (*(AP) = __va_arg_ptr(ARGS,TYPE)) -#define GET_ARG_VALUE(AP,F,TYPE) (*((TYPE *)(*(AP)))) -#else -typedef union { - wchar_t wc; - unsigned int u; - unsigned long ul; -#ifdef ULLONG_MAX - unsigned long long ull; -#endif -#ifdef __STDIO_PRINTF_FLOAT - double d; - long double ld; -#endif /* __STDIO_PRINTF_FLOAT */ - void *p; -} argvalue_t; - -#define GET_VA_ARG(AU,F,TYPE,ARGS) (AU->F = va_arg(ARGS,TYPE)) -#define GET_ARG_VALUE(AU,F,TYPE) ((TYPE)((AU)->F)) -#endif - -typedef struct { - const char *fmtpos; /* TODO: move below struct?? */ - struct printf_info info; -#ifdef NL_ARGMAX - int maxposarg; /* > 0 if args are positional, 0 if not, -1 if unknown */ -#endif /* NL_ARGMAX */ - int num_data_args; /* TODO: use sentinal??? */ - unsigned int conv_num; - unsigned char argnumber[4]; /* width | prec | 1st data | unused */ - int argtype[MAX_ARGS]; - va_list arg; -#ifdef __va_arg_ptr - void *argptr[MAX_ARGS]; -#else -/* if defined(NL_ARGMAX) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__) */ - /* While this is wasteful of space in the case where pos args aren't - * enabled, it is also needed to support custom printf handlers. */ - argvalue_t argvalue[MAX_ARGS]; -#endif -} ppfs_t; /* parse printf format state */ - -/**********************************************************************/ - -/* TODO: fix printf to return 0 and set errno if format error. Standard says - only returns -1 if sets error indicator for the stream. */ - -#ifdef __STDIO_PRINTF_FLOAT -typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, - intptr_t buf); - -extern ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, - __fp_outfunc_t fp_outfunc) attribute_hidden; -#endif - -extern int _ppfs_init(ppfs_t *ppfs, const char *fmt0) attribute_hidden; /* validates */ -extern void _ppfs_prepargs(ppfs_t *ppfs, va_list arg) attribute_hidden; /* sets posargptrs */ -extern void _ppfs_setargs(ppfs_t *ppfs) attribute_hidden; /* sets argptrs for current spec */ -extern int _ppfs_parsespec(ppfs_t *ppfs) attribute_hidden; /* parses specifier */ - -extern void _store_inttype(void *dest, int desttype, uintmax_t val) attribute_hidden; -extern uintmax_t _load_inttype(int desttype, const void *src, int uflag) attribute_hidden; - -/**********************************************************************/ -#ifdef L_parse_printf_format - -/* NOTE: This function differs from the glibc version in that parsing stops - * upon encountering an invalid conversion specifier. Since this is the way - * my printf functions work, I think it makes sense to do it that way here. - * Unfortunately, since glibc sets the return type as size_t, we have no way - * of returning that the template is illegal, other than returning 0. - */ - -size_t parse_printf_format(register const char *template, - size_t n, register int *argtypes) -{ - ppfs_t ppfs; - size_t i; - size_t count = 0; - - if (_ppfs_init(&ppfs, template) >= 0) { -#ifdef NL_ARGMAX - if (ppfs.maxposarg > 0) { /* Using positional args. */ - count = ppfs.maxposarg; - if (n > count) { - n = count; - } - for (i = 0 ; i < n ; i++) { - *argtypes++ = ppfs.argtype[i]; - } - } else { /* Not using positional args. */ -#endif /* NL_ARGMAX */ - while (*template) { - if ((*template == '%') && (*++template != '%')) { - ppfs.fmtpos = template; - _ppfs_parsespec(&ppfs); /* Can't fail. */ - template = ppfs.fmtpos; /* Update to one past spec end. */ - if (ppfs.info.width == INT_MIN) { - ++count; - if (n > 0) { - *argtypes++ = PA_INT; - --n; - } - } - if (ppfs.info.prec == INT_MIN) { - ++count; - if (n > 0) { - *argtypes++ = PA_INT; - --n; - } - } - for (i = 0 ; i < ppfs.num_data_args ; i++) { - if ((ppfs.argtype[i]) != __PA_NOARG) { - ++count; - if (n > 0) { - *argtypes++ = ppfs.argtype[i]; - --n; - } - } - } - } else { - ++template; - } - } -#ifdef NL_ARGMAX - } -#endif /* NL_ARGMAX */ - } - - return count; -} - -#endif -/**********************************************************************/ -#ifdef L__ppfs_init - -int attribute_hidden _ppfs_init(register ppfs_t *ppfs, const char *fmt0) -{ - int r; - - /* First, zero out everything... argnumber[], argtype[], argptr[] */ - __memset(ppfs, 0, sizeof(ppfs_t)); /* TODO: nonportable???? */ -#ifdef NL_ARGMAX - --ppfs->maxposarg; /* set to -1 */ -#endif /* NL_ARGMAX */ - ppfs->fmtpos = fmt0; -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Make checking of the format string in C locale an option. -#endif -#ifdef __UCLIBC_HAS_LOCALE__ - /* To support old programs, don't check mb validity if in C locale. */ - if (((__UCLIBC_CURLOCALE_DATA).encoding) != __ctype_encoding_7_bit) { - /* ANSI/ISO C99 requires format string to be a valid multibyte string - * beginning and ending in its initial shift state. */ - static const char invalid_mbs[] = "Invalid multibyte format string."; - mbstate_t mbstate; - const char *p; - mbstate.__mask = 0; /* Initialize the mbstate. */ - p = fmt0; - if (mbsrtowcs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { - ppfs->fmtpos = invalid_mbs; - return -1; - } - } -#endif /* __UCLIBC_HAS_LOCALE__ */ - /* now set all argtypes to no-arg */ - { -#if 1 - /* TODO - use memset here since already "paid for"? */ - register int *p = ppfs->argtype; - - r = MAX_ARGS; - do { - *p++ = __PA_NOARG; - } while (--r); -#else - /* TODO -- get rid of this?? */ - register char *p = (char *) ((MAX_ARGS-1) * sizeof(int)); - - do { - *((int *)(((char *)ppfs) + ((int)p) + offsetof(ppfs_t,argtype))) = __PA_NOARG; - p -= sizeof(int); - } while (p); -#endif - } - - /* - * Run through the entire format string to validate it and initialize - * the positional arg numbers (if any). - */ - { - register const char *fmt = fmt0; - - while (*fmt) { - if ((*fmt == '%') && (*++fmt != '%')) { - ppfs->fmtpos = fmt; /* back up to the '%' */ - if ((r = _ppfs_parsespec(ppfs)) < 0) { - return -1; - } - fmt = ppfs->fmtpos; /* update to one past end of spec */ - } else { - ++fmt; - } - } - ppfs->fmtpos = fmt0; /* rewind */ - } - -#ifdef NL_MAX_ARG - /* If we have positional args, make sure we know all the types. */ - { - register int *p = ppfs->argtype; - r = ppfs->maxposarg; - while (--r >= 0) { - if ( *p == __PA_NOARG ) { /* missing arg type!!! */ - return -1; - } - ++p; - } - } -#endif /* NL_MAX_ARG */ - - return 0; -} -#endif -/**********************************************************************/ -#ifdef L__ppfs_prepargs -void attribute_hidden _ppfs_prepargs(register ppfs_t *ppfs, va_list arg) -{ - int i; - - va_copy(ppfs->arg, arg); - -#ifdef NL_ARGMAX - if ((i = ppfs->maxposarg) > 0) { /* init for positional args */ - ppfs->num_data_args = i; - ppfs->info.width = ppfs->info.prec = ppfs->maxposarg = 0; - _ppfs_setargs(ppfs); - ppfs->maxposarg = i; - } -#endif /* NL_ARGMAX */ -} -#endif -/**********************************************************************/ -#ifdef L__ppfs_setargs - -void attribute_hidden _ppfs_setargs(register ppfs_t *ppfs) -{ -#ifdef __va_arg_ptr - register void **p = ppfs->argptr; -#else - register argvalue_t *p = ppfs->argvalue; -#endif - int i; - -#ifdef NL_ARGMAX - if (ppfs->maxposarg == 0) { /* initing for or no pos args */ -#endif /* NL_ARGMAX */ - if (ppfs->info.width == INT_MIN) { - ppfs->info.width = -#ifdef __va_arg_ptr - *(int *) -#endif - GET_VA_ARG(p,u,unsigned int,ppfs->arg); - } - if (ppfs->info.prec == INT_MIN) { - ppfs->info.prec = -#ifdef __va_arg_ptr - *(int *) -#endif - GET_VA_ARG(p,u,unsigned int,ppfs->arg); - } - i = 0; - while (i < ppfs->num_data_args) { - switch(ppfs->argtype[i++]) { - case (PA_INT|PA_FLAG_LONG_LONG): -#ifdef ULLONG_MAX - GET_VA_ARG(p,ull,unsigned long long,ppfs->arg); - break; -#endif - case (PA_INT|PA_FLAG_LONG): -#if ULONG_MAX != UINT_MAX - GET_VA_ARG(p,ul,unsigned long,ppfs->arg); - break; -#endif - case PA_CHAR: /* TODO - be careful */ - /* ... users could use above and really want below!! */ - case (PA_INT|__PA_FLAG_CHAR):/* TODO -- translate this!!! */ - case (PA_INT|PA_FLAG_SHORT): - case PA_INT: - GET_VA_ARG(p,u,unsigned int,ppfs->arg); - break; - case PA_WCHAR: /* TODO -- assume int? */ - /* we're assuming wchar_t is at least an int */ - GET_VA_ARG(p,wc,wchar_t,ppfs->arg); - break; -#ifdef __STDIO_PRINTF_FLOAT - /* PA_FLOAT */ - case PA_DOUBLE: - GET_VA_ARG(p,d,double,ppfs->arg); - break; - case (PA_DOUBLE|PA_FLAG_LONG_DOUBLE): - GET_VA_ARG(p,ld,long double,ppfs->arg); - break; -#else /* __STDIO_PRINTF_FLOAT */ - case PA_DOUBLE: - case (PA_DOUBLE|PA_FLAG_LONG_DOUBLE): - assert(0); - continue; -#endif /* __STDIO_PRINTF_FLOAT */ - default: - /* TODO -- really need to ensure this can't happen */ - assert(ppfs->argtype[i-1] & PA_FLAG_PTR); - case PA_POINTER: - case PA_STRING: - case PA_WSTRING: - GET_VA_ARG(p,p,void *,ppfs->arg); - break; - case __PA_NOARG: - continue; - } - ++p; - } -#ifdef NL_ARGMAX - } else { - if (ppfs->info.width == INT_MIN) { - ppfs->info.width - = (int) GET_ARG_VALUE(p + ppfs->argnumber[0] - 1,u,unsigned int); - } - if (ppfs->info.prec == INT_MIN) { - ppfs->info.prec - = (int) GET_ARG_VALUE(p + ppfs->argnumber[1] - 1,u,unsigned int); - } - } -#endif /* NL_ARGMAX */ - - /* Now we know the width and precision. */ - if (ppfs->info.width < 0) { - ppfs->info.width = -ppfs->info.width; - PRINT_INFO_SET_FLAG(&(ppfs->info),left); - PRINT_INFO_CLR_FLAG(&(ppfs->info),space); - ppfs->info.pad = ' '; - } -#if 0 - /* NOTE -- keep neg for now so float knows! */ - if (ppfs->info.prec < 0) { /* spec says treat as omitted. */ - /* so use default prec... 1 for everything but floats and strings. */ - ppfs->info.prec = 1; - } -#endif -} -#endif -/**********************************************************************/ -#ifdef L__ppfs_parsespec - -/* Notes: argtype differs from glibc for the following: - * mine glibc - * lc PA_WCHAR PA_CHAR the standard says %lc means %C - * ls PA_WSTRING PA_STRING the standard says %ls means %S - * {*}n {*}|PA_FLAG_PTR PA_FLAG_PTR size of n can be qualified + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. */ - -/* TODO: store positions of positional args */ - -/* TODO -- WARNING -- assumes aligned on integer boundaries!!! */ - -/* TODO -- disable if not using positional args!!! */ -#define _OVERLAPPING_DIFFERENT_ARGS - -/* TODO -- rethink this -- perhaps we should set to largest type??? */ - -#ifdef _OVERLAPPING_DIFFERENT_ARGS - -#define PROMOTED_SIZE_OF(X) ((sizeof(X) + sizeof(int) - 1) / sizeof(X)) - -static const short int type_codes[] = { - __PA_NOARG, /* must be first entry */ - PA_POINTER, - PA_STRING, - PA_WSTRING, - PA_CHAR, - PA_INT|PA_FLAG_SHORT, - PA_INT, - PA_INT|PA_FLAG_LONG, - PA_INT|PA_FLAG_LONG_LONG, - PA_WCHAR, -#ifdef __STDIO_PRINTF_FLOAT - /* PA_FLOAT, */ - PA_DOUBLE, - PA_DOUBLE|PA_FLAG_LONG_DOUBLE, -#endif /* __STDIO_PRINTF_FLOAT */ -}; - -static const unsigned char type_sizes[] = { - /* unknown type consumes no arg */ - 0, /* must be first entry */ - PROMOTED_SIZE_OF(void *), - PROMOTED_SIZE_OF(char *), - PROMOTED_SIZE_OF(wchar_t *), - PROMOTED_SIZE_OF(char), - PROMOTED_SIZE_OF(short), - PROMOTED_SIZE_OF(int), - PROMOTED_SIZE_OF(long), -#ifdef ULLONG_MAX - PROMOTED_SIZE_OF(long long), -#else - PROMOTED_SIZE_OF(long), /* TODO -- is this correct? (above too) */ -#endif - PROMOTED_SIZE_OF(wchar_t), -#ifdef __STDIO_PRINTF_FLOAT - /* PROMOTED_SIZE_OF(float), */ - PROMOTED_SIZE_OF(double), - PROMOTED_SIZE_OF(long double), -#endif /* __STDIO_PRINTF_FLOAT */ -}; - -static int _promoted_size(int argtype) -{ - register const short int *p; - - /* note -- since any unrecognized type is treated as a pointer */ - p = type_codes + sizeof(type_codes)/sizeof(type_codes[0]); - do { - if (*--p == argtype) { - break; - } - } while (p > type_codes); - - return type_sizes[(int)(p - type_codes)]; -} - -static int _is_equal_or_bigger_arg(int curtype, int newtype) -{ - /* Quick test */ - if (newtype == __PA_NOARG) { - return 0; - } - if ((curtype == __PA_NOARG) || (curtype == newtype)) { - return 1; - } - /* Ok... slot is already filled and types are different in name. */ - /* So, compare promoted sizes of curtype and newtype args. */ - return _promoted_size(curtype) <= _promoted_size(newtype); -} - -#else - -#define _is_equal_or_bigger_arg(C,N) (((C) == __PA_NOARG) || ((C) == (N))) - -#endif - -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ -/* TODO - do this differently? */ -static char _bss_custom_printf_spec[MAX_USER_SPEC]; /* 0-init'd for us. */ - -char *_custom_printf_spec = _bss_custom_printf_spec; -printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC]; -printf_function _custom_printf_handler[MAX_USER_SPEC]; -#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ - -int attribute_hidden _ppfs_parsespec(ppfs_t *ppfs) -{ - register const char *fmt; - register const char *p; - int preci; - int width; - int flags; - int dataargtype; - int i; - int dpoint; -#ifdef NL_ARGMAX - int maxposarg; -#endif /* NL_ARGMAX */ - int p_m_spec_chars; - int n; - int argtype[MAX_ARGS_PER_SPEC+2]; - int argnumber[3]; /* width, precision, 1st data arg */ - static const char spec_flags[] = SPEC_FLAGS; - static const char spec_chars[] = SPEC_CHARS;/* TODO: b? */ - static const char spec_ranges[] = SPEC_RANGES; - static const short spec_or_mask[] = SPEC_OR_MASK; - static const short spec_and_mask[] = SPEC_AND_MASK; - static const char qual_chars[] = QUAL_CHARS; -#ifdef __UCLIBC_HAS_WCHAR__ - char buf[32]; -#endif /* __UCLIBC_HAS_WCHAR__ */ - - /* WIDE note: we can test against '%' here since we don't allow */ - /* WIDE note: other mappings of '%' in the wide char set. */ - preci = -1; - argnumber[0] = 0; - argnumber[1] = 0; - argtype[0] = __PA_NOARG; - argtype[1] = __PA_NOARG; -#ifdef NL_ARGMAX - maxposarg = ppfs->maxposarg; -#endif /* NL_ARGMAX */ - -#ifdef __UCLIBC_HAS_WCHAR__ - /* This is somewhat lame, but saves a lot of code. If we're dealing with - * a wide stream, that means the format is a wchar string. So, copy it - * char-by-char into a normal char buffer for processing. Make the buffer - * (buf) big enough so that any reasonable format specifier will fit. - * While there a legal specifiers that won't, the all involve duplicate - * flags or outrageous field widths/precisions. */ - width = dpoint = 0; - if ((flags = ppfs->info._flags & FLAG_WIDESTREAM) == 0) { - fmt = ppfs->fmtpos; - } else { - fmt = buf + 1; - i = 0; - do { - if ((buf[i] = (char) (((wchar_t *) ppfs->fmtpos)[i-1])) - != (((wchar_t *) ppfs->fmtpos)[i-1]) - ) { - return -1; - } - } while (buf[i++]); - buf[sizeof(buf)-1] = 0; - } -#else /* __UCLIBC_HAS_WCHAR__ */ - width = flags = dpoint = 0; - fmt = ppfs->fmtpos; -#endif /* __UCLIBC_HAS_WCHAR__ */ - - assert(fmt[-1] == '%'); - assert(fmt[0] != '%'); - - /* Process arg pos and/or flags and/or width and/or precision. */ - width_precision: - p = fmt; - if (*fmt == '*') { - argtype[-dpoint] = PA_INT; - ++fmt; - } - i = 0; - while (isdigit(*fmt)) { - if (i < MAX_FIELD_WIDTH) { /* Avoid overflow. */ - i = (i * 10) + (*fmt - '0'); - } - ++fmt; - } - if (p[-1] == '%') { /* Check for a position. */ - - /* TODO: if val not in range, then error */ - -#ifdef NL_ARGMAX - if ((*fmt == '$') && (i > 0)) {/* Positional spec. */ - ++fmt; - if (maxposarg == 0) { - return -1; - } - if ((argnumber[2] = i) > maxposarg) { - maxposarg = i; - } - /* Now fall through to check flags. */ - } else { - if (maxposarg > 0) { -#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Support prec and width for %m when positional args used - /* Actually, positional arg processing will fail in general - * for specifiers that don't require an arg. */ -#endif /* __UCLIBC_MJN3_ONLY__ */ - if (*fmt == 'm') { - goto PREC_WIDTH; - } -#endif /* __UCLIBC_HAS_PRINTF_M_SPEC__ */ - return -1; - } - maxposarg = 0; /* Possible redundant store, but cuts size. */ - - if ((fmt > p) && (*p != '0')) { - goto PREC_WIDTH; - } - - fmt = p; /* Back up for possible '0's flag. */ - /* Now fall through to check flags. */ - } -#else /* NL_ARGMAX */ - if (*fmt == '$') { /* Positional spec. */ - return -1; - } - - if ((fmt > p) && (*p != '0')) { - goto PREC_WIDTH; - } - - fmt = p; /* Back up for possible '0's flag. */ - /* Now fall through to check flags. */ -#endif /* NL_ARGMAX */ - - restart_flags: /* Process flags. */ - i = 1; - p = spec_flags; - - do { - if (*fmt == *p++) { - ++fmt; - flags |= i; - goto restart_flags; - } - i += i; /* Better than i <<= 1 for bcc */ - } while (*p); - i = 0; - - /* If '+' then ignore ' ', and if '-' then ignore '0'. */ - /* Note: Need to ignore '0' when prec is an arg with val < 0, */ - /* but that test needs to wait until the arg is retrieved. */ - flags &= ~((flags & (FLAG_PLUS|FLAG_MINUS)) >> 1); - /* Note: Ignore '0' when prec is specified < 0 too (in printf). */ - - if (fmt[-1] != '%') { /* If we've done anything, loop for width. */ - goto width_precision; - } - } - PREC_WIDTH: - if (*p == '*') { /* Prec or width takes an arg. */ -#ifdef NL_ARGMAX - if (maxposarg) { - if ((*fmt++ != '$') || (i <= 0)) { - /* Using pos args and no $ or invalid arg number. */ - return -1; - } - argnumber[-dpoint] = i; - } else -#endif /* NL_ARGMAX */ - if (++p != fmt) { - /* Not using pos args but digits followed *. */ - return -1; - } - i = INT_MIN; - } - - if (!dpoint) { - width = i; - if (*fmt == '.') { - ++fmt; - dpoint = -1; /* To use as default precison. */ - goto width_precision; - } - } else { - preci = i; - } - - /* Process qualifier. */ - p = qual_chars; - do { - if (*fmt == *p) { - ++fmt; - break; - } - } while (*++p); - if ((p - qual_chars < 2) && (*fmt == *p)) { - p += ((sizeof(qual_chars)-2) / 2); - ++fmt; - } - dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; - - /* Process conversion specifier. */ - if (!*fmt) { - return -1; - } - - p = spec_chars; - - do { - if (*fmt == *p) { - p_m_spec_chars = p - spec_chars; - - if ((p_m_spec_chars >= CONV_c) - && (dataargtype & PA_FLAG_LONG)) { - p_m_spec_chars -= 2; /* lc -> C and ls -> S */ - } - - ppfs->conv_num = p_m_spec_chars; - p = spec_ranges-1; - while (p_m_spec_chars > *++p) {} - - i = p - spec_ranges; - argtype[2] = (dataargtype | spec_or_mask[i]) & spec_and_mask[i]; - p = spec_chars; - break; - } - } while(*++p); - - ppfs->info.spec = *fmt; - ppfs->info.prec = preci; - ppfs->info.width = width; - ppfs->info.pad = ((flags & FLAG_ZERO) ? '0' : ' '); - ppfs->info._flags = (flags & ~FLAG_ZERO) | (dataargtype & __PA_INTMASK); - ppfs->num_data_args = 1; - - if (!*p) { -#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ - if (*fmt == 'm') { - ppfs->conv_num = CONV_m; - ppfs->num_data_args = 0; - goto DONE; - } -#endif -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ - - /* Handle custom arg -- WARNING -- overwrites p!!! */ - ppfs->conv_num = CONV_custom0; - p = _custom_printf_spec; - do { - if (*p == *fmt) { - if ((ppfs->num_data_args - = ((*_custom_printf_arginfo[(int)(p-_custom_printf_spec)]) - (&(ppfs->info), MAX_ARGS_PER_SPEC, argtype+2))) - > MAX_ARGS_PER_SPEC) { - break; /* Error -- too many args! */ - } - goto DONE; - } - } while (++p < (_custom_printf_spec + MAX_USER_SPEC)); -#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ - /* Otherwise error. */ - return -1; - } - -#if defined(__UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__) || defined(__UCLIBC_HAS_PRINTF_M_SPEC__) - DONE: -#endif - -#ifdef NL_ARGMAX - if (maxposarg > 0) { - i = 0; - do { - /* Update maxposarg and check that NL_ARGMAX is not exceeded. */ - n = ((i <= 2) - ? (ppfs->argnumber[i] = argnumber[i]) - : argnumber[2] + (i-2)); - if (n > maxposarg) { - if ((maxposarg = n) > NL_ARGMAX) { - return -1; - } - } - --n; - /* Record argtype with largest size (current, new). */ - if (_is_equal_or_bigger_arg(ppfs->argtype[n], argtype[i])) { - ppfs->argtype[n] = argtype[i]; - } - } while (++i < ppfs->num_data_args + 2); - } else { -#endif /* NL_ARGMAX */ - ppfs->argnumber[2] = 1; - __memcpy(ppfs->argtype, argtype + 2, ppfs->num_data_args * sizeof(int)); -#ifdef NL_ARGMAX - } - - ppfs->maxposarg = maxposarg; -#endif /* NL_ARGMAX */ - -#ifdef __UCLIBC_HAS_WCHAR__ - if ((flags = ppfs->info._flags & FLAG_WIDESTREAM) == 0) { - ppfs->fmtpos = ++fmt; - } else { - ppfs->fmtpos = (const char *) (((const wchar_t *)(ppfs->fmtpos)) - + (fmt - buf) ); - } -#else /* __UCLIBC_HAS_WCHAR__ */ - ppfs->fmtpos = ++fmt; -#endif /* __UCLIBC_HAS_WCHAR__ */ - - return ppfs->num_data_args + 2; -} - -#endif -/**********************************************************************/ -#ifdef L_register_printf_function - -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ - -int register_printf_function(int spec, printf_function handler, - printf_arginfo_function arginfo) -{ - register char *r; - register char *p; - - if (spec && (arginfo != NULL)) { /* TODO -- check if spec is valid char */ - r = NULL; - p = _custom_printf_spec + MAX_USER_SPEC; - do { - --p; - if (!*p) { - r = p; - } -#ifdef __BCC__ - else /* bcc generates less code with fall-through */ -#endif - if (*p == spec) { - r = p; - p = _custom_printf_spec; - } - } while (p > _custom_printf_spec); - - if (r) { - if (handler) { - *r = spec; - _custom_printf_handler[(int)(r - p)] = handler; - _custom_printf_arginfo[(int)(r - p)] = arginfo; - } else { - *r = 0; - } - return 0; - } - /* TODO -- if asked to unregister a non-existent spec, return what? */ - } - return -1; -} - -#endif - -#endif -/**********************************************************************/ -#if defined(L_vfprintf) || defined(L_vfwprintf) - -/* We only support ascii digits (or their USC equivalent codes) in - * precision and width settings in *printf (wide) format strings. - * In other words, we don't currently support glibc's 'I' flag. - * We do accept it, but it is currently ignored. */ - -static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad); - -#ifdef L_vfprintf - -#define HIDDEN_VFPRINTF __vfprintf -#define VFPRINTF vfprintf -#define FMT_TYPE char -#define OUTNSTR _outnstr -#define STRLEN __strlen -#define _PPFS_init _ppfs_init -#define OUTPUT(F,S) __fputs_unlocked(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 - -#ifdef __STDIO_PRINTF_FLOAT - -static size_t _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) -{ - size_t r = 0; - - if (type & 0x80) { /* Some type of padding needed. */ - int buflen = __strlen((const char *) buf); - if ((len -= buflen) > 0) { - if ((r = _charpad(fp, (type & 0x7f), len)) != len) { - return r; - } - } - len = buflen; - } - return r + OUTNSTR(fp, (const char *) buf, len); -} - -#endif /* __STDIO_PRINTF_FLOAT */ - -#else /* L_vfprintf */ - -#define HIDDEN_VFPRINTF __vfwprintf -#define VFPRINTF vfwprintf -#define FMT_TYPE wchar_t -#define OUTNSTR _outnwcs -#define STRLEN wcslen -#define _PPFS_init _ppwfs_init -#define OUTPUT(F,S) fputws(S,F) -#define _outnwcs(stream, wstring, len) _wstdio_fwrite(wstring, len, stream) -#define FP_OUT _fp_out_wide - -static size_t _outnstr(FILE *stream, const char *s, size_t wclen) -{ - /* NOTE!!! len here is the number of wchars we want to generate!!! */ - wchar_t wbuf[64]; - mbstate_t mbstate; - size_t todo, r, n; - - mbstate.__mask = 0; - todo = wclen; - - while (todo) { - r = mbsrtowcs(wbuf, &s, - ((todo <= sizeof(wbuf)/sizeof(wbuf[0])) - ? todo - : sizeof(wbuf)/sizeof(wbuf[0])), - &mbstate); - assert(((ssize_t)r) > 0); - n = _outnwcs(stream, wbuf, r); - todo -= n; - if (n != r) { - break; - } - } - - return wclen - todo; -} - -#ifdef __STDIO_PRINTF_FLOAT - -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Move defines from _fpmaxtostr. Put them in a common header. -#endif - -/* The following defines are from _fpmaxtostr.*/ -#define DIGITS_PER_BLOCK 9 -#define NUM_DIGIT_BLOCKS ((DECIMAL_DIG+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK) -#define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK ) - -static size_t _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) -{ - wchar_t wbuf[BUF_SIZE]; - const char *s = (const char *) buf; - size_t r = 0; - int i; - - if (type & 0x80) { /* Some type of padding needed */ - int buflen = __strlen(s); - if ((len -= buflen) > 0) { - if ((r = _charpad(fp, (type & 0x7f), len)) != len) { - return r; - } - } - len = buflen; - } - - if (len > 0) { - i = 0; - do { -#ifdef __LOCALE_C_ONLY - wbuf[i] = s[i]; -#else /* __LOCALE_C_ONLY */ - -#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ - if (s[i] == ',') { - wbuf[i] = __UCLIBC_CURLOCALE_DATA.thousands_sep_wc; - } else -#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ - if (s[i] == '.') { - wbuf[i] = __UCLIBC_CURLOCALE_DATA.decimal_point_wc; - } else { - wbuf[i] = s[i]; - } -#endif /* __LOCALE_C_ONLY */ - - } while (++i < len); - - r += OUTNSTR(fp, wbuf, len); - } - - return r; -} - -#endif /* __STDIO_PRINTF_FLOAT */ - -static int _ppwfs_init(register ppfs_t *ppfs, const wchar_t *fmt0) -{ - static const wchar_t invalid_wcs[] = L"Invalid wide format string."; - int r; - - /* First, zero out everything... argnumber[], argtype[], argptr[] */ - __memset(ppfs, 0, sizeof(ppfs_t)); /* TODO: nonportable???? */ -#ifdef NL_ARGMAX - --ppfs->maxposarg; /* set to -1 */ -#endif /* NL_ARGMAX */ - ppfs->fmtpos = (const char *) fmt0; - ppfs->info._flags = FLAG_WIDESTREAM; - - { - mbstate_t mbstate; - const wchar_t *p; - mbstate.__mask = 0; /* Initialize the mbstate. */ - p = fmt0; - if (wcsrtombs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { - ppfs->fmtpos = (const char *) invalid_wcs; - return -1; - } - } - - /* now set all argtypes to no-arg */ - { -#if 1 - /* TODO - use memset here since already "paid for"? */ - register int *p = ppfs->argtype; - - r = MAX_ARGS; - do { - *p++ = __PA_NOARG; - } while (--r); -#else - /* TODO -- get rid of this?? */ - register char *p = (char *) ((MAX_ARGS-1) * sizeof(int)); - - do { - *((int *)(((char *)ppfs) + ((int)p) + offsetof(ppfs_t,argtype))) = __PA_NOARG; - p -= sizeof(int); - } while (p); -#endif - } - - /* - * Run through the entire format string to validate it and initialize - * the positional arg numbers (if any). - */ - { - register const wchar_t *fmt = fmt0; - - while (*fmt) { - if ((*fmt == '%') && (*++fmt != '%')) { - ppfs->fmtpos = (const char *) fmt; /* back up to the '%' */ - if ((r = _ppfs_parsespec(ppfs)) < 0) { - return -1; - } - fmt = (const wchar_t *) ppfs->fmtpos; /* update to one past end of spec */ - } else { - ++fmt; - } - } - ppfs->fmtpos = (const char *) fmt0; /* rewind */ - } - -#ifdef NL_ARGMAX - /* If we have positional args, make sure we know all the types. */ - { - register int *p = ppfs->argtype; - r = ppfs->maxposarg; - while (--r >= 0) { - if ( *p == __PA_NOARG ) { /* missing arg type!!! */ - return -1; - } - ++p; - } - } -#endif /* NL_ARGMAX */ - - return 0; -} - -#endif /* L_vfprintf */ - -static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad) -{ - size_t todo = numpad; - - /* TODO -- Use a buffer to cut down on function calls... */ - FMT_TYPE pad[1]; - - *pad = padchar; - while (todo && (OUTNSTR(stream, pad, 1) == 1)) { - --todo; - } - - return numpad - todo; -} - -/* TODO -- Dynamically allocate work space to accomodate stack-poor archs? */ -static int _do_one_spec(FILE * __restrict stream, - register ppfs_t *ppfs, int *count) -{ - static const char spec_base[] = SPEC_BASE; -#ifdef L_vfprintf - static const char prefix[] = "+\0-\0 \0000x\0000X"; - /* 0 2 4 6 9 11*/ -#else /* L_vfprintf */ - static const wchar_t prefix[] = L"+\0-\0 \0000x\0000X"; -#endif /* L_vfprintf */ - enum { - PREFIX_PLUS = 0, - PREFIX_MINUS = 2, - PREFIX_SPACE = 4, - PREFIX_LWR_X = 6, - PREFIX_UPR_X = 9, - PREFIX_NONE = 11 - }; - -#ifdef __va_arg_ptr - const void * const *argptr; -#else - const void * argptr[MAX_ARGS_PER_SPEC]; -#endif - int *argtype; -#ifdef __UCLIBC_HAS_WCHAR__ - const wchar_t *ws = NULL; - mbstate_t mbstate; -#endif /* __UCLIBC_HAS_WCHAR__ */ - size_t slen; -#ifdef L_vfprintf -#define SLEN slen -#else - size_t SLEN; - wchar_t wbuf[2]; -#endif - int base; - int numpad; - int alphacase; - int numfill = 0; /* TODO: fix */ - int prefix_num = PREFIX_NONE; - char padchar = ' '; -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Determine appropriate buf size. -#endif /* __UCLIBC_MJN3_ONLY__ */ - /* TODO: buf needs to be big enough for any possible error return strings - * and also for any locale-grouped long long integer strings generated. - * This should be large enough for any of the current archs/locales, but - * eventually this should be handled robustly. */ - char buf[128]; - -#ifdef NDEBUG - _ppfs_parsespec(ppfs); -#else - if (_ppfs_parsespec(ppfs) < 0) { /* TODO: just for debugging */ - abort(); - } -#endif - _ppfs_setargs(ppfs); - - argtype = ppfs->argtype + ppfs->argnumber[2] - 1; - /* Deal with the argptr vs argvalue issue. */ -#ifdef __va_arg_ptr - argptr = (const void * const *) ppfs->argptr; -#ifdef NL_ARGMAX - if (ppfs->maxposarg > 0) { /* Using positional args... */ - argptr += ppfs->argnumber[2] - 1; - } -#endif /* NL_ARGMAX */ -#else - /* Need to build a local copy... */ - { - register argvalue_t *p = ppfs->argvalue; - int i; -#ifdef NL_ARGMAX - if (ppfs->maxposarg > 0) { /* Using positional args... */ - p += ppfs->argnumber[2] - 1; - } -#endif /* NL_ARGMAX */ - for (i = 0 ; i < ppfs->num_data_args ; i++ ) { - argptr[i] = (void *) p++; - } - } -#endif - { - register char *s = NULL; /* TODO: Should s be unsigned char * ? */ - - if (ppfs->conv_num == CONV_n) { - _store_inttype(*(void **)*argptr, - ppfs->info._flags & __PA_INTMASK, - (intmax_t) (*count)); - return 0; - } - if (ppfs->conv_num <= CONV_i) { /* pointer or (un)signed int */ - alphacase = __UIM_LOWER; - -#ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_vfprintf -#warning CONSIDER: Should we ignore these flags if stub locale? What about custom specs? -#endif -#endif /* __UCLIBC_MJN3_ONLY__ */ - if ((base = spec_base[(int)(ppfs->conv_num - CONV_p)]) == 10) { - if (PRINT_INFO_FLAG_VAL(&(ppfs->info),group)) { - alphacase = __UIM_GROUP; - } - if (PRINT_INFO_FLAG_VAL(&(ppfs->info),i18n)) { - alphacase |= 0x80; - } - } - - if (ppfs->conv_num <= CONV_u) { /* pointer or unsigned int */ - if (ppfs->conv_num == CONV_X) { - alphacase = __UIM_UPPER; - } - if (ppfs->conv_num == CONV_p) { /* pointer */ - prefix_num = PREFIX_LWR_X; - } else { /* unsigned int */ - } - } else { /* signed int */ - base = -base; - } - if (ppfs->info.prec < 0) { /* Ignore '0' flag if prec specified. */ - padchar = ppfs->info.pad; - } -#ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_vfprintf -#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, - *argptr, base), base, alphacase); - if (ppfs->conv_num > CONV_u) { /* signed int */ - if (*s == '-') { - PRINT_INFO_SET_FLAG(&(ppfs->info),showsign); - ++s; /* handle '-' in the prefix string */ - prefix_num = PREFIX_MINUS; - } else if (PRINT_INFO_FLAG_VAL(&(ppfs->info),showsign)) { - prefix_num = PREFIX_PLUS; - } else if (PRINT_INFO_FLAG_VAL(&(ppfs->info),space)) { - prefix_num = PREFIX_SPACE; - } - } - slen = (char *)(buf + sizeof(buf) - 1) - s; -#ifdef L_vfwprintf - { - const char *q = s; - mbstate.__mask = 0; /* Initialize the mbstate. */ - SLEN = mbsrtowcs(NULL, &q, 0, &mbstate); - } -#endif - numfill = ((ppfs->info.prec < 0) ? 1 : ppfs->info.prec); - if (PRINT_INFO_FLAG_VAL(&(ppfs->info),alt)) { - if (ppfs->conv_num <= CONV_x) { /* x or p */ - prefix_num = PREFIX_LWR_X; - } - if (ppfs->conv_num == CONV_X) { - prefix_num = PREFIX_UPR_X; - } - if ((ppfs->conv_num == CONV_o) && (numfill <= SLEN)) { - numfill = ((*s == '0') ? 1 : SLEN + 1); - } - } - if (*s == '0') { - if (prefix_num >= PREFIX_LWR_X) { - prefix_num = PREFIX_NONE; - } - if (ppfs->conv_num == CONV_p) {/* null pointer */ - s = "(nil)"; -#ifdef L_vfwprintf - SLEN = -#endif - slen = 5; - numfill = 0; - } else if (numfill == 0) { /* if precision 0, no output */ -#ifdef L_vfwprintf - SLEN = -#endif - slen = 0; - } - } - numfill = ((numfill > SLEN) ? numfill - SLEN : 0); - } else if (ppfs->conv_num <= CONV_A) { /* floating point */ -#ifdef __STDIO_PRINTF_FLOAT - ssize_t nf; - nf = _fpmaxtostr(stream, - (__fpmax_t) - (PRINT_INFO_FLAG_VAL(&(ppfs->info),is_long_double) - ? *(long double *) *argptr - : (long double) (* (double *) *argptr)), - &ppfs->info, FP_OUT ); - if (nf < 0) { - return -1; - } - *count += nf; - - return 0; -#else /* __STDIO_PRINTF_FLOAT */ - 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 __UCLIBC_HAS_WCHAR__ - mbstate.__mask = 0; /* Initialize the mbstate. */ - if (ppfs->conv_num == CONV_S) { /* wide string */ - if (!(ws = *((const wchar_t **) *argptr))) { - goto NULL_STRING; - } - /* We use an awful uClibc-specific hack here, passing - * (char*) &ws as the conversion destination. This signals - * uClibc's wcsrtombs that we want a "restricted" length - * such that the mbs fits in a buffer of the specified - * size with no partial conversions. */ - if ((slen = wcsrtombs((char *) &ws, &ws, /* Use awful hack! */ - ((ppfs->info.prec >= 0) - ? ppfs->info.prec - : SIZE_MAX), &mbstate)) - == ((size_t)-1) - ) { - return -1; /* EILSEQ */ - } - } else { /* wide char */ - s = buf; - slen = wcrtomb(s, (*((const wchar_t *) *argptr)), &mbstate); - if (slen == ((size_t)-1)) { - return -1; /* EILSEQ */ - } - s[slen] = 0; /* TODO - Is this necessary? */ - } -#else /* __UCLIBC_HAS_WCHAR__ */ - return -1; -#endif /* __UCLIBC_HAS_WCHAR__ */ - } else if (ppfs->conv_num <= CONV_s) { /* char or string */ - if (ppfs->conv_num == CONV_s) { /* string */ - s = *((char **) (*argptr)); - if (s) { -#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ - SET_STRING_LEN: -#endif - slen = strnlen(s, ((ppfs->info.prec >= 0) - ? ppfs->info.prec : SIZE_MAX)); - } else { -#ifdef __UCLIBC_HAS_WCHAR__ - NULL_STRING: -#endif - s = "(null)"; - slen = 6; - } - } else { /* char */ - s = buf; - *s = (unsigned char)(*((const int *) *argptr)); - s[1] = 0; - slen = 1; - } - -#else /* L_vfprintf */ - - if (ppfs->conv_num == CONV_S) { /* wide string */ - ws = *((wchar_t **) (*argptr)); - if (!ws) { - goto NULL_STRING; - } - SLEN = wcsnlen(ws, ((ppfs->info.prec >= 0) - ? ppfs->info.prec : SIZE_MAX)); - } else { /* wide char */ - *wbuf = (wchar_t)(*((const wint_t *) *argptr)); - CHAR_CASE: - ws = wbuf; - wbuf[1] = 0; - SLEN = 1; - } - - } else if (ppfs->conv_num <= CONV_s) { /* char or string */ - - if (ppfs->conv_num == CONV_s) { /* string */ -#ifdef __UCLIBC_MJN3_ONLY__ -#warning TODO: Fix %s for vfwprintf... output upto illegal sequence? -#endif /* __UCLIBC_MJN3_ONLY__ */ - s = *((char **) (*argptr)); - if (s) { -#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ - SET_STRING_LEN: -#endif - /* We use an awful uClibc-specific hack here, passing - * (wchar_t*) &mbstate as the conversion destination. - * This signals uClibc's mbsrtowcs that we want a - * "restricted" length such that the mbs fits in a buffer - * of the specified size with no partial conversions. */ - { - const char *q = s; - mbstate.__mask = 0; /* Initialize the mbstate. */ - SLEN = mbsrtowcs((wchar_t *) &mbstate, &q, - ((ppfs->info.prec >= 0) - ? ppfs->info.prec : SIZE_MAX), - &mbstate); - } - if (SLEN == ((size_t)(-1))) { - return -1; /* EILSEQ */ - } - } else { - NULL_STRING: - s = "(null)"; - SLEN = slen = 6; - } - } else { /* char */ - *wbuf = btowc( (unsigned char)(*((const int *) *argptr)) ); - goto CHAR_CASE; - } - -#endif /* L_vfprintf */ - -#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ - } else if (ppfs->conv_num == CONV_m) { - s = __glibc_strerror_r_internal(errno, buf, sizeof(buf)); - goto SET_STRING_LEN; -#endif - } else { -#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ - assert(ppfs->conv_num == CONV_custom0); - - s = _custom_printf_spec; - do { - if (*s == ppfs->info.spec) { - int rv; - /* TODO -- check return value for sanity? */ - rv = (*_custom_printf_handler - [(int)(s-_custom_printf_spec)]) - (stream, &ppfs->info, argptr); - if (rv < 0) { - return -1; - } - *count += rv; - return 0; - } - } while (++s < (_custom_printf_spec + MAX_USER_SPEC)); -#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ - assert(0); - return -1; - } - -#ifdef __UCLIBC_MJN3_ONLY__ -#ifdef L_vfprintf -#warning CONSIDER: If using outdigits and/or grouping, how should we pad? -#endif -#endif /* __UCLIBC_MJN3_ONLY__ */ - { - size_t t; - - t = SLEN + numfill; - if (prefix_num != PREFIX_NONE) { - t += ((prefix_num < PREFIX_LWR_X) ? 1 : 2); - } - numpad = ((ppfs->info.width > t) ? (ppfs->info.width - t) : 0); - *count += t + numpad; - } - if (padchar == '0') { /* TODO: check this */ - numfill += numpad; - numpad = 0; - } - - /* Now handle the output itself. */ - if (!PRINT_INFO_FLAG_VAL(&(ppfs->info),left)) { - if (_charpad(stream, ' ', numpad) != numpad) { - return -1; - } - numpad = 0; - } - OUTPUT(stream, prefix + prefix_num); - if (_charpad(stream, '0', numfill) != numfill) { - return -1; - } - -#ifdef L_vfprintf - -#ifdef __UCLIBC_HAS_WCHAR__ - if (!ws) { - assert(s); - if (_outnstr(stream, s, slen) != slen) { - return -1; - } - } else { /* wide string */ - size_t t; - mbstate.__mask = 0; /* Initialize the mbstate. */ - while (slen) { - t = (slen <= sizeof(buf)) ? slen : sizeof(buf); - t = wcsrtombs(buf, &ws, t, &mbstate); - assert (t != ((size_t)(-1))); - if (_outnstr(stream, buf, t) != t) { - return -1; - } - slen -= t; - } - } -#else /* __UCLIBC_HAS_WCHAR__ */ - if (_outnstr(stream, s, slen) != slen) { - return -1; - } -#endif /* __UCLIBC_HAS_WCHAR__ */ - -#else /* L_vfprintf */ - - if (!ws) { - assert(s); - if (_outnstr(stream, s, SLEN) != SLEN) { - return -1; - } - } else { - if (_outnwcs(stream, ws, SLEN) != SLEN) { - return -1; - } - } - -#endif /* L_vfprintf */ - if (_charpad(stream, ' ', numpad) != numpad) { - return -1; - } - } - - return 0; -} - -int attribute_hidden HIDDEN_VFPRINTF (FILE * __restrict stream, - register 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, - STRLEN((const FMT_TYPE *)(ppfs.fmtpos))); -#if defined(L_vfprintf) && !defined(NDEBUG) - fprintf(stderr,"\nIMbS: \"%s\"\n\n", format); -#endif - count = -1; - } else { - _ppfs_prepargs(&ppfs, arg); /* This did a va_copy!!! */ - - do { - while (*format && (*format != '%')) { - ++format; - } - - if (format-s) { /* output any literal text in format string */ - if ( (r = OUTNSTR(stream, s, format-s)) != (format-s)) { - count = -1; - break; - } - count += r; - } - - if (!*format) { /* we're done */ - break; - } - - if (format[1] != '%') { /* if we get here, *format == '%' */ - /* TODO: _do_one_spec needs to know what the output funcs are!!! */ - ppfs.fmtpos = (const char *)(++format); - /* TODO: check -- should only fail on stream error */ - if ( (r = _do_one_spec(stream, &ppfs, &count)) < 0) { - count = -1; - break; - } - s = format = (const FMT_TYPE *) ppfs.fmtpos; - } else { /* %% means literal %, so start new string */ - s = ++format; - ++format; - } - } while (1); - - va_end(ppfs.arg); /* Need to clean up after va_copy! */ - } - -/* #if defined(L_vfprintf) && defined(__UCLIBC_HAS_WCHAR__) */ -/* DONE: */ -/* #endif */ - - __STDIO_AUTO_THREADUNLOCK(stream); - - return count; -} -strong_alias(HIDDEN_VFPRINTF,VFPRINTF) -#endif -/**********************************************************************/ +#define L_vfprintf +#include "_vfprintf.c" diff --git a/libc/stdio/vfscanf.c b/libc/stdio/vfscanf.c new file mode 100644 index 000000000..b13ff8db8 --- /dev/null +++ b/libc/stdio/vfscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfscanf +#include "_scanf.c" diff --git a/libc/stdio/vfwprintf.c b/libc/stdio/vfwprintf.c new file mode 100644 index 000000000..323b90015 --- /dev/null +++ b/libc/stdio/vfwprintf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfwprintf +#include "_vfprintf.c" diff --git a/libc/stdio/vfwscanf.c b/libc/stdio/vfwscanf.c new file mode 100644 index 000000000..ac982b4f1 --- /dev/null +++ b/libc/stdio/vfwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfwscanf +#include "_scanf.c" diff --git a/libc/stdio/vprintf.c b/libc/stdio/vprintf.c index 9c0e07514..7848a078d 100644 --- a/libc/stdio/vprintf.c +++ b/libc/stdio/vprintf.c @@ -8,7 +8,9 @@ #include "_stdio.h" #include <stdarg.h> +libc_hidden_proto(vfprintf) + int vprintf(const char * __restrict format, va_list arg) { - return __vfprintf(stdout, format, arg); + return vfprintf(stdout, format, arg); } diff --git a/libc/stdio/vscanf.c b/libc/stdio/vscanf.c new file mode 100644 index 000000000..834fe92ee --- /dev/null +++ b/libc/stdio/vscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vscanf +#include "_scanf.c" diff --git a/libc/stdio/vsnprintf.c b/libc/stdio/vsnprintf.c index c926b2ad7..ab6154848 100644 --- a/libc/stdio/vsnprintf.c +++ b/libc/stdio/vsnprintf.c @@ -8,13 +8,17 @@ #include "_stdio.h" #include <stdarg.h> +libc_hidden_proto(vsnprintf) + +libc_hidden_proto(vfprintf) + #ifdef __UCLIBC_MJN3_ONLY__ #warning WISHLIST: Implement vsnprintf for non-buffered and no custom stream case. #endif /* __UCLIBC_MJN3_ONLY__ */ #ifdef __STDIO_BUFFERS -int attribute_hidden __vsnprintf(char *__restrict buf, size_t size, +int vsnprintf(char *__restrict buf, size_t size, const char * __restrict format, va_list arg) { FILE f; @@ -61,7 +65,7 @@ int attribute_hidden __vsnprintf(char *__restrict buf, size_t size, __STDIO_STREAM_DISABLE_GETC(&f); __STDIO_STREAM_ENABLE_PUTC(&f); - rv = __vfprintf(&f, format, arg); + rv = vfprintf(&f, format, arg); if (size) { if (f.__bufpos == f.__bufend) { --f.__bufpos; @@ -70,7 +74,7 @@ int attribute_hidden __vsnprintf(char *__restrict buf, size_t size, } return rv; } -strong_alias(__vsnprintf,vsnprintf) +libc_hidden_def(vsnprintf) #elif defined(__USE_OLD_VFPRINTF__) @@ -80,7 +84,7 @@ typedef struct { unsigned char *bufpos; } __FILE_vsnprintf; -int attribute_hidden __vsnprintf(char *__restrict buf, size_t size, +int vsnprintf(char *__restrict buf, size_t size, const char * __restrict format, va_list arg) { __FILE_vsnprintf f; @@ -122,7 +126,7 @@ int attribute_hidden __vsnprintf(char *__restrict buf, size_t size, #endif f.f.__nextopen = NULL; - rv = __vfprintf((FILE *) &f, format, arg); + rv = vfprintf((FILE *) &f, format, arg); if (size) { if (f.bufpos == f.bufend) { --f.bufpos; @@ -131,7 +135,7 @@ int attribute_hidden __vsnprintf(char *__restrict buf, size_t size, } return rv; } -strong_alias(__vsnprintf,vsnprintf) +libc_hidden_def(vsnprintf) #elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) @@ -173,7 +177,7 @@ static ssize_t snpf_write(register void *cookie, const char *buf, #undef COOKIE -int attribute_hidden __vsnprintf(char *__restrict buf, size_t size, +int vsnprintf(char *__restrict buf, size_t size, const char * __restrict format, va_list arg) { FILE f; @@ -211,11 +215,11 @@ int attribute_hidden __vsnprintf(char *__restrict buf, size_t size, #endif f.__nextopen = NULL; - rv = __vfprintf(&f, format, arg); + rv = vfprintf(&f, format, arg); return rv; } -strong_alias(__vsnprintf,vsnprintf) +libc_hidden_def(vsnprintf) #else #warning Skipping vsnprintf since no buffering, no custom streams, and not old vfprintf! diff --git a/libc/stdio/vsprintf.c b/libc/stdio/vsprintf.c index a7d5e08f5..8e27c19d9 100644 --- a/libc/stdio/vsprintf.c +++ b/libc/stdio/vsprintf.c @@ -12,10 +12,12 @@ #warning Skipping vsprintf since no vsnprintf! #else +libc_hidden_proto(vsnprintf) + int vsprintf(char *__restrict buf, const char * __restrict format, va_list arg) { - return __vsnprintf(buf, SIZE_MAX, format, arg); + return vsnprintf(buf, SIZE_MAX, format, arg); } #endif diff --git a/libc/stdio/vsscanf.c b/libc/stdio/vsscanf.c new file mode 100644 index 000000000..882c2713e --- /dev/null +++ b/libc/stdio/vsscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vsscanf +#include "_scanf.c" diff --git a/libc/stdio/vswprintf.c b/libc/stdio/vswprintf.c index c9e73cf87..d95de51a2 100644 --- a/libc/stdio/vswprintf.c +++ b/libc/stdio/vswprintf.c @@ -9,11 +9,15 @@ #include <stdarg.h> #include <wchar.h> +libc_hidden_proto(vswprintf) + +libc_hidden_proto(vfwprintf) + #ifndef __STDIO_BUFFERS #warning Skipping vswprintf since no buffering! #else /* __STDIO_BUFFERS */ -int attribute_hidden __vswprintf(wchar_t *__restrict buf, size_t size, +int vswprintf(wchar_t *__restrict buf, size_t size, const wchar_t * __restrict format, va_list arg) { FILE f; @@ -56,7 +60,7 @@ int attribute_hidden __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(&f, format, arg); /* NOTE: Return behaviour differs from snprintf... */ if (f.__bufpos == f.__bufend) { @@ -70,6 +74,6 @@ int attribute_hidden __vswprintf(wchar_t *__restrict buf, size_t size, } return rv; } -strong_alias(__vswprintf,vswprintf) +libc_hidden_def(vswprintf) #endif /* __STDIO_BUFFERS */ diff --git a/libc/stdio/vswscanf.c b/libc/stdio/vswscanf.c new file mode 100644 index 000000000..fddb60209 --- /dev/null +++ b/libc/stdio/vswscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vswscanf +#include "_scanf.c" diff --git a/libc/stdio/vwprintf.c b/libc/stdio/vwprintf.c index 8c3401846..1c32887a4 100644 --- a/libc/stdio/vwprintf.c +++ b/libc/stdio/vwprintf.c @@ -9,7 +9,9 @@ #include <stdarg.h> #include <wchar.h> +libc_hidden_proto(vfwprintf) + int vwprintf(const wchar_t * __restrict format, va_list arg) { - return __vfwprintf(stdout, format, arg); + return vfwprintf(stdout, format, arg); } diff --git a/libc/stdio/vwscanf.c b/libc/stdio/vwscanf.c new file mode 100644 index 000000000..9e21a271e --- /dev/null +++ b/libc/stdio/vwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vwscanf +#include "_scanf.c" diff --git a/libc/stdio/wprintf.c b/libc/stdio/wprintf.c index 00f5ef514..9dc274aec 100644 --- a/libc/stdio/wprintf.c +++ b/libc/stdio/wprintf.c @@ -9,13 +9,15 @@ #include <stdarg.h> #include <wchar.h> +libc_hidden_proto(vfwprintf) + int wprintf(const wchar_t * __restrict format, ...) { va_list arg; int rv; va_start(arg, format); - rv = __vfwprintf(stdout, format, arg); + rv = vfwprintf(stdout, format, arg); va_end(arg); return rv; diff --git a/libc/stdio/wscanf.c b/libc/stdio/wscanf.c new file mode 100644 index 000000000..d354d527f --- /dev/null +++ b/libc/stdio/wscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org> + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_wscanf +#include "_scanf.c" |