* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
#endif /* LIBC_SCCS and not lint */
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.12 2004/05/02 20:13:29 obrien Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.17 2009/01/19 06:19:51 das Exp $");
#include "xlocale_private.h"
#include "namespace.h"
#include <ctype.h>
#include <inttypes.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#ifndef NO_FLOATING_POINT
static int parsefloat(FILE *, wchar_t **, size_t, locale_t loc);
-#endif /* !NO_FLOATING_POINT */
-
-extern int __scanfdebug;
+#endif
#define INCCL(_c) \
(cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \
(wmemchr(ccls, (_c), ccle - ccls) != NULL))
+static const mbstate_t initial_mbs;
+
/*
* MT-safe version.
*/
char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
int index; /* for %index$ */
va_list ap_orig; /* to reset ap to first argument */
- static const mbstate_t initial;
mbstate_t mbs;
int mb_cur_max = MB_CUR_MAX_L(loc);
break;
case 'n':
- if (flags & SUPPRESS) /* ??? */
+ {
+ void *ptr = va_arg(ap, void *);
+ if ((ptr == NULL) || (flags & SUPPRESS)) /* ??? */
continue;
- if (flags & SHORTSHORT)
- *va_arg(ap, char *) = nread;
+ else if (flags & SHORTSHORT)
+ *(char *)ptr = nread;
else if (flags & SHORT)
- *va_arg(ap, short *) = nread;
+ *(short *)ptr = nread;
else if (flags & LONG)
- *va_arg(ap, long *) = nread;
+ *(long *)ptr = nread;
else if (flags & LONGLONG)
- *va_arg(ap, long long *) = nread;
+ *(long long *)ptr = nread;
else if (flags & INTMAXT)
- *va_arg(ap, intmax_t *) = nread;
+ *(intmax_t *)ptr = nread;
else if (flags & SIZET)
- *va_arg(ap, size_t *) = nread;
+ *(size_t *)ptr = nread;
else if (flags & PTRDIFFT)
- *va_arg(ap, ptrdiff_t *) = nread;
+ *(ptrdiff_t *)ptr = nread;
else
- *va_arg(ap, int *) = nread;
+ *(int *)ptr = nread;
continue;
-
+ }
default:
goto match_failure;
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while (width != 0 &&
(wi = __fgetwc(fp, loc)) != WEOF) {
if (width >= mb_cur_max &&
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while ((wi = __fgetwc(fp, loc)) != WEOF &&
width != 0 && INCCL(wi)) {
if (width >= mb_cur_max &&
} else {
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
- mbs = initial;
+ mbs = initial_mbs;
while ((wi = __fgetwc(fp, loc)) != WEOF &&
width != 0 &&
!iswspace_l(wi, loc)) {
float res = wcstof_l(pbuf, &p, loc);
*va_arg(ap, float *) = res;
}
- if (__scanfdebug && p - pbuf != width)
- LIBC_ABORT("p - pbuf %ld != width %ld", (long)(p - pbuf), width);
nassigned++;
}
nread += width;
static int
parsefloat(FILE *fp, wchar_t **buf, size_t width, locale_t loc)
{
+ mbstate_t mbs;
+ size_t nconv;
wchar_t *commit, *p;
int infnanpos = 0;
enum {
- S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
wchar_t c;
- char *decimal_point;
wchar_t decpt;
_Bool gotmantdig = 0, ishex = 0;
wchar_t *b;
wchar_t *e;
size_t s;
+ mbs = initial_mbs;
+
+ nconv = mbrtowc_l(&decpt, localeconv()->decimal_point, MB_CUR_MAX_L(loc), &mbs, loc);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+
s = (width == 0 ? BUF : (width + 1));
if ((b = (wchar_t *)__parsefloat_buf(s * sizeof(wchar_t))) == NULL) {
*buf = NULL;
*/
commit = b - 1;
c = WEOF;
- decimal_point = localeconv_l(loc)->decimal_point;
- mbtowc_l(&decpt, decimal_point, strlen(decimal_point), loc);
for (p = b; width == 0 || p < e; ) {
if ((c = __fgetwc(fp, loc)) == WEOF)
break;
break;
case S_NAN:
switch (infnanpos) {
- case -1: /* XXX kludge to deal with nan(...) */
- goto parsedone;
case 0:
if (c != 'A' && c != 'a')
goto parsedone;
default:
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
} else if (!iswalnum_l(c, loc) && c != '_')
goto parsedone;
break;
}
infnanpos++;
break;
+ case S_DONE:
+ goto parsedone;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x') {