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