]> git.ipfire.org Git - thirdparty/glibc.git/blame - stdio-common/vfscanf.c
[BZ #2510, BZ #2830, BZ #3137, BZ #3313, BZ #3426, BZ #3465, BZ #3480, BZ #3483,...
[thirdparty/glibc.git] / stdio-common / vfscanf.c
CommitLineData
11bf311e
UD
1/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006
2 Free Software Foundation, Inc.
2c6fe0bd 3 This file is part of the GNU C Library.
28f540f4 4
2c6fe0bd 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
28f540f4 9
2c6fe0bd
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
28f540f4 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
28f540f4 19
d64b6ad0 20#include <assert.h>
28f540f4
RM
21#include <errno.h>
22#include <limits.h>
23#include <ctype.h>
24#include <stdarg.h>
25#include <stdio.h>
e852e889 26#include <stdint.h>
28f540f4
RM
27#include <stdlib.h>
28#include <string.h>
8d8c6efa 29#include <wchar.h>
2c6fe0bd 30#include <wctype.h>
5107cf1d 31#include <bits/libc-lock.h>
14ea22e9 32#include <locale/localeinfo.h>
28f540f4 33
28f540f4 34#ifdef __GNUC__
14ea22e9
UD
35# define HAVE_LONGLONG
36# define LONGLONG long long
28f540f4 37#else
14ea22e9 38# define LONGLONG long
28f540f4
RM
39#endif
40
96d0213e
UD
41/* Determine whether we have to handle `long long' at all. */
42#if LONG_MAX == LONG_LONG_MAX
43# define need_longlong 0
44#else
45# define need_longlong 1
46#endif
47
859a09cf
UD
48/* Determine whether we have to handle `long'. */
49#if INT_MAX == LONG_MAX
50# define need_long 0
51#else
52# define need_long 1
53#endif
54
96aa2d94 55/* Those are flags in the conversion format. */
859a09cf
UD
56#define LONG 0x001 /* l: long or double */
57#define LONGDBL 0x002 /* L: long long or long double */
58#define SHORT 0x004 /* h: short */
59#define SUPPRESS 0x008 /* *: suppress assignment */
60#define POINTER 0x010 /* weird %p pointer (`fake hex') */
61#define NOSKIP 0x020 /* do not skip blanks */
62#define WIDTH 0x040 /* width was given */
63#define GROUP 0x080 /* ': group numbers */
64#define MALLOC 0x100 /* a: malloc strings */
65#define CHAR 0x200 /* hh: char */
a1d84548 66#define I18N 0x400 /* I: use locale's digits */
96aa2d94
RM
67
68
e3b22ad3
UD
69#include <locale/localeinfo.h>
70#include <libioP.h>
71#include <libio.h>
05be689b 72
e3b22ad3
UD
73#undef va_list
74#define va_list _IO_va_list
d64b6ad0 75
e3b22ad3
UD
76#ifdef COMPILE_WSCANF
77# define ungetc(c, s) ((void) (c == WEOF \
d64b6ad0 78 || (--read_in, \
77fe0b9c 79 INTUSE(_IO_sputbackwc) (s, c))))
e3b22ad3 80# define ungetc_not_eof(c, s) ((void) (--read_in, \
77fe0b9c 81 INTUSE(_IO_sputbackwc) (s, c)))
e3b22ad3 82# define inchar() (c == WEOF ? ((errno = inchar_errno), WEOF) \
d64b6ad0 83 : ((c = _IO_getwc_unlocked (s)), \
7d68a8ec 84 (void) (c != WEOF \
6dd67bd5
UD
85 ? ++read_in \
86 : (size_t) (inchar_errno = errno)), c))
d64b6ad0 87
e3b22ad3
UD
88# define MEMCPY(d, s, n) __wmemcpy (d, s, n)
89# define ISSPACE(Ch) iswspace (Ch)
90# define ISDIGIT(Ch) iswdigit (Ch)
91# define ISXDIGIT(Ch) iswxdigit (Ch)
92# define TOLOWER(Ch) towlower (Ch)
93# define ORIENT if (_IO_fwide (s, 1) != 1) return WEOF
94# define __strtoll_internal __wcstoll_internal
95# define __strtoull_internal __wcstoull_internal
96# define __strtol_internal __wcstol_internal
97# define __strtoul_internal __wcstoul_internal
98# define __strtold_internal __wcstold_internal
99# define __strtod_internal __wcstod_internal
100# define __strtof_internal __wcstof_internal
101
102# define L_(Str) L##Str
103# define CHAR_T wchar_t
104# define UCHAR_T unsigned int
105# define WINT_T wint_t
106# undef EOF
107# define EOF WEOF
108#else
109# define ungetc(c, s) ((void) ((int) c == EOF \
c764b9a7 110 || (--read_in, \
77fe0b9c 111 INTUSE(_IO_sputbackc) (s, (unsigned char) c))))
e3b22ad3 112# define ungetc_not_eof(c, s) ((void) (--read_in, \
77fe0b9c 113 INTUSE(_IO_sputbackc) (s, (unsigned char) c)))
e3b22ad3 114# define inchar() (c == EOF ? ((errno = inchar_errno), EOF) \
b112c02f 115 : ((c = _IO_getc_unlocked (s)), \
7d68a8ec 116 (void) (c != EOF \
6dd67bd5
UD
117 ? ++read_in \
118 : (size_t) (inchar_errno = errno)), c))
e3b22ad3
UD
119# define MEMCPY(d, s, n) memcpy (d, s, n)
120# define ISSPACE(Ch) __isspace_l (Ch, loc)
121# define ISDIGIT(Ch) __isdigit_l (Ch, loc)
122# define ISXDIGIT(Ch) __isxdigit_l (Ch, loc)
68dc4dcb 123# define TOLOWER(Ch) __tolower_l ((unsigned char) (Ch), loc)
e3b22ad3 124# define ORIENT if (_IO_vtable_offset (s) == 0 \
6b3f2b3d 125 && _IO_fwide (s, -1) != -1) \
411adb10 126 return EOF
d64b6ad0 127
e3b22ad3
UD
128# define L_(Str) Str
129# define CHAR_T char
130# define UCHAR_T unsigned char
131# define WINT_T int
132#endif
d64b6ad0 133
e3b22ad3
UD
134#define encode_error() do { \
135 errval = 4; \
2c6fe0bd 136 __set_errno (EILSEQ); \
e3b22ad3 137 goto errout; \
2c6fe0bd 138 } while (0)
e3b22ad3
UD
139#define conv_error() do { \
140 errval = 2; \
141 goto errout; \
7c713e28 142 } while (0)
e3b22ad3
UD
143#define input_error() do { \
144 errval = 1; \
145 if (done == 0) done = EOF; \
146 goto errout; \
7c713e28 147 } while (0)
e3b22ad3 148#define ARGCHECK(s, format) \
7c713e28
RM
149 do \
150 { \
151 /* Check file argument for consistence. */ \
152 CHECK_FILE (s, EOF); \
f8b87ef0
UD
153 if (s->_flags & _IO_NO_READS) \
154 { \
155 __set_errno (EBADF); \
156 return EOF; \
157 } \
158 else if (format == NULL) \
159 { \
160 MAYBE_SET_EINVAL; \
161 return EOF; \
162 } \
96aa2d94 163 } while (0)
e3b22ad3 164#define LOCK_STREAM(S) \
0dce3d15 165 __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, (S)); \
edf5b2d7 166 _IO_flockfile (S)
e3b22ad3 167#define UNLOCK_STREAM(S) \
c0fb8a56
UD
168 _IO_funlockfile (S); \
169 __libc_cleanup_region_end (0)
28f540f4
RM
170
171
172/* Read formatted input from S according to the format string
173 FORMAT, using the argument list in ARG.
174 Return the number of assignments made, or -1 for an input error. */
e3b22ad3 175#ifdef COMPILE_WSCANF
d64b6ad0 176int
c6251f03
RM
177_IO_vfwscanf (_IO_FILE *s, const wchar_t *format, _IO_va_list argptr,
178 int *errp)
e3b22ad3 179#else
28f540f4 180int
c6251f03
RM
181_IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
182 int *errp)
96aa2d94 183#endif
28f540f4 184{
4cca6b86 185 va_list arg;
d64b6ad0
UD
186 register const CHAR_T *f = format;
187 register UCHAR_T fc; /* Current character of the format. */
1dc72e4f 188 register WINT_T done = 0; /* Assignments done. */
28f540f4 189 register size_t read_in = 0; /* Chars read in. */
d64b6ad0 190 register WINT_T c = 0; /* Last char read. */
28f540f4 191 register int width; /* Maximum field width. */
0793d348 192 register int flags; /* Modifiers for current format element. */
e3b22ad3
UD
193 int errval = 0;
194#ifndef COMPILE_WSCANF
195 __locale_t loc = _NL_CURRENT_LOCALE;
196 struct locale_data *const curctype = loc->__locales[LC_CTYPE];
197#endif
0793d348 198
7d68a8ec
UD
199 /* Errno of last failed inchar call. */
200 int inchar_errno = 0;
28f540f4 201 /* Status for reading F-P nums. */
01cdeca0 202 char got_dot, got_e, negative;
28f540f4 203 /* If a [...] is a [^...]. */
d64b6ad0 204 CHAR_T not_in;
377a515b 205#define exp_char not_in
28f540f4
RM
206 /* Base for integral numbers. */
207 int base;
208 /* Signedness for integral numbers. */
209 int number_signed;
377a515b 210#define is_hexa number_signed
77a58cad 211 /* Decimal point character. */
72acaddf 212#ifdef COMPILE_WSCANF
52a7f7c0 213 wint_t decimal;
72acaddf
UD
214#else
215 const char *decimal;
216#endif
0793d348 217 /* The thousands character of the current locale. */
72acaddf 218#ifdef COMPILE_WSCANF
52a7f7c0 219 wint_t thousands;
72acaddf
UD
220#else
221 const char *thousands;
222#endif
8d8c6efa
UD
223 /* State for the conversions. */
224 mbstate_t state;
28f540f4 225 /* Integral holding variables. */
f0bf9cb9
RM
226 union
227 {
228 long long int q;
229 unsigned long long int uq;
230 long int l;
231 unsigned long int ul;
232 } num;
28f540f4 233 /* Character-buffer pointer. */
ba1ffaa1 234 char *str = NULL;
2c6fe0bd 235 wchar_t *wstr = NULL;
ba1ffaa1 236 char **strptr = NULL;
54188057 237 ssize_t strsize = 0;
05be689b
RM
238 /* We must not react on white spaces immediately because they can
239 possibly be matched even if in the input stream no character is
240 available anymore. */
241 int skip_space = 0;
c53a89d4
UD
242 /* Nonzero if we are reading a pointer. */
243 int read_pointer;
28f540f4 244 /* Workspace. */
d64b6ad0
UD
245 CHAR_T *tw; /* Temporary pointer. */
246 CHAR_T *wp = NULL; /* Workspace. */
77a58cad 247 size_t wpmax = 0; /* Maximal size of workspace. */
05be689b 248 size_t wpsize; /* Currently used bytes in workspace. */
77a58cad
RM
249#define ADDW(Ch) \
250 do \
251 { \
252 if (wpsize == wpmax) \
253 { \
d64b6ad0 254 CHAR_T *old = wp; \
44f8759b 255 wpmax = (UCHAR_MAX + 1 > 2 * wpmax ? UCHAR_MAX + 1 : 2 * wpmax); \
d64b6ad0 256 wp = (CHAR_T *) alloca (wpmax * sizeof (wchar_t)); \
05be689b 257 if (old != NULL) \
d64b6ad0 258 MEMCPY (wp, old, wpsize); \
77a58cad
RM
259 } \
260 wp[wpsize++] = (Ch); \
261 } \
262 while (0)
28f540f4 263
4cca6b86
UD
264#ifdef __va_copy
265 __va_copy (arg, argptr);
266#else
267 arg = (va_list) argptr;
268#endif
269
d64b6ad0
UD
270#ifdef ORIENT
271 ORIENT;
272#endif
273
96aa2d94 274 ARGCHECK (s, format);
28f540f4 275
e3b22ad3
UD
276 {
277#ifndef COMPILE_WSCANF
278 struct locale_data *const curnumeric = loc->__locales[LC_NUMERIC];
279#endif
280
281 /* Figure out the decimal point character. */
72acaddf 282#ifdef COMPILE_WSCANF
e3b22ad3 283 decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
72acaddf 284#else
e3b22ad3 285 decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string;
72acaddf 286#endif
e3b22ad3 287 /* Figure out the thousands separator character. */
72acaddf 288#ifdef COMPILE_WSCANF
e3b22ad3 289 thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
72acaddf 290#else
e3b22ad3
UD
291 thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string;
292 if (*thousands == '\0')
293 thousands = NULL;
72acaddf 294#endif
e3b22ad3 295 }
28f540f4 296
7c713e28 297 /* Lock the stream. */
edf5b2d7 298 LOCK_STREAM (s);
aa1075ea 299
8d8c6efa 300
72acaddf 301#ifndef COMPILE_WSCANF
8d8c6efa
UD
302 /* From now on we use `state' to convert the format string. */
303 memset (&state, '\0', sizeof (state));
d64b6ad0 304#endif
8d8c6efa 305
28f540f4
RM
306 /* Run through the format string. */
307 while (*f != '\0')
308 {
be69ea41
RM
309 unsigned int argpos;
310 /* Extract the next argument, which is of type TYPE.
311 For a %N$... spec, this is the Nth argument from the beginning;
312 otherwise it is the next argument after the state now in ARG. */
4cca6b86 313#ifdef __va_copy
96aa2d94 314# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
4cca6b86
UD
315 ({ unsigned int pos = argpos; \
316 va_list arg; \
317 __va_copy (arg, argptr); \
318 while (--pos > 0) \
319 (void) va_arg (arg, void *); \
320 va_arg (arg, type); \
321 }))
322#else
323# if 0
324 /* XXX Possible optimization. */
325# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
96aa2d94
RM
326 ({ va_list arg = (va_list) argptr; \
327 arg = (va_list) ((char *) arg \
328 + (argpos - 1) \
329 * __va_rounded_size (void *)); \
330 va_arg (arg, type); \
331 }))
4cca6b86
UD
332# else
333# define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
be69ea41
RM
334 ({ unsigned int pos = argpos; \
335 va_list arg = (va_list) argptr; \
336 while (--pos > 0) \
337 (void) va_arg (arg, void *); \
338 va_arg (arg, type); \
339 }))
4cca6b86 340# endif
96aa2d94 341#endif
be69ea41 342
72acaddf 343#ifndef COMPILE_WSCANF
44f8759b 344 if (!isascii ((unsigned char) *f))
28f540f4
RM
345 {
346 /* Non-ASCII, may be a multibyte. */
8d8c6efa 347 int len = __mbrlen (f, strlen (f), &state);
28f540f4
RM
348 if (len > 0)
349 {
3867ee64
RM
350 do
351 {
352 c = inchar ();
694b49ca 353 if (__builtin_expect (c == EOF, 0))
3867ee64 354 input_error ();
44f8759b 355 else if (c != (unsigned char) *f++)
3867ee64 356 {
44f8759b 357 ungetc_not_eof (c, s);
3867ee64
RM
358 conv_error ();
359 }
360 }
361 while (--len > 0);
28f540f4
RM
362 continue;
363 }
364 }
d64b6ad0 365#endif
28f540f4
RM
366
367 fc = *f++;
368 if (fc != '%')
369 {
05be689b 370 /* Remember to skip spaces. */
d64b6ad0 371 if (ISSPACE (fc))
05be689b
RM
372 {
373 skip_space = 1;
374 continue;
375 }
376
3867ee64
RM
377 /* Read a character. */
378 c = inchar ();
379
28f540f4 380 /* Characters other than format specs must just match. */
694b49ca 381 if (__builtin_expect (c == EOF, 0))
96aa2d94 382 input_error ();
05be689b 383
2114e10a
RM
384 /* We saw white space char as the last character in the format
385 string. Now it's time to skip all leading white space. */
05be689b 386 if (skip_space)
28f540f4 387 {
d64b6ad0 388 while (ISSPACE (c))
694b49ca 389 if (__builtin_expect (inchar () == EOF, 0))
d3b52028 390 input_error ();
05be689b 391 skip_space = 0;
28f540f4 392 }
05be689b 393
694b49ca 394 if (__builtin_expect (c != fc, 0))
3867ee64 395 {
655c0697 396 ungetc (c, s);
3867ee64
RM
397 conv_error ();
398 }
05be689b 399
28f540f4
RM
400 continue;
401 }
402
05be689b 403 /* This is the start of the conversion string. */
96aa2d94 404 flags = 0;
96aa2d94 405
c53a89d4
UD
406 /* Not yet decided whether we read a pointer or not. */
407 read_pointer = 0;
408
be69ea41
RM
409 /* Initialize state of modifiers. */
410 argpos = 0;
be69ea41 411
05be689b
RM
412 /* Prepare temporary buffer. */
413 wpsize = 0;
414
be69ea41 415 /* Check for a positional parameter specification. */
44f8759b 416 if (ISDIGIT ((UCHAR_T) *f))
be69ea41 417 {
44f8759b
UD
418 argpos = (UCHAR_T) *f++ - L_('0');
419 while (ISDIGIT ((UCHAR_T) *f))
420 argpos = argpos * 10 + ((UCHAR_T) *f++ - L_('0'));
d64b6ad0 421 if (*f == L_('$'))
be69ea41
RM
422 ++f;
423 else
424 {
425 /* Oops; that was actually the field width. */
426 width = argpos;
0793d348 427 flags |= WIDTH;
be69ea41
RM
428 argpos = 0;
429 goto got_width;
430 }
431 }
432
a1d84548
UD
433 /* Check for the assignment-suppressing, the number grouping flag,
434 and the signal to use the locale's digit representation. */
435 while (*f == L_('*') || *f == L_('\'') || *f == L_('I'))
f0bf9cb9
RM
436 switch (*f++)
437 {
d64b6ad0 438 case L_('*'):
0793d348 439 flags |= SUPPRESS;
f0bf9cb9 440 break;
d64b6ad0 441 case L_('\''):
0793d348 442 flags |= GROUP;
f0bf9cb9 443 break;
a1d84548
UD
444 case L_('I'):
445 flags |= I18N;
446 break;
f0bf9cb9
RM
447 }
448
96aa2d94 449 /* We have seen width. */
44f8759b 450 if (ISDIGIT ((UCHAR_T) *f))
96aa2d94 451 flags |= WIDTH;
96aa2d94 452
28f540f4
RM
453 /* Find the maximum field width. */
454 width = 0;
44f8759b 455 while (ISDIGIT ((UCHAR_T) *f))
28f540f4
RM
456 {
457 width *= 10;
44f8759b 458 width += (UCHAR_T) *f++ - L_('0');
28f540f4 459 }
be69ea41 460 got_width:
28f540f4
RM
461 if (width == 0)
462 width = -1;
463
464 /* Check for type modifiers. */
c3966b88
UD
465 switch (*f++)
466 {
d64b6ad0 467 case L_('h'):
c3966b88 468 /* ints are short ints or chars. */
d64b6ad0 469 if (*f == L_('h'))
c3966b88
UD
470 {
471 ++f;
472 flags |= CHAR;
473 }
474 else
475 flags |= SHORT;
476 break;
d64b6ad0
UD
477 case L_('l'):
478 if (*f == L_('l'))
c3966b88
UD
479 {
480 /* A double `l' is equivalent to an `L'. */
481 ++f;
859a09cf 482 flags |= LONGDBL | LONG;
c3966b88
UD
483 }
484 else
485 /* ints are long ints. */
486 flags |= LONG;
487 break;
d64b6ad0
UD
488 case L_('q'):
489 case L_('L'):
c3966b88 490 /* doubles are long doubles, and ints are long long ints. */
859a09cf 491 flags |= LONGDBL | LONG;
c3966b88 492 break;
d64b6ad0 493 case L_('a'):
c3966b88
UD
494 /* The `a' is used as a flag only if followed by `s', `S' or
495 `['. */
d64b6ad0 496 if (*f != L_('s') && *f != L_('S') && *f != L_('['))
c3966b88
UD
497 {
498 --f;
499 break;
500 }
501 /* String conversions (%s, %[) take a `char **'
502 arg and fill it in with a malloc'd pointer. */
503 flags |= MALLOC;
504 break;
d64b6ad0 505 case L_('z'):
96d0213e 506 if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
c3966b88
UD
507 flags |= LONGDBL;
508 else if (sizeof (size_t) > sizeof (unsigned int))
509 flags |= LONG;
510 break;
d64b6ad0 511 case L_('j'):
96d0213e 512 if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int))
c3966b88
UD
513 flags |= LONGDBL;
514 else if (sizeof (uintmax_t) > sizeof (unsigned int))
515 flags |= LONG;
516 break;
d64b6ad0 517 case L_('t'):
96d0213e 518 if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int))
c3966b88
UD
519 flags |= LONGDBL;
520 else if (sizeof (ptrdiff_t) > sizeof (int))
521 flags |= LONG;
522 break;
523 default:
524 /* Not a recognized modifier. Backup. */
525 --f;
526 break;
527 }
28f540f4
RM
528
529 /* End of the format string? */
694b49ca 530 if (__builtin_expect (*f == L_('\0'), 0))
96aa2d94 531 conv_error ();
28f540f4
RM
532
533 /* Find the conversion specifier. */
28f540f4 534 fc = *f++;
d64b6ad0 535 if (skip_space || (fc != L_('[') && fc != L_('c')
f9a06dc1 536 && fc != L_('C') && fc != L_('n')))
05be689b
RM
537 {
538 /* Eat whitespace. */
14ea22e9
UD
539 int save_errno = errno;
540 errno = 0;
3867ee64 541 do
694b49ca 542 if (__builtin_expect (inchar () == EOF && errno == EINTR, 0))
f8b87ef0 543 input_error ();
d64b6ad0 544 while (ISSPACE (c));
14ea22e9 545 errno = save_errno;
655c0697 546 ungetc (c, s);
05be689b
RM
547 skip_space = 0;
548 }
549
28f540f4
RM
550 switch (fc)
551 {
d64b6ad0 552 case L_('%'): /* Must match a literal '%'. */
14ea22e9 553 c = inchar ();
694b49ca 554 if (__builtin_expect (c == EOF, 0))
dc30f461 555 input_error ();
694b49ca 556 if (__builtin_expect (c != fc, 0))
3867ee64 557 {
44f8759b 558 ungetc_not_eof (c, s);
3867ee64
RM
559 conv_error ();
560 }
28f540f4
RM
561 break;
562
d64b6ad0 563 case L_('n'): /* Answer number of assignments done. */
01cdeca0
RM
564 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
565 with the 'n' conversion specifier. */
0793d348 566 if (!(flags & SUPPRESS))
5290baf0
UD
567 {
568 /* Don't count the read-ahead. */
96d0213e 569 if (need_longlong && (flags & LONGDBL))
5290baf0 570 *ARG (long long int *) = read_in;
859a09cf 571 else if (need_long && (flags & LONG))
5290baf0
UD
572 *ARG (long int *) = read_in;
573 else if (flags & SHORT)
574 *ARG (short int *) = read_in;
859a09cf 575 else if (!(flags & CHAR))
5290baf0 576 *ARG (int *) = read_in;
859a09cf
UD
577 else
578 *ARG (char *) = read_in;
8d57beea
UD
579
580#ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
581 /* We have a severe problem here. The ISO C standard
582 contradicts itself in explaining the effect of the %n
583 format in `scanf'. While in ISO C:1990 and the ISO C
584 Amendement 1:1995 the result is described as
585
586 Execution of a %n directive does not effect the
587 assignment count returned at the completion of
588 execution of the f(w)scanf function.
589
590 in ISO C Corrigendum 1:1994 the following was added:
591
592 Subclause 7.9.6.2
593 Add the following fourth example:
594 In:
595 #include <stdio.h>
596 int d1, d2, n1, n2, i;
597 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
598 the value 123 is assigned to d1 and the value3 to n1.
599 Because %n can never get an input failure the value
600 of 3 is also assigned to n2. The value of d2 is not
601 affected. The value 3 is assigned to i.
602
14ea22e9 603 We go for now with the historically correct code from ISO C,
8d57beea
UD
604 i.e., we don't count the %n assignments. When it ever
605 should proof to be wrong just remove the #ifdef above. */
5290baf0 606 ++done;
8d57beea 607#endif
5290baf0 608 }
28f540f4
RM
609 break;
610
d64b6ad0 611 case L_('c'): /* Match characters. */
2c6fe0bd 612 if ((flags & LONG) == 0)
28f540f4 613 {
2c6fe0bd
UD
614 if (!(flags & SUPPRESS))
615 {
616 str = ARG (char *);
617 if (str == NULL)
618 conv_error ();
619 }
28f540f4 620
14ea22e9 621 c = inchar ();
694b49ca 622 if (__builtin_expect (c == EOF, 0))
2c6fe0bd 623 input_error ();
28f540f4 624
2c6fe0bd
UD
625 if (width == -1)
626 width = 1;
28f540f4 627
72acaddf 628#ifdef COMPILE_WSCANF
d64b6ad0
UD
629 /* We have to convert the wide character(s) into multibyte
630 characters and store the result. */
631 memset (&state, '\0', sizeof (state));
632
633 do
634 {
635 size_t n;
636
4aebaa6b 637 n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
694b49ca 638 if (__builtin_expect (n == (size_t) -1, 0))
d64b6ad0
UD
639 /* No valid wide character. */
640 input_error ();
641
642 /* Increment the output pointer. Even if we don't
643 write anything. */
644 str += n;
645 }
646 while (--width > 0 && inchar () != EOF);
647#else
2c6fe0bd
UD
648 if (!(flags & SUPPRESS))
649 {
650 do
651 *str++ = c;
652 while (--width > 0 && inchar () != EOF);
653 }
654 else
655 while (--width > 0 && inchar () != EOF);
d64b6ad0 656#endif
2c6fe0bd 657
2c6fe0bd
UD
658 if (!(flags & SUPPRESS))
659 ++done;
660
661 break;
28f540f4 662 }
2c6fe0bd 663 /* FALLTHROUGH */
d64b6ad0
UD
664 case L_('C'):
665 if (!(flags & SUPPRESS))
666 {
667 wstr = ARG (wchar_t *);
0e16ecfa 668 if (wstr == NULL)
d64b6ad0
UD
669 conv_error ();
670 }
671
672 c = inchar ();
694b49ca 673 if (__builtin_expect (c == EOF, 0))
d64b6ad0
UD
674 input_error ();
675
72acaddf 676#ifdef COMPILE_WSCANF
d64b6ad0
UD
677 /* Just store the incoming wide characters. */
678 if (!(flags & SUPPRESS))
679 {
680 do
681 *wstr++ = c;
682 while (--width > 0 && inchar () != EOF);
683 }
684 else
685 while (--width > 0 && inchar () != EOF);
686#else
2c6fe0bd 687 {
d64b6ad0
UD
688 /* We have to convert the multibyte input sequence to wide
689 characters. */
68bd3326 690 char buf[1];
d64b6ad0 691 mbstate_t cstate;
28f540f4 692
d64b6ad0 693 memset (&cstate, '\0', sizeof (cstate));
edf5b2d7 694
2c6fe0bd
UD
695 do
696 {
d64b6ad0
UD
697 /* This is what we present the mbrtowc function first. */
698 buf[0] = c;
d64b6ad0
UD
699
700 while (1)
701 {
702 size_t n;
703
704 n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
2f278c94 705 buf, 1, &cstate);
d64b6ad0
UD
706
707 if (n == (size_t) -2)
708 {
709 /* Possibly correct character, just not enough
710 input. */
694b49ca 711 if (__builtin_expect (inchar () == EOF, 0))
d64b6ad0
UD
712 encode_error ();
713
2f278c94 714 buf[0] = c;
d64b6ad0
UD
715 continue;
716 }
717
694b49ca 718 if (__builtin_expect (n != 1, 0))
d64b6ad0
UD
719 encode_error ();
720
721 /* We have a match. */
722 break;
723 }
724
725 /* Advance the result pointer. */
726 ++wstr;
727 }
728 while (--width > 0 && inchar () != EOF);
2c6fe0bd 729 }
d64b6ad0 730#endif
28f540f4 731
d64b6ad0
UD
732 if (!(flags & SUPPRESS))
733 ++done;
2c6fe0bd 734
d64b6ad0
UD
735 break;
736
737 case L_('s'): /* Read a string. */
738 if (!(flags & LONG))
739 {
2c6fe0bd 740#define STRING_ARG(Str, Type) \
d64b6ad0 741 do if (!(flags & SUPPRESS)) \
28f540f4 742 { \
d64b6ad0
UD
743 if (flags & MALLOC) \
744 { \
745 /* The string is to be stored in a malloc'd buffer. */ \
746 strptr = ARG (char **); \
747 if (strptr == NULL) \
748 conv_error (); \
749 /* Allocate an initial buffer. */ \
750 strsize = 100; \
751 *strptr = (char *) malloc (strsize * sizeof (Type)); \
752 Str = (Type *) *strptr; \
753 } \
754 else \
755 Str = ARG (Type *); \
756 if (Str == NULL) \
28f540f4 757 conv_error (); \
d64b6ad0
UD
758 } while (0)
759 STRING_ARG (str, char);
28f540f4 760
d64b6ad0 761 c = inchar ();
694b49ca 762 if (__builtin_expect (c == EOF, 0))
d64b6ad0 763 input_error ();
28f540f4 764
72acaddf 765#ifdef COMPILE_WSCANF
d64b6ad0
UD
766 memset (&state, '\0', sizeof (state));
767#endif
768
769 do
3867ee64 770 {
d64b6ad0
UD
771 if (ISSPACE (c))
772 {
44f8759b 773 ungetc_not_eof (c, s);
d64b6ad0
UD
774 break;
775 }
776
72acaddf 777#ifdef COMPILE_WSCANF
d64b6ad0
UD
778 /* This is quite complicated. We have to convert the
779 wide characters into multibyte characters and then
780 store them. */
781 {
782 size_t n;
783
784 if (!(flags & SUPPRESS) && (flags & MALLOC)
785 && str + MB_CUR_MAX >= *strptr + strsize)
786 {
787 /* We have to enlarge the buffer if the `a' flag
788 was given. */
d90e1b42
UD
789 size_t strleng = str - *strptr;
790 char *newstr;
791
792 newstr = (char *) realloc (*strptr, strsize * 2);
793 if (newstr == NULL)
d64b6ad0
UD
794 {
795 /* Can't allocate that much. Last-ditch
796 effort. */
d90e1b42
UD
797 newstr = (char *) realloc (*strptr,
798 strleng + MB_CUR_MAX);
799 if (newstr == NULL)
d64b6ad0
UD
800 {
801 /* We lose. Oh well. Terminate the
802 string and stop converting,
803 so at least we don't skip any input. */
d90e1b42 804 ((char *) (*strptr))[strleng] = '\0';
d64b6ad0
UD
805 ++done;
806 conv_error ();
807 }
808 else
809 {
d90e1b42
UD
810 *strptr = newstr;
811 str = newstr + strleng;
812 strsize = strleng + MB_CUR_MAX;
d64b6ad0
UD
813 }
814 }
815 else
816 {
d90e1b42
UD
817 *strptr = newstr;
818 str = newstr + strleng;
d64b6ad0
UD
819 strsize *= 2;
820 }
821 }
822
4aebaa6b
UD
823 n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c,
824 &state);
694b49ca 825 if (__builtin_expect (n == (size_t) -1, 0))
d64b6ad0
UD
826 encode_error ();
827
828 assert (n <= MB_CUR_MAX);
829 str += n;
830 }
831#else
832 /* This is easy. */
833 if (!(flags & SUPPRESS))
834 {
835 *str++ = c;
836 if ((flags & MALLOC)
837 && (char *) str == *strptr + strsize)
838 {
839 /* Enlarge the buffer. */
840 str = (char *) realloc (*strptr, 2 * strsize);
841 if (str == NULL)
842 {
843 /* Can't allocate that much. Last-ditch
844 effort. */
845 str = (char *) realloc (*strptr, strsize + 1);
846 if (str == NULL)
847 {
848 /* We lose. Oh well. Terminate the
849 string and stop converting,
850 so at least we don't skip any input. */
851 ((char *) (*strptr))[strsize - 1] = '\0';
852 ++done;
853 conv_error ();
854 }
855 else
856 {
857 *strptr = (char *) str;
858 str += strsize;
859 ++strsize;
860 }
861 }
862 else
863 {
864 *strptr = (char *) str;
865 str += strsize;
866 strsize *= 2;
867 }
868 }
869 }
870#endif
28f540f4 871 }
d64b6ad0 872 while ((width <= 0 || --width > 0) && inchar () != EOF);
28f540f4 873
d64b6ad0
UD
874 if (!(flags & SUPPRESS))
875 {
72acaddf 876#ifdef COMPILE_WSCANF
44f8759b 877 /* We have to emit the code to get into the initial
d64b6ad0
UD
878 state. */
879 char buf[MB_LEN_MAX];
4aebaa6b 880 size_t n = __wcrtomb (buf, L'\0', &state);
d64b6ad0
UD
881 if (n > 0 && (flags & MALLOC)
882 && str + n >= *strptr + strsize)
883 {
884 /* Enlarge the buffer. */
d90e1b42
UD
885 size_t strleng = str - *strptr;
886 char *newstr;
887
888 newstr = (char *) realloc (*strptr, strleng + n + 1);
889 if (newstr == NULL)
d64b6ad0
UD
890 {
891 /* We lose. Oh well. Terminate the string
892 and stop converting, so at least we don't
893 skip any input. */
d90e1b42 894 ((char *) (*strptr))[strleng] = '\0';
d64b6ad0
UD
895 ++done;
896 conv_error ();
897 }
898 else
899 {
d90e1b42
UD
900 *strptr = newstr;
901 str = newstr + strleng;
902 strsize = strleng + n + 1;
d64b6ad0
UD
903 }
904 }
905
906 str = __mempcpy (str, buf, n);
907#endif
d90e1b42 908 *str++ = '\0';
d64b6ad0
UD
909
910 if ((flags & MALLOC) && str - *strptr != strsize)
911 {
912 char *cp = (char *) realloc (*strptr, str - *strptr);
913 if (cp != NULL)
914 *strptr = cp;
915 }
916
917 ++done;
918 }
919 break;
28f540f4 920 }
d64b6ad0 921 /* FALLTHROUGH */
28f540f4 922
d64b6ad0 923 case L_('S'):
2c6fe0bd 924 {
72acaddf 925#ifndef COMPILE_WSCANF
d64b6ad0
UD
926 mbstate_t cstate;
927#endif
928
929 /* Wide character string. */
2c6fe0bd
UD
930 STRING_ARG (wstr, wchar_t);
931
d64b6ad0 932 c = inchar ();
694b49ca 933 if (__builtin_expect (c == EOF, 0))
d64b6ad0
UD
934 input_error ();
935
72acaddf 936#ifndef COMPILE_WSCANF
d64b6ad0
UD
937 memset (&cstate, '\0', sizeof (cstate));
938#endif
939
2c6fe0bd
UD
940 do
941 {
d64b6ad0 942 if (ISSPACE (c))
2c6fe0bd 943 {
44f8759b 944 ungetc_not_eof (c, s);
2c6fe0bd
UD
945 break;
946 }
947
72acaddf 948#ifdef COMPILE_WSCANF
d64b6ad0
UD
949 /* This is easy. */
950 if (!(flags & SUPPRESS))
951 {
952 *wstr++ = c;
953 if ((flags & MALLOC)
954 && wstr == (wchar_t *) *strptr + strsize)
955 {
956 /* Enlarge the buffer. */
957 wstr = (wchar_t *) realloc (*strptr,
958 (2 * strsize)
959 * sizeof (wchar_t));
960 if (wstr == NULL)
961 {
962 /* Can't allocate that much. Last-ditch
963 effort. */
964 wstr = (wchar_t *) realloc (*strptr,
d90e1b42
UD
965 (strsize + 1)
966 * sizeof (wchar_t));
d64b6ad0
UD
967 if (wstr == NULL)
968 {
969 /* We lose. Oh well. Terminate the string
970 and stop converting, so at least we don't
971 skip any input. */
972 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
973 ++done;
974 conv_error ();
975 }
976 else
977 {
978 *strptr = (char *) wstr;
979 wstr += strsize;
980 ++strsize;
981 }
982 }
983 else
984 {
985 *strptr = (char *) wstr;
986 wstr += strsize;
987 strsize *= 2;
988 }
989 }
990 }
991#else
992 {
68bd3326 993 char buf[1];
d64b6ad0
UD
994
995 buf[0] = c;
d64b6ad0
UD
996
997 while (1)
998 {
999 size_t n;
1000
1001 n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
2f278c94 1002 buf, 1, &cstate);
d64b6ad0
UD
1003
1004 if (n == (size_t) -2)
1005 {
1006 /* Possibly correct character, just not enough
1007 input. */
694b49ca 1008 if (__builtin_expect (inchar () == EOF, 0))
d64b6ad0
UD
1009 encode_error ();
1010
2f278c94 1011 buf[0] = c;
d64b6ad0
UD
1012 continue;
1013 }
1014
694b49ca 1015 if (__builtin_expect (n != 1, 0))
d64b6ad0
UD
1016 encode_error ();
1017
1018 /* We have a match. */
2f278c94 1019 ++wstr;
d64b6ad0
UD
1020 break;
1021 }
1022
1023 if (!(flags & SUPPRESS) && (flags & MALLOC)
1024 && wstr == (wchar_t *) *strptr + strsize)
1025 {
1026 /* Enlarge the buffer. */
1027 wstr = (wchar_t *) realloc (*strptr,
1028 (2 * strsize
1029 * sizeof (wchar_t)));
1030 if (wstr == NULL)
1031 {
1032 /* Can't allocate that much. Last-ditch effort. */
1033 wstr = (wchar_t *) realloc (*strptr,
1034 ((strsize + 1)
1035 * sizeof (wchar_t)));
1036 if (wstr == NULL)
1037 {
1038 /* We lose. Oh well. Terminate the
1039 string and stop converting, so at
1040 least we don't skip any input. */
1041 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1042 ++done;
1043 conv_error ();
1044 }
1045 else
1046 {
1047 *strptr = (char *) wstr;
1048 wstr += strsize;
1049 ++strsize;
1050 }
1051 }
1052 else
1053 {
1054 *strptr = (char *) wstr;
1055 wstr += strsize;
1056 strsize *= 2;
1057 }
1058 }
1059 }
1060#endif
2c6fe0bd 1061 }
d64b6ad0 1062 while ((width <= 0 || --width > 0) && inchar () != EOF);
2c6fe0bd
UD
1063
1064 if (!(flags & SUPPRESS))
1065 {
d64b6ad0
UD
1066 *wstr++ = L'\0';
1067
1068 if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
1069 {
1070 wchar_t *cp = (wchar_t *) realloc (*strptr,
1071 ((wstr
1072 - (wchar_t *) *strptr)
1073 * sizeof(wchar_t)));
1074 if (cp != NULL)
1075 *strptr = (char *) cp;
1076 }
1077
2c6fe0bd
UD
1078 ++done;
1079 }
1080 }
1081 break;
1082
d64b6ad0
UD
1083 case L_('x'): /* Hexadecimal integer. */
1084 case L_('X'): /* Ditto. */
28f540f4
RM
1085 base = 16;
1086 number_signed = 0;
1087 goto number;
1088
d64b6ad0 1089 case L_('o'): /* Octal integer. */
28f540f4
RM
1090 base = 8;
1091 number_signed = 0;
1092 goto number;
1093
d64b6ad0 1094 case L_('u'): /* Unsigned decimal integer. */
28f540f4
RM
1095 base = 10;
1096 number_signed = 0;
1097 goto number;
1098
d64b6ad0 1099 case L_('d'): /* Signed decimal integer. */
28f540f4
RM
1100 base = 10;
1101 number_signed = 1;
1102 goto number;
1103
d64b6ad0 1104 case L_('i'): /* Generic number. */
28f540f4
RM
1105 base = 0;
1106 number_signed = 1;
1107
1108 number:
14ea22e9 1109 c = inchar ();
694b49ca 1110 if (__builtin_expect (c == EOF, 0))
96aa2d94 1111 input_error ();
28f540f4
RM
1112
1113 /* Check for a sign. */
d64b6ad0 1114 if (c == L_('-') || c == L_('+'))
28f540f4 1115 {
77a58cad 1116 ADDW (c);
28f540f4
RM
1117 if (width > 0)
1118 --width;
3867ee64 1119 c = inchar ();
28f540f4
RM
1120 }
1121
1122 /* Look for a leading indication of base. */
d64b6ad0 1123 if (width != 0 && c == L_('0'))
28f540f4
RM
1124 {
1125 if (width > 0)
1126 --width;
28f540f4 1127
be10a868 1128 ADDW (c);
3867ee64 1129 c = inchar ();
28f540f4 1130
d64b6ad0 1131 if (width != 0 && TOLOWER (c) == L_('x'))
28f540f4
RM
1132 {
1133 if (base == 0)
1134 base = 16;
1135 if (base == 16)
1136 {
1137 if (width > 0)
1138 --width;
3867ee64 1139 c = inchar ();
28f540f4
RM
1140 }
1141 }
1142 else if (base == 0)
1143 base = 8;
1144 }
1145
1146 if (base == 0)
1147 base = 10;
1148
694b49ca 1149 if (base == 10 && __builtin_expect ((flags & I18N) != 0, 0))
28f540f4 1150 {
a1d84548
UD
1151 int from_level;
1152 int to_level;
eac4282f 1153 int level;
72acaddf 1154#ifdef COMPILE_WSCANF
e87f0c33 1155 const wchar_t *wcdigits[10];
f448d449 1156 const wchar_t *wcdigits_extended[10];
a1d84548
UD
1157#else
1158 const char *mbdigits[10];
f448d449 1159 const char *mbdigits_extended[10];
a1d84548 1160#endif
f448d449
UD
1161 /* "to_inpunct" is a map from ASCII digits to their
1162 equivalent in locale. This is defined for locales
1163 which use an extra digits set. */
1164 wctrans_t map = __wctrans ("to_inpunct");
a1d84548 1165 int n;
05be689b 1166
a1d84548 1167 from_level = 0;
72acaddf 1168#ifdef COMPILE_WSCANF
a1d84548
UD
1169 to_level = _NL_CURRENT_WORD (LC_CTYPE,
1170 _NL_CTYPE_INDIGITS_WC_LEN) - 1;
1171#else
e3b22ad3 1172 to_level = (uint32_t) curctype->values[_NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN)].word - 1;
a1d84548
UD
1173#endif
1174
f448d449
UD
1175 /* Get the alternative digit forms if there are any. */
1176 if (__builtin_expect (map != NULL, 0))
1177 {
1178 /* Adding new level for extra digits set in locale file. */
1179 ++to_level;
1180
1181 for (n = 0; n < 10; ++n)
1182 {
1183#ifdef COMPILE_WSCANF
1184 wcdigits[n] = (const wchar_t *)
1185 _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
1186
1187 wchar_t *wc_extended = (wchar_t *)
1188 alloca ((to_level + 2) * sizeof (wchar_t));
1189 __wmemcpy (wc_extended, wcdigits[n], to_level);
1190 wc_extended[to_level] = __towctrans (L'0' + n, map);
1191 wc_extended[to_level + 1] = '\0';
1192 wcdigits_extended[n] = wc_extended;
1193#else
1194 mbdigits[n]
1195 = curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string;
1196
1197 /* Get the equivalent wide char in map. */
1198 wint_t extra_wcdigit = __towctrans (L'0' + n, map);
1199
1200 /* Convert it to multibyte representation. */
1201 mbstate_t state;
1202 memset (&state, '\0', sizeof (state));
1203
1204 char extra_mbdigit[MB_LEN_MAX];
1205 size_t mblen
1206 = __wcrtomb (extra_mbdigit, extra_wcdigit, &state);
1207
1208 if (mblen == (size_t) -1)
1209 {
1210 /* Ignore this new level. */
1211 map = NULL;
1212 break;
1213 }
1214
1215 /* Calculate the length of mbdigits[n]. */
1216 const char *last_char = mbdigits[n];
1217 for (level = 0; level < to_level; ++level)
1218 last_char = strchr (last_char, '\0') + 1;
1219
1220 size_t mbdigits_len = last_char - mbdigits[n];
1221
1222 /* Allocate memory for extended multibyte digit. */
1223 char *mb_extended;
1224 mb_extended = (char *) alloca (mbdigits_len + mblen + 1);
1225
1226 /* And get the mbdigits + extra_digit string. */
1227 *(char *) __mempcpy (__mempcpy (mb_extended, mbdigits[n],
1228 mbdigits_len),
1229 extra_mbdigit, mblen) = '\0';
1230 mbdigits_extended[n] = mb_extended;
1231#endif
1232 }
1233 }
1234
eac4282f
UD
1235 /* Read the number into workspace. */
1236 while (c != EOF && width != 0)
a1d84548 1237 {
eac4282f
UD
1238 /* In this round we get the pointer to the digit strings
1239 and also perform the first round of comparisons. */
1240 for (n = 0; n < 10; ++n)
1241 {
1242 /* Get the string for the digits with value N. */
72acaddf 1243#ifdef COMPILE_WSCANF
f448d449
UD
1244 if (__builtin_expect (map != NULL, 0))
1245 wcdigits[n] = wcdigits_extended[n];
1246 else
1247 wcdigits[n] = (const wchar_t *)
1248 _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
eac4282f 1249 wcdigits[n] += from_level;
a1d84548 1250
52a7f7c0 1251 if (c == (wint_t) *wcdigits[n])
eac4282f
UD
1252 {
1253 to_level = from_level;
1254 break;
1255 }
1256
1257 /* Advance the pointer to the next string. */
1258 ++wcdigits[n];
a1d84548 1259#else
eac4282f
UD
1260 const char *cmpp;
1261 int avail = width > 0 ? width : INT_MAX;
e87f0c33 1262
f448d449
UD
1263 if (__builtin_expect (map != NULL, 0))
1264 mbdigits[n] = mbdigits_extended[n];
1265 else
1266 mbdigits[n]
1267 = curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string;
a1d84548 1268
eac4282f
UD
1269 for (level = 0; level < from_level; level++)
1270 mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
a1d84548 1271
eac4282f 1272 cmpp = mbdigits[n];
44f8759b 1273 while ((unsigned char) *cmpp == c && avail > 0)
eac4282f
UD
1274 {
1275 if (*++cmpp == '\0')
1276 break;
1277 else
1278 {
1279 if ((c = inchar ()) == EOF)
1280 break;
1281 --avail;
1282 }
1283 }
1284
1285 if (*cmpp == '\0')
1286 {
1287 if (width > 0)
1288 width = avail;
1289 to_level = from_level;
1290 break;
1291 }
a1d84548 1292
eac4282f
UD
1293 /* We are pushing all read characters back. */
1294 if (cmpp > mbdigits[n])
1295 {
1296 ungetc (c, s);
1297 while (--cmpp > mbdigits[n])
44f8759b
UD
1298 ungetc_not_eof ((unsigned char) *cmpp, s);
1299 c = (unsigned char) *cmpp;
eac4282f
UD
1300 }
1301
1302 /* Advance the pointer to the next string. */
1303 mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
a1d84548 1304#endif
eac4282f 1305 }
a1d84548 1306
eac4282f 1307 if (n == 10)
a1d84548 1308 {
eac4282f
UD
1309 /* Have not yet found the digit. */
1310 for (level = from_level + 1; level <= to_level; ++level)
a1d84548 1311 {
eac4282f
UD
1312 /* Search all ten digits of this level. */
1313 for (n = 0; n < 10; ++n)
1314 {
72acaddf 1315#ifdef COMPILE_WSCANF
52a7f7c0 1316 if (c == (wint_t) *wcdigits[n])
eac4282f 1317 break;
a1d84548 1318
eac4282f
UD
1319 /* Advance the pointer to the next string. */
1320 ++wcdigits[n];
a1d84548 1321#else
eac4282f
UD
1322 const char *cmpp;
1323 int avail = width > 0 ? width : INT_MAX;
1324
1325 cmpp = mbdigits[n];
44f8759b 1326 while ((unsigned char) *cmpp == c && avail > 0)
eac4282f
UD
1327 {
1328 if (*++cmpp == '\0')
1329 break;
1330 else
1331 {
1332 if ((c = inchar ()) == EOF)
1333 break;
1334 --avail;
1335 }
1336 }
a1d84548 1337
eac4282f
UD
1338 if (*cmpp == '\0')
1339 {
1340 if (width > 0)
1341 width = avail;
1342 break;
1343 }
1344
1345 /* We are pushing all read characters back. */
1346 if (cmpp > mbdigits[n])
1347 {
1348 ungetc (c, s);
1349 while (--cmpp > mbdigits[n])
44f8759b
UD
1350 ungetc_not_eof ((unsigned char) *cmpp, s);
1351 c = (unsigned char) *cmpp;
eac4282f
UD
1352 }
1353
1354 /* Advance the pointer to the next string. */
1355 mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1356#endif
1357 }
1358
1359 if (n < 10)
a1d84548 1360 {
eac4282f
UD
1361 /* Found it. */
1362 from_level = level;
1363 to_level = level;
1364 break;
a1d84548 1365 }
eac4282f
UD
1366 }
1367 }
a1d84548 1368
eac4282f
UD
1369 if (n < 10)
1370 c = L_('0') + n;
1371 else if ((flags & GROUP)
1372#ifdef COMPILE_WSCANF
1373 && thousands != L'\0'
1374#else
1375 && thousands != NULL
1376#endif
1377 )
1378 {
1379 /* Try matching against the thousands separator. */
1380#ifdef COMPILE_WSCANF
1381 if (c != thousands)
1382 break;
1383#else
1384 const char *cmpp = thousands;
1385 int avail = width > 0 ? width : INT_MAX;
1386
44f8759b 1387 while ((unsigned char) *cmpp == c && avail > 0)
eac4282f
UD
1388 {
1389 ADDW (c);
1390 if (*++cmpp == '\0')
a1d84548 1391 break;
eac4282f
UD
1392 else
1393 {
1394 if ((c = inchar ()) == EOF)
1395 break;
1396 --avail;
1397 }
1398 }
a1d84548 1399
eac4282f
UD
1400 if (*cmpp != '\0')
1401 {
1402 /* We are pushing all read characters back. */
1403 if (cmpp > thousands)
1404 {
1405 wpsize -= cmpp - thousands;
1406 ungetc (c, s);
1407 while (--cmpp > thousands)
44f8759b
UD
1408 ungetc_not_eof ((unsigned char) *cmpp, s);
1409 c = (unsigned char) *cmpp;
eac4282f
UD
1410 }
1411 break;
a1d84548
UD
1412 }
1413
eac4282f
UD
1414 if (width > 0)
1415 width = avail;
a1d84548 1416
eac4282f
UD
1417 /* The last thousands character will be added back by
1418 the ADDW below. */
1419 --wpsize;
1420#endif
a1d84548 1421 }
eac4282f
UD
1422 else
1423 break;
a1d84548 1424
eac4282f
UD
1425 ADDW (c);
1426 if (width > 0)
1427 --width;
a1d84548 1428
eac4282f
UD
1429 c = inchar ();
1430 }
7752137a 1431 }
a1d84548
UD
1432 else
1433 /* Read the number into workspace. */
1434 while (c != EOF && width != 0)
1435 {
72acaddf
UD
1436 if (base == 16)
1437 {
1438 if (!ISXDIGIT (c))
1439 break;
1440 }
52a7f7c0 1441 else if (!ISDIGIT (c) || (int) (c - L_('0')) >= base)
72acaddf
UD
1442 {
1443 if (base == 10 && (flags & GROUP)
1444#ifdef COMPILE_WSCANF
1445 && thousands != L'\0'
1446#else
1447 && thousands != NULL
1448#endif
1449 )
1450 {
1451 /* Try matching against the thousands separator. */
1452#ifdef COMPILE_WSCANF
1453 if (c != thousands)
1454 break;
1455#else
1456 const char *cmpp = thousands;
1457 int avail = width > 0 ? width : INT_MAX;
1458
44f8759b 1459 while ((unsigned char) *cmpp == c && avail > 0)
eac4282f
UD
1460 {
1461 ADDW (c);
1462 if (*++cmpp == '\0')
1463 break;
1464 else
1465 {
1466 if ((c = inchar ()) == EOF)
1467 break;
1468 --avail;
1469 }
1470 }
72acaddf
UD
1471
1472 if (*cmpp != '\0')
1473 {
eac4282f 1474 /* We are pushing all read characters back. */
72acaddf
UD
1475 if (cmpp > thousands)
1476 {
eac4282f 1477 wpsize -= cmpp - thousands;
72acaddf
UD
1478 ungetc (c, s);
1479 while (--cmpp > thousands)
44f8759b
UD
1480 ungetc_not_eof ((unsigned char) *cmpp, s);
1481 c = (unsigned char) *cmpp;
72acaddf
UD
1482 }
1483 break;
1484 }
eac4282f 1485
72acaddf 1486 if (width > 0)
eac4282f
UD
1487 width = avail;
1488
1489 /* The last thousands character will be added back by
1490 the ADDW below. */
1491 --wpsize;
72acaddf
UD
1492#endif
1493 }
1494 else
1495 break;
1496 }
a1d84548
UD
1497 ADDW (c);
1498 if (width > 0)
1499 --width;
1500
1501 c = inchar ();
1502 }
28f540f4 1503
a1d84548
UD
1504 if (wpsize == 0
1505 || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
c53a89d4
UD
1506 {
1507 /* There was no number. If we are supposed to read a pointer
1508 we must recognize "(nil)" as well. */
694b49ca
UD
1509 if (__builtin_expect (wpsize == 0
1510 && read_pointer
1511 && (width < 0 || width >= 0)
1512 && c == '('
1513 && TOLOWER (inchar ()) == L_('n')
1514 && TOLOWER (inchar ()) == L_('i')
1515 && TOLOWER (inchar ()) == L_('l')
1516 && inchar () == L_(')'), 1))
c53a89d4
UD
1517 /* We must produce the value of a NULL pointer. A single
1518 '0' digit is enough. */
d64b6ad0 1519 ADDW (L_('0'));
c53a89d4
UD
1520 else
1521 {
1522 /* The last read character is not part of the number
1523 anymore. */
655c0697 1524 ungetc (c, s);
c53a89d4
UD
1525
1526 conv_error ();
1527 }
1528 }
1529 else
1530 /* The just read character is not part of the number anymore. */
655c0697 1531 ungetc (c, s);
28f540f4
RM
1532
1533 /* Convert the number. */
d64b6ad0 1534 ADDW (L_('\0'));
96d0213e 1535 if (need_longlong && (flags & LONGDBL))
f0bf9cb9 1536 {
be69ea41 1537 if (number_signed)
2f6d1f1b 1538 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
f0bf9cb9 1539 else
2f6d1f1b 1540 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
f0bf9cb9 1541 }
28f540f4 1542 else
f0bf9cb9 1543 {
be69ea41 1544 if (number_signed)
0793d348 1545 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
f0bf9cb9 1546 else
0793d348 1547 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
f0bf9cb9 1548 }
694b49ca 1549 if (__builtin_expect (wp == tw, 0))
28f540f4
RM
1550 conv_error ();
1551
0793d348 1552 if (!(flags & SUPPRESS))
28f540f4
RM
1553 {
1554 if (! number_signed)
1555 {
96d0213e 1556 if (need_longlong && (flags & LONGDBL))
be69ea41 1557 *ARG (unsigned LONGLONG int *) = num.uq;
859a09cf 1558 else if (need_long && (flags & LONG))
be69ea41 1559 *ARG (unsigned long int *) = num.ul;
0793d348 1560 else if (flags & SHORT)
be69ea41 1561 *ARG (unsigned short int *)
f0bf9cb9 1562 = (unsigned short int) num.ul;
859a09cf 1563 else if (!(flags & CHAR))
be69ea41 1564 *ARG (unsigned int *) = (unsigned int) num.ul;
859a09cf
UD
1565 else
1566 *ARG (unsigned char *) = (unsigned char) num.ul;
28f540f4
RM
1567 }
1568 else
1569 {
96d0213e 1570 if (need_longlong && (flags & LONGDBL))
be69ea41 1571 *ARG (LONGLONG int *) = num.q;
859a09cf 1572 else if (need_long && (flags & LONG))
be69ea41 1573 *ARG (long int *) = num.l;
0793d348 1574 else if (flags & SHORT)
be69ea41 1575 *ARG (short int *) = (short int) num.l;
859a09cf 1576 else if (!(flags & CHAR))
be69ea41 1577 *ARG (int *) = (int) num.l;
859a09cf
UD
1578 else
1579 *ARG (signed char *) = (signed char) num.ul;
28f540f4
RM
1580 }
1581 ++done;
1582 }
1583 break;
1584
d64b6ad0
UD
1585 case L_('e'): /* Floating-point numbers. */
1586 case L_('E'):
1587 case L_('f'):
233f5f68 1588 case L_('F'):
d64b6ad0
UD
1589 case L_('g'):
1590 case L_('G'):
1591 case L_('a'):
1592 case L_('A'):
14ea22e9 1593 c = inchar ();
694b49ca 1594 if (__builtin_expect (c == EOF, 0))
96aa2d94 1595 input_error ();
28f540f4 1596
918b198d
UD
1597 got_dot = got_e = 0;
1598
28f540f4 1599 /* Check for a sign. */
d64b6ad0 1600 if (c == L_('-') || c == L_('+'))
28f540f4 1601 {
d64b6ad0 1602 negative = c == L_('-');
694b49ca 1603 if (__builtin_expect (width == 0 || inchar () == EOF, 0))
28f540f4 1604 /* EOF is only an input error before we read any chars. */
96aa2d94 1605 conv_error ();
f4efd068
UD
1606 if (! ISDIGIT (c) && TOLOWER (c) != L_('i')
1607 && TOLOWER (c) != L_('n'))
8d8c6efa 1608 {
72acaddf 1609#ifdef COMPILE_WSCANF
694b49ca 1610 if (__builtin_expect (c != decimal, 0))
72acaddf
UD
1611 {
1612 /* This is no valid number. */
1613 ungetc (c, s);
fcc10ffa 1614 conv_error ();
72acaddf
UD
1615 }
1616#else
1617 /* Match against the decimal point. At this point
1618 we are taking advantage of the fact that we can
1619 push more than one character back. This is
1620 (almost) never necessary since the decimal point
1621 string hopefully never contains more than one
1622 byte. */
1623 const char *cmpp = decimal;
1624 int avail = width > 0 ? width : INT_MAX;
1625
946c5771 1626 while ((unsigned char) *cmpp == c && avail-- > 0)
72acaddf
UD
1627 if (*++cmpp == '\0')
1628 break;
1629 else
1630 {
1631 if (inchar () == EOF)
1632 break;
72acaddf
UD
1633 }
1634
694b49ca 1635 if (__builtin_expect (*cmpp != '\0', 0))
72acaddf
UD
1636 {
1637 /* This is no valid number. */
1638 while (1)
1639 {
1640 ungetc (c, s);
1641 if (cmpp == decimal)
1642 break;
44f8759b 1643 c = (unsigned char) *--cmpp;
72acaddf
UD
1644 }
1645
fcc10ffa 1646 conv_error ();
72acaddf 1647 }
918b198d
UD
1648 else
1649 {
1650 /* Add all the characters. */
1651 for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
1652 ADDW ((unsigned char) *cmpp);
1653 if (width > 0)
1654 width = avail;
1655 got_dot = 1;
1656
1657 c = inchar ();
1658 }
72acaddf 1659 if (width > 0)
eac4282f 1660 width = avail;
72acaddf 1661#endif
8d8c6efa 1662 }
28f540f4
RM
1663 if (width > 0)
1664 --width;
1665 }
01cdeca0
RM
1666 else
1667 negative = 0;
28f540f4 1668
9b26f5c4 1669 /* Take care for the special arguments "nan" and "inf". */
d64b6ad0 1670 if (TOLOWER (c) == L_('n'))
9b26f5c4
UD
1671 {
1672 /* Maybe "nan". */
1673 ADDW (c);
694b49ca
UD
1674 if (__builtin_expect (width == 0
1675 || inchar () == EOF
1676 || TOLOWER (c) != L_('a'), 0))
f4efd068 1677 conv_error ();
9df54168
UD
1678 if (width > 0)
1679 --width;
9b26f5c4 1680 ADDW (c);
694b49ca
UD
1681 if (__builtin_expect (width == 0
1682 || inchar () == EOF
1683 || TOLOWER (c) != L_('n'), 0))
f4efd068 1684 conv_error ();
9df54168
UD
1685 if (width > 0)
1686 --width;
9b26f5c4
UD
1687 ADDW (c);
1688 /* It is "nan". */
1689 goto scan_float;
1690 }
d64b6ad0 1691 else if (TOLOWER (c) == L_('i'))
9b26f5c4
UD
1692 {
1693 /* Maybe "inf" or "infinity". */
1694 ADDW (c);
694b49ca
UD
1695 if (__builtin_expect (width == 0
1696 || inchar () == EOF
1697 || TOLOWER (c) != L_('n'), 0))
f4efd068 1698 conv_error ();
9df54168
UD
1699 if (width > 0)
1700 --width;
9b26f5c4 1701 ADDW (c);
694b49ca
UD
1702 if (__builtin_expect (width == 0
1703 || inchar () == EOF
1704 || TOLOWER (c) != L_('f'), 0))
f4efd068 1705 conv_error ();
9df54168
UD
1706 if (width > 0)
1707 --width;
9b26f5c4
UD
1708 ADDW (c);
1709 /* It is as least "inf". */
9df54168 1710 if (width != 0 && inchar () != EOF)
9b26f5c4 1711 {
d64b6ad0 1712 if (TOLOWER (c) == L_('i'))
9b26f5c4 1713 {
9df54168
UD
1714 if (width > 0)
1715 --width;
8d8c6efa 1716 /* Now we have to read the rest as well. */
9b26f5c4 1717 ADDW (c);
694b49ca
UD
1718 if (__builtin_expect (width == 0
1719 || inchar () == EOF
1720 || TOLOWER (c) != L_('n'), 0))
f4efd068 1721 conv_error ();
9df54168
UD
1722 if (width > 0)
1723 --width;
9b26f5c4 1724 ADDW (c);
694b49ca
UD
1725 if (__builtin_expect (width == 0
1726 || inchar () == EOF
1727 || TOLOWER (c) != L_('i'), 0))
f4efd068 1728 conv_error ();
9df54168
UD
1729 if (width > 0)
1730 --width;
9b26f5c4 1731 ADDW (c);
694b49ca
UD
1732 if (__builtin_expect (width == 0
1733 || inchar () == EOF
1734 || TOLOWER (c) != L_('t'), 0))
f4efd068 1735 conv_error ();
9df54168
UD
1736 if (width > 0)
1737 --width;
9b26f5c4 1738 ADDW (c);
694b49ca
UD
1739 if (__builtin_expect (width == 0
1740 || inchar () == EOF
1741 || TOLOWER (c) != L_('y'), 0))
f4efd068 1742 conv_error ();
9df54168
UD
1743 if (width > 0)
1744 --width;
9b26f5c4
UD
1745 ADDW (c);
1746 }
1747 else
1748 /* Never mind. */
655c0697 1749 ungetc (c, s);
9b26f5c4
UD
1750 }
1751 goto scan_float;
1752 }
1753
63551311 1754 is_hexa = 0;
d64b6ad0 1755 exp_char = L_('e');
9df54168 1756 if (width != 0 && c == L_('0'))
377a515b 1757 {
63551311
UD
1758 ADDW (c);
1759 c = inchar ();
9df54168
UD
1760 if (width > 0)
1761 --width;
1762 if (width != 0 && TOLOWER (c) == L_('x'))
63551311
UD
1763 {
1764 /* It is a number in hexadecimal format. */
1765 ADDW (c);
377a515b 1766
63551311 1767 is_hexa = 1;
d64b6ad0 1768 exp_char = L_('p');
377a515b 1769
63551311
UD
1770 /* Grouping is not allowed. */
1771 flags &= ~GROUP;
1772 c = inchar ();
9df54168
UD
1773 if (width > 0)
1774 --width;
63551311 1775 }
377a515b
UD
1776 }
1777
28f540f4
RM
1778 do
1779 {
d64b6ad0 1780 if (ISDIGIT (c))
77a58cad 1781 ADDW (c);
d64b6ad0 1782 else if (!got_e && is_hexa && ISXDIGIT (c))
377a515b
UD
1783 ADDW (c);
1784 else if (got_e && wp[wpsize - 1] == exp_char
d64b6ad0 1785 && (c == L_('-') || c == L_('+')))
77a58cad 1786 ADDW (c);
52a7f7c0
UD
1787 else if (wpsize > 0 && !got_e
1788 && (CHAR_T) TOLOWER (c) == exp_char)
28f540f4 1789 {
377a515b 1790 ADDW (exp_char);
28f540f4
RM
1791 got_e = got_dot = 1;
1792 }
28f540f4 1793 else
377a515b 1794 {
72acaddf
UD
1795#ifdef COMPILE_WSCANF
1796 if (! got_dot && c == decimal)
1797 {
1798 ADDW (c);
1799 got_dot = 1;
1800 }
eb35b097
UD
1801 else if ((flags & GROUP) != 0 && thousands != L'\0'
1802 && ! got_dot && c == thousands)
72acaddf
UD
1803 ADDW (c);
1804 else
1805 {
1806 /* The last read character is not part of the number
1807 anymore. */
1808 ungetc (c, s);
1809 break;
1810 }
1811#else
1812 const char *cmpp = decimal;
1813 int avail = width > 0 ? width : INT_MAX;
1814
1815 if (! got_dot)
1816 {
44f8759b 1817 while ((unsigned char) *cmpp == c && avail > 0)
72acaddf
UD
1818 if (*++cmpp == '\0')
1819 break;
1820 else
1821 {
1822 if (inchar () == EOF)
1823 break;
1824 --avail;
1825 }
1826 }
1827
1828 if (*cmpp == '\0')
1829 {
1830 /* Add all the characters. */
1831 for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
44f8759b 1832 ADDW ((unsigned char) *cmpp);
72acaddf 1833 if (width > 0)
eac4282f 1834 width = avail;
72acaddf
UD
1835 got_dot = 1;
1836 }
1837 else
1838 {
1839 /* Figure out whether it is a thousands separator.
1840 There is one problem: we possibly read more than
1841 one character. We cannot push them back but since
1842 we know that parts of the `decimal' string matched,
1843 we can compare against it. */
1844 const char *cmp2p = thousands;
1845
eb35b097
UD
1846 if ((flags & GROUP) != 0 && thousands != NULL
1847 && ! got_dot)
72acaddf 1848 {
eb35b097 1849 while (cmp2p - thousands < cmpp - decimal
72acaddf
UD
1850 && *cmp2p == decimal[cmp2p - thousands])
1851 ++cmp2p;
eb35b097 1852 if (cmp2p - thousands == cmpp - decimal)
72acaddf 1853 {
44f8759b 1854 while ((unsigned char) *cmp2p == c && avail > 0)
72acaddf
UD
1855 if (*++cmp2p == '\0')
1856 break;
1857 else
1858 {
1859 if (inchar () == EOF)
1860 break;
1861 --avail;
1862 }
1863 }
1864 }
1865
1866 if (cmp2p != NULL && *cmp2p == '\0')
1867 {
1868 /* Add all the characters. */
1869 for (cmpp = thousands; *cmpp != '\0'; ++cmpp)
44f8759b 1870 ADDW ((unsigned char) *cmpp);
72acaddf 1871 if (width > 0)
eac4282f 1872 width = avail;
72acaddf
UD
1873 }
1874 else
1875 {
1876 /* The last read character is not part of the number
1877 anymore. */
1878 ungetc (c, s);
1879 break;
1880 }
1881 }
1882#endif
377a515b 1883 }
28f540f4
RM
1884 if (width > 0)
1885 --width;
01cdeca0 1886 }
377a515b 1887 while (width != 0 && inchar () != EOF);
3867ee64 1888
377a515b
UD
1889 /* Have we read any character? If we try to read a number
1890 in hexadecimal notation and we have read only the `0x'
11bf311e
UD
1891 prefix or no exponent this is an error. */
1892 if (__builtin_expect (wpsize == 0
1893 || (is_hexa && (wpsize == 2 || ! got_e)), 0))
96aa2d94 1894 conv_error ();
28f540f4 1895
9b26f5c4 1896 scan_float:
28f540f4 1897 /* Convert the number. */
d64b6ad0 1898 ADDW (L_('\0'));
c6251f03 1899 if ((flags & LONGDBL) && !__ldbl_is_dbl)
28f540f4 1900 {
0793d348
RM
1901 long double d = __strtold_internal (wp, &tw, flags & GROUP);
1902 if (!(flags & SUPPRESS) && tw != wp)
01cdeca0 1903 *ARG (long double *) = negative ? -d : d;
28f540f4 1904 }
c6251f03 1905 else if (flags & (LONG | LONGDBL))
28f540f4 1906 {
0793d348
RM
1907 double d = __strtod_internal (wp, &tw, flags & GROUP);
1908 if (!(flags & SUPPRESS) && tw != wp)
01cdeca0 1909 *ARG (double *) = negative ? -d : d;
28f540f4
RM
1910 }
1911 else
1912 {
0793d348
RM
1913 float d = __strtof_internal (wp, &tw, flags & GROUP);
1914 if (!(flags & SUPPRESS) && tw != wp)
01cdeca0 1915 *ARG (float *) = negative ? -d : d;
28f540f4
RM
1916 }
1917
694b49ca 1918 if (__builtin_expect (tw == wp, 0))
28f540f4
RM
1919 conv_error ();
1920
0793d348 1921 if (!(flags & SUPPRESS))
28f540f4
RM
1922 ++done;
1923 break;
1924
d64b6ad0 1925 case L_('['): /* Character class. */
2c6fe0bd 1926 if (flags & LONG)
d64b6ad0 1927 STRING_ARG (wstr, wchar_t);
2c6fe0bd 1928 else
d64b6ad0 1929 STRING_ARG (str, char);
28f540f4 1930
d64b6ad0 1931 if (*f == L_('^'))
28f540f4
RM
1932 {
1933 ++f;
1934 not_in = 1;
1935 }
1936 else
1937 not_in = 0;
1938
d64b6ad0
UD
1939 if (width < 0)
1940 /* There is no width given so there is also no limit on the
1941 number of characters we read. Therefore we set width to
1942 a very high value to make the algorithm easier. */
1943 width = INT_MAX;
1944
72acaddf 1945#ifdef COMPILE_WSCANF
d64b6ad0
UD
1946 /* Find the beginning and the end of the scanlist. We are not
1947 creating a lookup table since it would have to be too large.
1948 Instead we search each time through the string. This is not
1949 a constant lookup time but who uses this feature deserves to
1950 be punished. */
1951 tw = (wchar_t *) f; /* Marks the beginning. */
1952
cc7f258f 1953 if (*f == L']')
d64b6ad0
UD
1954 ++f;
1955
1956 while ((fc = *f++) != L'\0' && fc != L']');
1957
694b49ca 1958 if (__builtin_expect (fc == L'\0', 0))
d64b6ad0
UD
1959 conv_error ();
1960 wp = (wchar_t *) f - 1;
1961#else
b17178fc
RM
1962 /* Fill WP with byte flags indexed by character.
1963 We will use this flag map for matching input characters. */
44f8759b 1964 if (wpmax < UCHAR_MAX + 1)
b17178fc 1965 {
44f8759b 1966 wpmax = UCHAR_MAX + 1;
b17178fc
RM
1967 wp = (char *) alloca (wpmax);
1968 }
44f8759b 1969 memset (wp, '\0', UCHAR_MAX + 1);
b17178fc
RM
1970
1971 fc = *f;
1972 if (fc == ']' || fc == '-')
1973 {
1974 /* If ] or - appears before any char in the set, it is not
1975 the terminator or separator, but the first char in the
1976 set. */
1977 wp[fc] = 1;
1978 ++f;
1979 }
02ac66c5 1980
28f540f4 1981 while ((fc = *f++) != '\0' && fc != ']')
3f651a4d 1982 if (fc == '-' && *f != '\0' && *f != ']'
d64b6ad0
UD
1983 && (unsigned char) f[-2] <= (unsigned char) *f)
1984 {
1985 /* Add all characters from the one before the '-'
1986 up to (but not including) the next format char. */
44f8759b 1987 for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
d64b6ad0
UD
1988 wp[fc] = 1;
1989 }
1990 else
1991 /* Add the character to the flag map. */
1992 wp[fc] = 1;
1993
694b49ca 1994 if (__builtin_expect (fc == '\0', 0))
d64b6ad0
UD
1995 conv_error();
1996#endif
28f540f4 1997
2c6fe0bd 1998 if (flags & LONG)
28f540f4 1999 {
d64b6ad0 2000 size_t now = read_in;
72acaddf 2001#ifdef COMPILE_WSCANF
694b49ca 2002 if (__builtin_expect (inchar () == WEOF, 0))
d64e603a
UD
2003 input_error ();
2004
d64b6ad0
UD
2005 do
2006 {
2007 wchar_t *runp;
2008
d64b6ad0
UD
2009 /* Test whether it's in the scanlist. */
2010 runp = tw;
2011 while (runp < wp)
2012 {
cc7f258f 2013 if (runp[0] == L'-' && runp[1] != '\0' && runp + 1 != wp
d64b6ad0
UD
2014 && runp != tw
2015 && (unsigned int) runp[-1] <= (unsigned int) runp[1])
2016 {
2017 /* Match against all characters in between the
2018 first and last character of the sequence. */
2019 wchar_t wc;
2020
cc7f258f 2021 for (wc = runp[-1] + 1; wc <= runp[1]; ++wc)
52a7f7c0 2022 if ((wint_t) wc == c)
d64b6ad0
UD
2023 break;
2024
cc7f258f 2025 if (wc <= runp[1] && !not_in)
d64b6ad0 2026 break;
cc7f258f 2027 if (wc <= runp[1] && not_in)
d64b6ad0
UD
2028 {
2029 /* The current character is not in the
2030 scanset. */
73f1b067 2031 ungetc (c, s);
d64b6ad0
UD
2032 goto out;
2033 }
cc7f258f
UD
2034
2035 runp += 2;
d64b6ad0
UD
2036 }
2037 else
2038 {
52a7f7c0 2039 if ((wint_t) *runp == c && !not_in)
d64b6ad0 2040 break;
52a7f7c0 2041 if ((wint_t) *runp == c && not_in)
d64b6ad0 2042 {
73f1b067 2043 ungetc (c, s);
d64b6ad0
UD
2044 goto out;
2045 }
cc7f258f
UD
2046
2047 ++runp;
d64b6ad0 2048 }
cc7f258f 2049 }
d64b6ad0 2050
cc7f258f
UD
2051 if (runp == wp && !not_in)
2052 {
73f1b067 2053 ungetc (c, s);
cc7f258f 2054 goto out;
d64b6ad0
UD
2055 }
2056
2057 if (!(flags & SUPPRESS))
2058 {
2059 *wstr++ = c;
2060
2061 if ((flags & MALLOC)
2062 && wstr == (wchar_t *) *strptr + strsize)
2063 {
2064 /* Enlarge the buffer. */
2065 wstr = (wchar_t *) realloc (*strptr,
2066 (2 * strsize)
2067 * sizeof (wchar_t));
2068 if (wstr == NULL)
2069 {
2070 /* Can't allocate that much. Last-ditch
2071 effort. */
2072 wstr = (wchar_t *)
d90e1b42
UD
2073 realloc (*strptr, (strsize + 1)
2074 * sizeof (wchar_t));
d64b6ad0
UD
2075 if (wstr == NULL)
2076 {
2077 /* We lose. Oh well. Terminate the string
2078 and stop converting, so at least we don't
2079 skip any input. */
2080 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2081 ++done;
2082 conv_error ();
2083 }
2084 else
2085 {
2086 *strptr = (char *) wstr;
2087 wstr += strsize;
2088 ++strsize;
2089 }
2090 }
2091 else
2092 {
2093 *strptr = (char *) wstr;
2094 wstr += strsize;
2095 strsize *= 2;
2096 }
2097 }
2098 }
2099 }
d64e603a 2100 while (--width > 0 && inchar () != WEOF);
d64b6ad0
UD
2101 out:
2102#else
2103 char buf[MB_LEN_MAX];
2104 size_t cnt = 0;
2105 mbstate_t cstate;
2106
694b49ca 2107 if (__builtin_expect (inchar () == EOF, 0))
d64e603a
UD
2108 input_error ();
2109
d64b6ad0 2110 memset (&cstate, '\0', sizeof (cstate));
2c6fe0bd
UD
2111
2112 do
3867ee64 2113 {
d64b6ad0 2114 if (wp[c] == not_in)
2c6fe0bd 2115 {
44f8759b 2116 ungetc_not_eof (c, s);
2c6fe0bd
UD
2117 break;
2118 }
d64b6ad0
UD
2119
2120 /* This is easy. */
2121 if (!(flags & SUPPRESS))
2122 {
2123 size_t n;
2124
2125 /* Convert it into a wide character. */
bed38142
UD
2126 buf[0] = c;
2127 n = __mbrtowc (wstr, buf, 1, &cstate);
d64b6ad0
UD
2128
2129 if (n == (size_t) -2)
2130 {
2131 /* Possibly correct character, just not enough
2132 input. */
bed38142 2133 ++cnt;
d64b6ad0 2134 assert (cnt < MB_CUR_MAX);
d64e603a 2135 continue;
d64b6ad0 2136 }
0f740059 2137 cnt = 0;
d64b6ad0 2138
d64b6ad0
UD
2139 ++wstr;
2140 if ((flags & MALLOC)
2141 && wstr == (wchar_t *) *strptr + strsize)
2142 {
2143 /* Enlarge the buffer. */
2144 wstr = (wchar_t *) realloc (*strptr,
2145 (2 * strsize
2146 * sizeof (wchar_t)));
2147 if (wstr == NULL)
2148 {
2149 /* Can't allocate that much. Last-ditch
2150 effort. */
2151 wstr = (wchar_t *)
2152 realloc (*strptr, ((strsize + 1)
2153 * sizeof (wchar_t)));
2154 if (wstr == NULL)
2155 {
2156 /* We lose. Oh well. Terminate the
2157 string and stop converting,
2158 so at least we don't skip any input. */
2159 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2160 ++done;
2161 conv_error ();
2162 }
2163 else
2164 {
2165 *strptr = (char *) wstr;
2166 wstr += strsize;
2167 ++strsize;
2168 }
2169 }
2170 else
2171 {
2172 *strptr = (char *) wstr;
2173 wstr += strsize;
2174 strsize *= 2;
2175 }
2176 }
2177 }
d64e603a
UD
2178
2179 if (--width <= 0)
2180 break;
3867ee64 2181 }
d64e603a 2182 while (inchar () != EOF);
d64b6ad0 2183
694b49ca 2184 if (__builtin_expect (cnt != 0, 0))
d64b6ad0
UD
2185 /* We stopped in the middle of recognizing another
2186 character. That's a problem. */
2187 encode_error ();
2188#endif
3867ee64 2189
694b49ca 2190 if (__builtin_expect (now == read_in, 0))
d64b6ad0 2191 /* We haven't succesfully read any character. */
2c6fe0bd 2192 conv_error ();
28f540f4 2193
2c6fe0bd
UD
2194 if (!(flags & SUPPRESS))
2195 {
d64b6ad0
UD
2196 *wstr++ = L'\0';
2197
2198 if ((flags & MALLOC)
2199 && wstr - (wchar_t *) *strptr != strsize)
2200 {
2201 wchar_t *cp = (wchar_t *)
2202 realloc (*strptr, ((wstr - (wchar_t *) *strptr)
2203 * sizeof(wchar_t)));
2204 if (cp != NULL)
2205 *strptr = (char *) cp;
2206 }
2207
2c6fe0bd
UD
2208 ++done;
2209 }
2210 }
2211 else
28f540f4 2212 {
d64b6ad0 2213 size_t now = read_in;
d64e603a 2214
694b49ca 2215 if (__builtin_expect (inchar () == EOF, 0))
d64e603a
UD
2216 input_error ();
2217
72acaddf 2218#ifdef COMPILE_WSCANF
d64b6ad0
UD
2219
2220 memset (&state, '\0', sizeof (state));
2221
2222 do
2223 {
2224 wchar_t *runp;
2225 size_t n;
2226
d64b6ad0
UD
2227 /* Test whether it's in the scanlist. */
2228 runp = tw;
2229 while (runp < wp)
2230 {
cc7f258f 2231 if (runp[0] == L'-' && runp[1] != '\0' && runp + 1 != wp
d64b6ad0
UD
2232 && runp != tw
2233 && (unsigned int) runp[-1] <= (unsigned int) runp[1])
2234 {
2235 /* Match against all characters in between the
2236 first and last character of the sequence. */
2237 wchar_t wc;
2238
cc7f258f 2239 for (wc = runp[-1] + 1; wc <= runp[1]; ++wc)
52a7f7c0 2240 if ((wint_t) wc == c)
d64b6ad0
UD
2241 break;
2242
cc7f258f 2243 if (wc <= runp[1] && !not_in)
d64b6ad0 2244 break;
cc7f258f 2245 if (wc <= runp[1] && not_in)
d64b6ad0
UD
2246 {
2247 /* The current character is not in the
2248 scanset. */
73f1b067 2249 ungetc (c, s);
d64b6ad0
UD
2250 goto out2;
2251 }
cc7f258f
UD
2252
2253 runp += 2;
d64b6ad0
UD
2254 }
2255 else
2256 {
52a7f7c0 2257 if ((wint_t) *runp == c && !not_in)
d64b6ad0 2258 break;
52a7f7c0 2259 if ((wint_t) *runp == c && not_in)
d64b6ad0 2260 {
73f1b067 2261 ungetc (c, s);
d64b6ad0
UD
2262 goto out2;
2263 }
cc7f258f
UD
2264
2265 ++runp;
d64b6ad0 2266 }
cc7f258f 2267 }
d64b6ad0 2268
cc7f258f
UD
2269 if (runp == wp && !not_in)
2270 {
73f1b067 2271 ungetc (c, s);
cc7f258f 2272 goto out2;
d64b6ad0
UD
2273 }
2274
2275 if (!(flags & SUPPRESS))
2276 {
2277 if ((flags & MALLOC)
2278 && str + MB_CUR_MAX >= *strptr + strsize)
2279 {
2280 /* Enlarge the buffer. */
d90e1b42
UD
2281 size_t strleng = str - *strptr;
2282 char *newstr;
2283
2284 newstr = (char *) realloc (*strptr, 2 * strsize);
2285 if (newstr == NULL)
d64b6ad0
UD
2286 {
2287 /* Can't allocate that much. Last-ditch
2288 effort. */
d90e1b42
UD
2289 newstr = (char *) realloc (*strptr,
2290 strleng + MB_CUR_MAX);
2291 if (newstr == NULL)
d64b6ad0
UD
2292 {
2293 /* We lose. Oh well. Terminate the string
2294 and stop converting, so at least we don't
2295 skip any input. */
d90e1b42 2296 ((char *) (*strptr))[strleng] = '\0';
d64b6ad0
UD
2297 ++done;
2298 conv_error ();
2299 }
2300 else
2301 {
d90e1b42
UD
2302 *strptr = newstr;
2303 str = newstr + strleng;
2304 strsize = strleng + MB_CUR_MAX;
d64b6ad0
UD
2305 }
2306 }
2307 else
2308 {
d90e1b42
UD
2309 *strptr = newstr;
2310 str = newstr + strleng;
d64b6ad0
UD
2311 strsize *= 2;
2312 }
2313 }
2314 }
2315
4aebaa6b 2316 n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
694b49ca 2317 if (__builtin_expect (n == (size_t) -1, 0))
d64b6ad0
UD
2318 encode_error ();
2319
2320 assert (n <= MB_CUR_MAX);
2321 str += n;
2322 }
d64e603a 2323 while (--width > 0 && inchar () != WEOF);
d64b6ad0
UD
2324 out2:
2325#else
2c6fe0bd
UD
2326 do
2327 {
2328 if (wp[c] == not_in)
2329 {
44f8759b 2330 ungetc_not_eof (c, s);
2c6fe0bd
UD
2331 break;
2332 }
d64b6ad0
UD
2333
2334 /* This is easy. */
2335 if (!(flags & SUPPRESS))
2336 {
2337 *str++ = c;
2338 if ((flags & MALLOC)
2339 && (char *) str == *strptr + strsize)
2340 {
2341 /* Enlarge the buffer. */
e3b22ad3
UD
2342 size_t newsize = 2 * strsize;
2343
2344 allocagain:
2345 str = (char *) realloc (*strptr, newsize);
d64b6ad0
UD
2346 if (str == NULL)
2347 {
2348 /* Can't allocate that much. Last-ditch
2349 effort. */
e3b22ad3 2350 if (newsize > strsize + 1)
d64b6ad0 2351 {
e3b22ad3
UD
2352 newsize = strsize + 1;
2353 goto allocagain;
d64b6ad0 2354 }
e3b22ad3
UD
2355 /* We lose. Oh well. Terminate the
2356 string and stop converting,
2357 so at least we don't skip any input. */
2358 ((char *) (*strptr))[strsize - 1] = '\0';
2359 ++done;
2360 conv_error ();
d64b6ad0
UD
2361 }
2362 else
2363 {
2364 *strptr = (char *) str;
2365 str += strsize;
e3b22ad3 2366 strsize = newsize;
d64b6ad0
UD
2367 }
2368 }
2369 }
2c6fe0bd 2370 }
d64e603a 2371 while (--width > 0 && inchar () != EOF);
d64b6ad0 2372#endif
2c6fe0bd 2373
694b49ca 2374 if (__builtin_expect (now == read_in, 0))
d64b6ad0 2375 /* We haven't succesfully read any character. */
2c6fe0bd
UD
2376 conv_error ();
2377
2378 if (!(flags & SUPPRESS))
2379 {
72acaddf 2380#ifdef COMPILE_WSCANF
44f8759b 2381 /* We have to emit the code to get into the initial
d64b6ad0
UD
2382 state. */
2383 char buf[MB_LEN_MAX];
4aebaa6b 2384 size_t n = __wcrtomb (buf, L'\0', &state);
d64b6ad0
UD
2385 if (n > 0 && (flags & MALLOC)
2386 && str + n >= *strptr + strsize)
2387 {
2388 /* Enlarge the buffer. */
d90e1b42
UD
2389 size_t strleng = str - *strptr;
2390 char *newstr;
2391
2392 newstr = (char *) realloc (*strptr, strleng + n + 1);
2393 if (newstr == NULL)
d64b6ad0
UD
2394 {
2395 /* We lose. Oh well. Terminate the string
2396 and stop converting, so at least we don't
2397 skip any input. */
d90e1b42 2398 ((char *) (*strptr))[strleng] = '\0';
d64b6ad0
UD
2399 ++done;
2400 conv_error ();
2401 }
2402 else
2403 {
d90e1b42
UD
2404 *strptr = newstr;
2405 str = newstr + strleng;
2406 strsize = strleng + n + 1;
d64b6ad0
UD
2407 }
2408 }
2409
2410 str = __mempcpy (str, buf, n);
2411#endif
d90e1b42 2412 *str++ = '\0';
d64b6ad0
UD
2413
2414 if ((flags & MALLOC) && str - *strptr != strsize)
2415 {
2416 char *cp = (char *) realloc (*strptr, str - *strptr);
2417 if (cp != NULL)
2418 *strptr = cp;
2419 }
2420
2c6fe0bd
UD
2421 ++done;
2422 }
28f540f4
RM
2423 }
2424 break;
2425
d64b6ad0 2426 case L_('p'): /* Generic pointer. */
28f540f4
RM
2427 base = 16;
2428 /* A PTR must be the same size as a `long int'. */
0793d348 2429 flags &= ~(SHORT|LONGDBL);
859a09cf
UD
2430 if (need_long)
2431 flags |= LONG;
96aa2d94 2432 number_signed = 0;
c53a89d4 2433 read_pointer = 1;
28f540f4 2434 goto number;
47b856a9
UD
2435
2436 default:
2437 /* If this is an unknown format character punt. */
27658f20 2438 conv_error ();
28f540f4
RM
2439 }
2440 }
2441
14ea22e9 2442 /* The last thing we saw int the format string was a white space.
05be689b
RM
2443 Consume the last white spaces. */
2444 if (skip_space)
3867ee64
RM
2445 {
2446 do
2447 c = inchar ();
655c0697 2448 while (ISSPACE (c));
3867ee64
RM
2449 ungetc (c, s);
2450 }
05be689b 2451
e3b22ad3 2452 errout:
7c713e28 2453 /* Unlock stream. */
c0fb8a56 2454 UNLOCK_STREAM (s);
aa1075ea 2455
e3b22ad3
UD
2456 if (errp != NULL)
2457 *errp |= errval;
2458
3867ee64 2459 return done;
28f540f4
RM
2460}
2461
e3b22ad3 2462#ifdef COMPILE_WSCANF
d64b6ad0
UD
2463int
2464__vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
2465{
2466 return _IO_vfwscanf (s, format, argptr, NULL);
2467}
c6251f03 2468ldbl_weak_alias (__vfwscanf, vfwscanf)
e3b22ad3 2469#else
b2518f55 2470int
c6251f03 2471___vfscanf (FILE *s, const char *format, va_list argptr)
b2518f55 2472{
c6251f03 2473 return _IO_vfscanf_internal (s, format, argptr, NULL);
b2518f55 2474}
c6251f03
RM
2475ldbl_strong_alias (_IO_vfscanf_internal, _IO_vfscanf)
2476ldbl_strong_alias (___vfscanf, __vfscanf)
2477ldbl_hidden_def (___vfscanf, __vfscanf)
2478ldbl_weak_alias (___vfscanf, vfscanf)
d64b6ad0 2479#endif