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