[uClibc-cvs] uClibc/libc/stdio Makefile, 1.40, 1.41 old_vfprintf.c, 1.8, 1.9 printf.c, 1.47, 1.48 scanf.c, 1.29, 1.30

Manuel Novoa III mjn3 at uclibc.org
Sat Sep 6 03:37:20 UTC 2003


Update of /var/cvs/uClibc/libc/stdio
In directory winder:/tmp/cvs-serv22743

Modified Files:
	Makefile old_vfprintf.c printf.c scanf.c 
Log Message:
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.


Index: old_vfprintf.c
===================================================================
RCS file: /var/cvs/uClibc/libc/stdio/old_vfprintf.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- old_vfprintf.c	5 Sep 2003 05:36:10 -0000	1.8
+++ old_vfprintf.c	6 Sep 2003 03:37:17 -0000	1.9
@@ -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 @@
 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 @@
 	OUTNSTR(fp, (const char *) buf, len);
 }
 
-
-
 #endif
 
 
@@ -207,7 +258,69 @@
 /* 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 @@
 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 @@
 			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 @@
 			} 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 @@
 					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 @@
 						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 @@
 					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 @@
 							--len;
 						}
 						++cnt;
-						putc(ch, op);
+						PUTC(ch, op);
 					}
 				}
 				goto nextfmt;
@@ -531,7 +685,7 @@
 
 	charout:
 		++cnt;
-		putc(*fmt, op);	/* normal char out */
+		PUTC(*fmt, op); /* normal char out */
 
 	nextfmt:
 		++fmt;

Index: Makefile
===================================================================
RCS file: /var/cvs/uClibc/libc/stdio/Makefile,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- Makefile	5 Sep 2003 06:50:56 -0000	1.40
+++ Makefile	6 Sep 2003 03:37:17 -0000	1.41
@@ -50,7 +50,7 @@
 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 @@
 
 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
 

Index: printf.c
===================================================================
RCS file: /var/cvs/uClibc/libc/stdio/printf.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- printf.c	1 Sep 2003 09:45:44 -0000	1.47
+++ printf.c	6 Sep 2003 03:37:17 -0000	1.48
@@ -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 @@
 #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 @@
 	}
 	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 @@
 	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 @@
 /**********************************************************************/
 #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 @@
 /**********************************************************************/
 #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 @@
 /**********************************************************************/
 #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 @@
 /**********************************************************************/
 #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 @@
 /**********************************************************************/
 #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, ...)

Index: scanf.c
===================================================================
RCS file: /var/cvs/uClibc/libc/stdio/scanf.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- scanf.c	18 Aug 2003 21:15:55 -0000	1.29
+++ scanf.c	6 Sep 2003 03:37:17 -0000	1.30
@@ -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 @@
 /**********************************************************************/
 #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 @@
 	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 @@
 #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 @@
 
 	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 @@
 
 	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 @@
 	}
 
 	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 @@
 #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 @@
 			}
 			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 @@
 					}
 					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[. */




More information about the uClibc-cvs mailing list