summaryrefslogtreecommitdiff
path: root/libc/stdio
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2003-09-06 03:37:17 +0000
committerManuel Novoa III <mjn3@codepoet.org>2003-09-06 03:37:17 +0000
commitf763ad5a3646b8b88ad34474b81594e591ee3332 (patch)
treeff4640799ffe780665a91fca4686adb9232f5fd0 /libc/stdio
parentdb07e536d4da78c06cf89f8a90bff1732734941e (diff)
Implement vsnprintf (old_vfprintf only) and vsnscanf when uClibc is
configured with non-buffered stdio and non-wchar mode. Fix a couple of bugs that showed up in minimalist configurations. Update old_vfprintf to handle size qualifiers on the integer and %n conversions. It now passed the glibc printf tests with the exception of a floating point rounding difference.
Diffstat (limited to 'libc/stdio')
-rw-r--r--libc/stdio/Makefile4
-rw-r--r--libc/stdio/old_vfprintf.c232
-rw-r--r--libc/stdio/printf.c96
-rw-r--r--libc/stdio/scanf.c96
4 files changed, 358 insertions, 70 deletions
diff --git a/libc/stdio/Makefile b/libc/stdio/Makefile
index 44ce51848..b92eed2a1 100644
--- a/libc/stdio/Makefile
+++ b/libc/stdio/Makefile
@@ -50,7 +50,7 @@ MOBJ = fclose.o fflush.o fopen.o freopen.o perror.o remove.o \
MSRC2= printf.c
MOBJ2= vsnprintf.o vdprintf.o vasprintf.o vprintf.o vsprintf.o \
fprintf.o snprintf.o dprintf.o asprintf.o printf.o sprintf.o \
- _store_inttype.o
+ _store_inttype.o _load_inttype.o
MSRC3=scanf.c
MOBJ3=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o \
@@ -65,7 +65,7 @@ endif
ifneq ($(USE_OLD_VFPRINTF),y)
MOBJ2 += _ppfs_init.o _ppfs_prepargs.o _ppfs_setargs.o \
- _ppfs_parsespec.o vfprintf.o _load_inttype.o \
+ _ppfs_parsespec.o vfprintf.o \
register_printf_function.o parse_printf_format.o
endif
diff --git a/libc/stdio/old_vfprintf.c b/libc/stdio/old_vfprintf.c
index ecec63c9f..5afbefb07 100644
--- a/libc/stdio/old_vfprintf.c
+++ b/libc/stdio/old_vfprintf.c
@@ -85,6 +85,8 @@
*
* Sep 5, 2003
* Convert to new floating point conversion routine.
+ * Fix qualifier handling on integer and %n conversions.
+ * Add support for vsnprintf when in non-buffered/no-wchar configuration.
*
*/
@@ -125,11 +127,13 @@
/**************************************************************************/
+#define _ISOC99_SOURCE /* for ULLONG primarily... */
#define _GNU_SOURCE /* for strnlen */
#define _STDIO_UTILITY
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
+#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
@@ -153,7 +157,60 @@
#define WANT_GNU_ERRNO 0
#endif
-#if defined(__UCLIBC_HAS_FLOATS__)
+#undef PUTC
+#undef OUTNSTR
+#undef _outnstr
+
+#ifdef __STDIO_BUFFERS
+
+#define PUTC(C,F) putc_unlocked((C),(F))
+#define OUTNSTR _outnstr
+#define _outnstr(stream, string, len) _stdio_fwrite(string, len, stream)
+
+#else /* __STDIO_BUFFERS */
+
+typedef struct {
+ FILE f;
+ unsigned char *bufend; /* pointer to 1 past end of buffer */
+ unsigned char *bufpos;
+} __FILE_vsnprintf;
+
+#ifdef __UCLIBC_HAS_FLOATS__
+static void _outnstr(FILE *stream, const unsigned char *s, size_t n)
+{
+ __FILE_vsnprintf *f = (__FILE_vsnprintf *) stream;
+
+ if (f->f.filedes != -2) {
+ _stdio_fwrite(s, n, &f->f);
+ } else {
+ if (f->bufend > f->bufpos) {
+ size_t r = f->bufend - f->bufpos;
+ if (r > n) {
+ r = n;
+ }
+ memcpy(f->bufpos, s, r);
+ f->bufpos += r;
+ }
+ }
+}
+#endif
+
+static void putc_unlocked_sprintf(int c, __FILE_vsnprintf *f)
+{
+ if (f->f.filedes != -2) {
+ putc_unlocked(c, &f->f);
+ } else if (f->bufpos < f->bufend) {
+ *f->bufpos++ = c;
+ }
+}
+
+
+#define PUTC(C,F) putc_unlocked_sprintf((C),(__FILE_vsnprintf *)(F))
+#define OUTNSTR _outnstr
+
+#endif /* __STDIO_BUFFERS */
+
+#ifdef __UCLIBC_HAS_FLOATS__
#include <float.h>
#include <bits/uClibc_fpmax.h>
@@ -163,14 +220,10 @@ typedef void (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len,
extern size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
__fp_outfunc_t fp_outfunc);
-#define FMT_TYPE char
-#define OUTNSTR _outnstr
-#define _outnstr(stream, string, len) _stdio_fwrite(string, len, stream)
-
static void _charpad(FILE * __restrict stream, int padchar, size_t numpad)
{
/* TODO -- Use a buffer to cut down on function calls... */
- FMT_TYPE pad[1];
+ char pad[1];
*pad = padchar;
while (numpad) {
@@ -191,8 +244,6 @@ static void _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf)
OUTNSTR(fp, (const char *) buf, len);
}
-
-
#endif
@@ -207,7 +258,69 @@ enum {
/* layout 01234 */
static const char spec[] = "+-#0 ";
-static const char qual[] = "hlLq";
+/**********************************************************************/
+
+extern void _store_inttype(void *dest, int desttype, uintmax_t val);
+extern uintmax_t _load_inttype(int desttype, const void *src, int uflag);
+
+/*
+ * 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)
+ */
+
+#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 \
+}
+
+static const char qual_chars[] = QUAL_CHARS;
+
+/* static const char qual[] = "hlLq"; */
+/**********************************************************************/
#if !defined(__UCLIBC_HAS_FLOATS__) && WANT_FLOAT_ERROR
static const char dbl_err[] = "<DOUBLE>";
@@ -228,7 +341,17 @@ static const char u_radix[] = "\x02\x08\x10\x10\x10\x0a";
int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
va_list ap)
{
- int i, cnt, lval, len;
+ union {
+#ifdef LLONG_MAX
+ long long ll;
+#endif
+#if LONG_MAX != INT_MAX
+ long l;
+#endif
+ int i;
+ } intarg;
+ int i, cnt, dataargtype, len;
+ const void *argptr; /* This does not need to be initialized. */
register char *p;
const char *fmt0;
int preci, width;
@@ -249,11 +372,6 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
preci = -5; /* max string width or mininum digits */
radix = 10; /* number base */
dpoint = 0; /* found decimal point */
-#if INT_MAX != LONG_MAX
- lval = 0; /* sizeof(int) != sizeof(long) */
-#else
- lval = 1; /* sizeof(int) == sizeof(long) */
-#endif
/* init flags */
for (p =(char *) spec ; *p ; p++) {
@@ -305,16 +423,18 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
} while ((*fmt == '.') && !dpoint );
/* process optional qualifier */
- for (p = (char *) qual ; *p ; p++) {
- if (*p == *fmt) {
- lval = p - qual;
- ++fmt; /* TODO - hh */
- if ((*p == 'l') && (*fmt == *p)) {
- ++lval;
- ++fmt;
- }
+ p = (char *) 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;
#if WANT_GNU_ERRNO
if (*fmt == 'm') {
@@ -332,23 +452,51 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
goto charout;
}
if (p-u_spec < 2) { /* store output count in int ptr */
- *(va_arg(ap, int *)) = cnt;
+ _store_inttype(va_arg(ap, void *),
+ dataargtype,
+ (intmax_t) (cnt));
goto nextfmt;
}
+
+ if (p-u_spec < 10) {
+ if (*p == 'p') {
+#if INTPTR_MAX == INT_MAX
+ dataargtype = 0;
+#else
+#error Fix dataargtype for pointers!
+#endif
+ }
+
+ switch(dataargtype) {
+ case (PA_INT|PA_FLAG_LONG_LONG):
+#ifdef LLONG_MAX
+ intarg.ll = va_arg(ap, long long);
+ argptr = &intarg.ll;
+ break;
+#endif
+ case (PA_INT|PA_FLAG_LONG):
+#if LONG_MAX != INT_MAX
+ intarg.l = va_arg(ap, long);
+ argptr = &intarg.l;
+ break;
+#endif
+ default:
+ intarg.i = va_arg(ap, int);
+ argptr = &intarg.i;
+ break;
+ }
+ }
+
if (p-u_spec < 8) { /* unsigned conversion */
radix = u_radix[p-u_spec-2];
upcase = ((*p == 'x') ? __UIM_LOWER : __UIM_UPPER);
if (*p == 'p') {
- lval = (sizeof(char *) == sizeof(long));
upcase = __UIM_LOWER;
flag[FLAG_HASH] = 'p';
}
-
- p = _uintmaxtostr((tmp + sizeof(tmp) - 1),
- ((lval>1) /* TODO -- longlong/long/int/short/char */
- ? va_arg(ap, uintmax_t)
- : (uintmax_t)
- va_arg(ap, unsigned long)),
+ p = _uintmaxtostr(tmp + sizeof(tmp) - 1,
+ (uintmax_t)
+ _load_inttype(dataargtype, argptr, radix),
radix, upcase);
flag[FLAG_PLUS] = '\0'; /* meaningless for unsigned */
@@ -371,12 +519,9 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
p = "(nil)";
}
} else if (p-u_spec < 10) { /* signed conversion */
-
- p = _uintmaxtostr((tmp + sizeof(tmp) - 1),
- ((lval>1) /* TODO -- longlong/long/int/short/char */
- ? va_arg(ap, uintmax_t)
- : (uintmax_t) ((intmax_t) /* sign-extend! */
- va_arg(ap, long))),
+ p = _uintmaxtostr(tmp + sizeof(tmp) - 1,
+ (uintmax_t)
+ _load_inttype(dataargtype, argptr, -radix),
-radix, upcase);
} else if (p-u_spec < 12) { /* character or string */
@@ -425,12 +570,21 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
if (flag[FLAG_MINUS_LJUSTIFY]) {
PRINT_INFO_SET_FLAG(&info,left);
}
+#if 1
+ cnt += _fpmaxtostr(op,
+ (__fpmax_t)
+ ((dataargtype == (8 << 8))
+ ? va_arg(ap, long double)
+ : (long double) va_arg(ap, double)),
+ &info, _fp_out_narrow);
+#else
cnt += _fpmaxtostr(op,
(__fpmax_t)
((lval > 1)
? va_arg(ap, long double)
: (long double) va_arg(ap, double)),
&info, _fp_out_narrow);
+#endif
goto nextfmt;
#elif WANT_FLOAT_ERROR
(void) ((lval > 1) ? va_arg(ap, long double)
@@ -520,7 +674,7 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
--len;
}
++cnt;
- putc(ch, op);
+ PUTC(ch, op);
}
}
goto nextfmt;
@@ -531,7 +685,7 @@ int vfprintf(FILE * __restrict op, register const char * __restrict fmt,
charout:
++cnt;
- putc(*fmt, op); /* normal char out */
+ PUTC(*fmt, op); /* normal char out */
nextfmt:
++fmt;
diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c
index d7d23ddc0..1cc121212 100644
--- a/libc/stdio/printf.c
+++ b/libc/stdio/printf.c
@@ -72,6 +72,9 @@
*
* 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.
*/
/* TODO:
@@ -145,6 +148,12 @@
#undef L__fpmaxtostr
#endif /* __STDIO_PRINTF_FLOAT */
+
+#undef __STDIO_HAS_VSNPRINTF
+#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
+#define __STDIO_HAS_VSNPRINTF 1
+#endif
+
/**********************************************************************/
/* Now controlled by uClibc_stdio.h. */
@@ -1190,6 +1199,7 @@ int register_printf_function(int spec, printf_function handler,
#endif /* __UCLIBC_MJN3_ONLY__ */
#ifdef __STDIO_BUFFERS
+
int vsnprintf(char *__restrict buf, size_t size,
const char * __restrict format, va_list arg)
{
@@ -1238,8 +1248,59 @@ int vsnprintf(char *__restrict buf, size_t size,
}
return rv;
}
-#else /* __STDIO_BUFFERS */
-#ifdef __STDIO_GLIBC_CUSTOM_STREAMS
+
+#elif defined(__USE_OLD_VFPRINTF__)
+
+typedef struct {
+ FILE f;
+ unsigned char *bufend; /* pointer to 1 past end of buffer */
+ unsigned char *bufpos;
+} __FILE_vsnprintf;
+
+int vsnprintf(char *__restrict buf, size_t size,
+ const char * __restrict format, va_list arg)
+{
+ __FILE_vsnprintf f;
+ int rv;
+
+ f.bufpos = buf;
+
+ if (size > SIZE_MAX - (size_t) buf) {
+ size = SIZE_MAX - (size_t) buf;
+ }
+ f.bufend = buf + size;
+
+#if 0 /* shouldn't be necessary */
+/* #ifdef __STDIO_GLIBC_CUSTOM_STREAMS */
+ f.f.cookie = &(f.f.filedes);
+ f.f.gcs.read = 0;
+ f.f.gcs.write = 0;
+ f.f.gcs.seek = 0;
+ f.f.gcs.close = 0;
+#endif
+ f.f.filedes = -2; /* for debugging */
+ f.f.modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING);
+
+#ifdef __STDIO_MBSTATE
+ __INIT_MBSTATE(&(f.f.state));
+#endif /* __STDIO_MBSTATE */
+
+#ifdef __STDIO_THREADSAFE
+ f.f.user_locking = 0;
+ __stdio_init_mutex(&f.f.lock);
+#endif
+
+ rv = vfprintf((FILE *) &f, format, arg);
+ if (size) {
+ if (f.bufpos == f.bufend) {
+ --f.bufpos;
+ }
+ *f.bufpos = 0;
+ }
+ return rv;
+}
+
+#elif defined(__STDIO_GLIBC_CUSTOM_STREAMS)
typedef struct {
size_t pos;
@@ -1314,10 +1375,13 @@ int vsnprintf(char *__restrict buf, size_t size,
return rv;
}
-#else /* __STDIO_GLIBC_CUSTOM_STREAMS */
-#warning Skipping vsnprintf since no buffering and no custom streams!
-#endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
-#endif /* __STDIO_BUFFERS */
+#else
+#warning Skipping vsnprintf since no buffering, no custom streams, and not old vfprintf!
+#ifdef __STDIO_HAS_VSNPRINTF
+#error WHOA! __STDIO_HAS_VSNPRINTF is defined!
+#endif
+#endif
+
#endif
/**********************************************************************/
#ifdef L_vdprintf
@@ -1366,8 +1430,8 @@ int vdprintf(int filedes, const char * __restrict format, va_list arg)
/**********************************************************************/
#ifdef L_vasprintf
-#if !defined(__STDIO_BUFFERS) && !defined(__STDIO_GLIBC_CUSTOM_STREAMS)
-#warning Skipping vasprintf since no buffering and no custom streams!
+#ifndef __STDIO_HAS_VSNPRINTF
+#warning Skipping vasprintf since no vsnprintf!
#else
int vasprintf(char **__restrict buf, const char * __restrict format,
@@ -1420,8 +1484,8 @@ int vprintf(const char * __restrict format, va_list arg)
/**********************************************************************/
#ifdef L_vsprintf
-#if !defined(__STDIO_BUFFERS) && !defined(__STDIO_GLIBC_CUSTOM_STREAMS)
-#warning Skipping vsprintf since no buffering and no custom streams!
+#ifndef __STDIO_HAS_VSNPRINTF
+#warning Skipping vsprintf since no vsnprintf!
#else
int vsprintf(char *__restrict buf, const char * __restrict format,
@@ -1451,8 +1515,8 @@ int fprintf(FILE * __restrict stream, const char * __restrict format, ...)
/**********************************************************************/
#ifdef L_snprintf
-#if !defined(__STDIO_BUFFERS) && !defined(__STDIO_GLIBC_CUSTOM_STREAMS)
-#warning Skipping snprintf since no buffering and no custom streams!
+#ifndef __STDIO_HAS_VSNPRINTF
+#warning Skipping snprintf since no vsnprintf!
#else
int snprintf(char *__restrict buf, size_t size,
@@ -1488,8 +1552,8 @@ int dprintf(int filedes, const char * __restrict format, ...)
/**********************************************************************/
#ifdef L_asprintf
-#if !defined(__STDIO_BUFFERS) && !defined(__STDIO_GLIBC_CUSTOM_STREAMS)
-#warning Skipping asprintf and __asprintf since no buffering and no custom streams!
+#ifndef __STDIO_HAS_VSNPRINTF
+#warning Skipping asprintf and __asprintf since no vsnprintf!
#else
weak_alias(__asprintf,asprintf)
@@ -1525,8 +1589,8 @@ int printf(const char * __restrict format, ...)
/**********************************************************************/
#ifdef L_sprintf
-#if !defined(__STDIO_BUFFERS) && !defined(__STDIO_GLIBC_CUSTOM_STREAMS)
-#warning Skipping sprintf since no buffering and no custom streams!
+#ifndef __STDIO_HAS_VSNPRINTF
+#warning Skipping sprintf since no vsnprintf!
#else
int sprintf(char *__restrict buf, const char * __restrict format, ...)
diff --git a/libc/stdio/scanf.c b/libc/stdio/scanf.c
index 11deea38c..9f811968a 100644
--- a/libc/stdio/scanf.c
+++ b/libc/stdio/scanf.c
@@ -25,6 +25,10 @@
* 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.
*/
@@ -72,6 +76,20 @@
#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__
#endif
+#undef __STDIO_HAS_VSSCANF
+#if defined(__STDIO_BUFFERS) || !defined(__UCLIBC_HAS_WCHAR__) || defined(__STDIO_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);
#ifdef LLONG_MAX
@@ -143,7 +161,7 @@ int scanf(const char * __restrict format, ...)
/**********************************************************************/
#ifdef L_sscanf
-#if defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS)
+#ifdef __STDIO_HAS_VSSCANF
int sscanf(const char * __restrict str, const char * __restrict format, ...)
{
@@ -157,9 +175,9 @@ int sscanf(const char * __restrict str, const char * __restrict format, ...)
return rv;
}
-#else /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
-#warning Skipping sscanf since no buffering and no custom streams!
-#endif /* defined(__STDIO_BUFFERS) || defined(__STDIO_GLIBC_CUSTOM_STREAMS) */
+#else /* __STDIO_HAS_VSSCANF */
+#warning Skipping sscanf since no vsscanf!
+#endif /* __STDIO_HAS_VSSCANF */
#endif
/**********************************************************************/
@@ -179,6 +197,7 @@ int vscanf(const char * __restrict format, va_list arg)
#endif /* __UCLIBC_MJN3_ONLY__ */
#ifdef __STDIO_BUFFERS
+
int vsscanf(__const char *sp, __const char *fmt, va_list ap)
{
FILE string[1];
@@ -202,8 +221,32 @@ int vsscanf(__const char *sp, __const char *fmt, va_list ap)
return vfscanf(string, fmt, ap);
}
-#else /* __STDIO_BUFFERS */
-#ifdef __STDIO_GLIBC_CUSTOM_STREAMS
+
+#elif !defined(__UCLIBC_HAS_WCHAR__)
+
+int vsscanf(__const char *sp, __const char *fmt, va_list ap)
+{
+ __FILE_vsscanf string[1];
+
+ string->f.filedes = -2;
+ string->f.modeflags = (__FLAG_NARROW|__FLAG_READONLY);
+ string->bufpos = (unsigned char *) ((void *) sp);
+ string->bufread = string->bufpos + strlen(sp);
+
+#ifdef __STDIO_MBSTATE
+#error __STDIO_MBSTATE is defined!
+#endif /* __STDIO_MBSTATE */
+
+#ifdef __STDIO_THREADSAFE
+ string->user_locking = 0;
+ __stdio_init_mutex(&string->f.lock);
+#endif
+
+ return vfscanf(&string->f, fmt, ap);
+}
+
+#elif defined(__STDIO_GLIBC_CUSTOM_STREAMS)
+
int vsscanf(__const char *sp, __const char *fmt, va_list ap)
{
FILE *f;
@@ -217,10 +260,13 @@ int vsscanf(__const char *sp, __const char *fmt, va_list ap)
return rv;
}
-#else /* __STDIO_GLIBC_CUSTOM_STREAMS */
-#warning Skipping vsscanf since no buffering and no custom streams!
-#endif /* __STDIO_GLIBC_CUSTOM_STREAMS */
-#endif /* __STDIO_BUFFERS */
+
+#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
/**********************************************************************/
@@ -617,10 +663,28 @@ int __scan_getc(register struct scan_cookie *sc)
}
if (sc->ungot_flag == 0) {
+#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__)
+ if (sc->fp->filedes != -2) {
+ 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);
@@ -962,7 +1026,13 @@ 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 (sc->fp->filedes != -2) {
+ 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. */
@@ -1146,8 +1216,8 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg)
}
fmt += i;
-#if defined(NL_ARGMAX) && (NL_ARGMAX > 0)
if (psfs.store) {
+#if defined(NL_ARGMAX) && (NL_ARGMAX > 0)
if (psfs.num_pos_args == -2) {
psfs.cur_ptr = va_arg(arg, void *);
} else {
@@ -1156,10 +1226,10 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg)
}
psfs.cur_ptr = psfs.pos_args[psfs.cur_pos_arg];
}
- }
#else /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */
- psfs.cur_ptr = va_arg(arg, void *);
+ 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[. */