]> git.ipfire.org Git - thirdparty/glibc.git/blame - stdio-common/vfscanf.c
Use glibc_likely instead __builtin_expect.
[thirdparty/glibc.git] / stdio-common / vfscanf.c
CommitLineData
d4697bc9 1/* Copyright (C) 1991-2014 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 { \
a1ffb40e 272 if (__glibc_unlikely (wpsize == wpmax)) \
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 ();
a1ffb40e 395 if (__glibc_unlikely (c == EOF))
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. */
a1ffb40e 423 if (__glibc_unlikely (c == EOF))
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))
a1ffb40e 431 if (__glibc_unlikely (inchar () == EOF))
d3b52028 432 input_error ();
05be689b 433 skip_space = 0;
28f540f4 434 }
05be689b 435
a1ffb40e 436 if (__glibc_unlikely (c != fc))
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? */
a1ffb40e 584 if (__glibc_unlikely (*f == L_('\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 ();
a1ffb40e 613 if (__glibc_unlikely (c == EOF))
dc30f461 614 input_error ();
a1ffb40e 615 if (__glibc_unlikely (c != fc))
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 ();
a1ffb40e 713 if (__glibc_unlikely (c == EOF))
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);
a1ffb40e 761 if (__glibc_unlikely (n == (size_t) -1))
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 ();
a1ffb40e 839 if (__glibc_unlikely (c == EOF))
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. */
a1ffb40e 949 if (__glibc_unlikely (inchar () == EOF))
d64b6ad0
UD
950 encode_error ();
951
2f278c94 952 buf[0] = c;
d64b6ad0
UD
953 continue;
954 }
955
a1ffb40e 956 if (__glibc_unlikely (n != 1))
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 ();
a1ffb40e 994 if (__glibc_unlikely (c == EOF))
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);
a1ffb40e 1063 if (__glibc_unlikely (n == (size_t) -1))
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. */
a1ffb40e 1265 if (__glibc_unlikely (inchar () == EOF))
d64b6ad0
UD
1266 encode_error ();
1267
2f278c94 1268 buf[0] = c;
d64b6ad0
UD
1269 continue;
1270 }
1271
a1ffb40e 1272 if (__glibc_unlikely (n != 1))
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 ();
a1ffb40e 1371 if (__glibc_unlikely (c == EOF))
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 1436 /* Get the alternative digit forms if there are any. */
a1ffb40e 1437 if (__glibc_unlikely (map != NULL))
f448d449
UD
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
a1ffb40e 1505 if (__glibc_unlikely (map != NULL))
f448d449
UD
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
a1ffb40e 1524 if (__glibc_unlikely (map != NULL))
f448d449
UD
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)
728dab0e 1760 && (width < 0 || width >= 5)
694b49ca
UD
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 }
a1ffb40e 1798 if (__glibc_unlikely (wp == tw))
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;
a1ffb40e 1845 if (__glibc_unlikely (c == EOF))
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_('-');
a1ffb40e 1854 if (__glibc_unlikely (width == 0 || inchar () == EOF))
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 }
a4966c61
AS
1969 else
1970 got_digit = 1;
377a515b
UD
1971 }
1972
ac2ca022 1973 while (1)
28f540f4 1974 {
d64b6ad0 1975 if (ISDIGIT (c))
6ecec3b6
AS
1976 {
1977 ADDW (c);
1978 got_digit = 1;
1979 }
3979024a 1980 else if (!got_e && (flags & HEXA_FLOAT) && ISXDIGIT (c))
6ecec3b6
AS
1981 {
1982 ADDW (c);
1983 got_digit = 1;
1984 }
377a515b 1985 else if (got_e && wp[wpsize - 1] == exp_char
d64b6ad0 1986 && (c == L_('-') || c == L_('+')))
77a58cad 1987 ADDW (c);
6ecec3b6 1988 else if (got_digit && !got_e
52a7f7c0 1989 && (CHAR_T) TOLOWER (c) == exp_char)
28f540f4 1990 {
377a515b 1991 ADDW (exp_char);
28f540f4
RM
1992 got_e = got_dot = 1;
1993 }
28f540f4 1994 else
377a515b 1995 {
72acaddf
UD
1996#ifdef COMPILE_WSCANF
1997 if (! got_dot && c == decimal)
1998 {
1999 ADDW (c);
2000 got_dot = 1;
2001 }
3979024a 2002 else if ((flags & GROUP) != 0 && ! got_dot && c == thousands)
72acaddf
UD
2003 ADDW (c);
2004 else
2005 {
2006 /* The last read character is not part of the number
2007 anymore. */
2008 ungetc (c, s);
2009 break;
2010 }
2011#else
2012 const char *cmpp = decimal;
2013 int avail = width > 0 ? width : INT_MAX;
2014
2015 if (! got_dot)
2016 {
ecb72bd5 2017 while ((unsigned char) *cmpp == c && avail >= 0)
72acaddf
UD
2018 if (*++cmpp == '\0')
2019 break;
2020 else
2021 {
ecb72bd5 2022 if (avail == 0 || inchar () == EOF)
72acaddf
UD
2023 break;
2024 --avail;
2025 }
2026 }
2027
2028 if (*cmpp == '\0')
2029 {
2030 /* Add all the characters. */
2031 for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
44f8759b 2032 ADDW ((unsigned char) *cmpp);
72acaddf 2033 if (width > 0)
eac4282f 2034 width = avail;
72acaddf
UD
2035 got_dot = 1;
2036 }
2037 else
2038 {
2039 /* Figure out whether it is a thousands separator.
2040 There is one problem: we possibly read more than
2041 one character. We cannot push them back but since
2042 we know that parts of the `decimal' string matched,
2043 we can compare against it. */
2044 const char *cmp2p = thousands;
2045
3979024a 2046 if ((flags & GROUP) != 0 && ! got_dot)
72acaddf 2047 {
eb35b097 2048 while (cmp2p - thousands < cmpp - decimal
72acaddf
UD
2049 && *cmp2p == decimal[cmp2p - thousands])
2050 ++cmp2p;
eb35b097 2051 if (cmp2p - thousands == cmpp - decimal)
72acaddf 2052 {
ecb72bd5 2053 while ((unsigned char) *cmp2p == c && avail >= 0)
72acaddf
UD
2054 if (*++cmp2p == '\0')
2055 break;
2056 else
2057 {
ecb72bd5 2058 if (avail == 0 || inchar () == EOF)
72acaddf
UD
2059 break;
2060 --avail;
2061 }
2062 }
2063 }
2064
2065 if (cmp2p != NULL && *cmp2p == '\0')
2066 {
2067 /* Add all the characters. */
2068 for (cmpp = thousands; *cmpp != '\0'; ++cmpp)
44f8759b 2069 ADDW ((unsigned char) *cmpp);
72acaddf 2070 if (width > 0)
eac4282f 2071 width = avail;
72acaddf
UD
2072 }
2073 else
2074 {
2075 /* The last read character is not part of the number
2076 anymore. */
2077 ungetc (c, s);
2078 break;
2079 }
2080 }
2081#endif
377a515b 2082 }
ac2ca022
UD
2083
2084 if (width == 0 || inchar () == EOF)
2085 break;
2086
28f540f4
RM
2087 if (width > 0)
2088 --width;
01cdeca0 2089 }
3867ee64 2090
ecb72bd5
UD
2091 wctrans_t map;
2092 if (__builtin_expect ((flags & I18N) != 0, 0)
2093 /* Hexadecimal floats make no sense, fixing localized
2094 digits with ASCII letters. */
3979024a 2095 && !(flags & HEXA_FLOAT)
ecb72bd5
UD
2096 /* Minimum requirement. */
2097 && (wpsize == 0 || got_dot)
2098 && (map = __wctrans ("to_inpunct")) != NULL)
2099 {
2100 /* Reget the first character. */
2101 inchar ();
2102
2103 /* Localized digits, decimal points, and thousands
2104 separator. */
2105 wint_t wcdigits[12];
2106
2107 /* First get decimal equivalent to check if we read it
2108 or not. */
2109 wcdigits[11] = __towctrans (L'.', map);
2110
2111 /* If we have not read any character or have just read
f095bb72
UD
2112 locale decimal point which matches the decimal point
2113 for localized FP numbers, then we may have localized
2114 digits. Note, we test GOT_DOT above. */
ecb72bd5
UD
2115#ifdef COMPILE_WSCANF
2116 if (wpsize == 0 || (wpsize == 1 && wcdigits[11] == decimal))
2117#else
2118 char mbdigits[12][MB_LEN_MAX + 1];
2119
2120 mbstate_t state;
2121 memset (&state, '\0', sizeof (state));
2122
2123 bool match_so_far = wpsize == 0;
2124 size_t mblen = __wcrtomb (mbdigits[11], wcdigits[11], &state);
2125 if (mblen != (size_t) -1)
2126 {
2127 mbdigits[11][mblen] = '\0';
2128 match_so_far |= (wpsize == strlen (decimal)
2129 && strcmp (decimal, mbdigits[11]) == 0);
2130 }
2131 else
2132 {
2133 size_t decimal_len = strlen (decimal);
2134 /* This should always be the case but the data comes
2135 from a file. */
2136 if (decimal_len <= MB_LEN_MAX)
2137 {
2138 match_so_far |= wpsize == decimal_len;
2139 memcpy (mbdigits[11], decimal, decimal_len + 1);
2140 }
2141 else
2142 match_so_far = false;
2143 }
2144
2145 if (match_so_far)
2146#endif
2147 {
3979024a
UD
2148 bool have_locthousands = (flags & GROUP) != 0;
2149
ecb72bd5 2150 /* Now get the digits and the thousands-sep equivalents. */
f095bb72 2151 for (int n = 0; n < 11; ++n)
ecb72bd5
UD
2152 {
2153 if (n < 10)
2154 wcdigits[n] = __towctrans (L'0' + n, map);
2155 else if (n == 10)
3979024a
UD
2156 {
2157 wcdigits[10] = __towctrans (L',', map);
2158 have_locthousands &= wcdigits[10] != L'\0';
2159 }
ecb72bd5
UD
2160
2161#ifndef COMPILE_WSCANF
2162 memset (&state, '\0', sizeof (state));
2163
2164 size_t mblen = __wcrtomb (mbdigits[n], wcdigits[n],
2165 &state);
2166 if (mblen == (size_t) -1)
2167 {
2168 if (n == 10)
2169 {
3979024a 2170 if (have_locthousands)
ecb72bd5
UD
2171 {
2172 size_t thousands_len = strlen (thousands);
2173 if (thousands_len <= MB_LEN_MAX)
2174 memcpy (mbdigits[10], thousands,
2175 thousands_len + 1);
2176 else
2177 have_locthousands = false;
2178 }
2179 }
2180 else
2181 /* Ignore checking against localized digits. */
2182 goto no_i18nflt;
2183 }
2184 else
2185 mbdigits[n][mblen] = '\0';
2186#endif
2187 }
2188
2189 /* Start checking against localized digits, if
382466e0 2190 conversion is done correctly. */
ecb72bd5
UD
2191 while (1)
2192 {
2193 if (got_e && wp[wpsize - 1] == exp_char
2194 && (c == L_('-') || c == L_('+')))
2195 ADDW (c);
2196 else if (wpsize > 0 && !got_e
2197 && (CHAR_T) TOLOWER (c) == exp_char)
2198 {
2199 ADDW (exp_char);
2200 got_e = got_dot = 1;
2201 }
2202 else
2203 {
2204 /* Check against localized digits, decimal point,
2205 and thousands separator. */
2206 int n;
2207 for (n = 0; n < 12; ++n)
2208 {
2209#ifdef COMPILE_WSCANF
2210 if (c == wcdigits[n])
2211 {
2212 if (n < 10)
2213 ADDW (L_('0') + n);
2214 else if (n == 11 && !got_dot)
2215 {
2216 ADDW (decimal);
2217 got_dot = 1;
2218 }
2219 else if (n == 10 && have_locthousands
2220 && ! got_dot)
2221 ADDW (thousands);
2222 else
2223 /* The last read character is not part
2224 of the number anymore. */
2225 n = 12;
2226
2227 break;
2228 }
2229#else
2230 const char *cmpp = mbdigits[n];
2231 int avail = width > 0 ? width : INT_MAX;
2232
2233 while ((unsigned char) *cmpp == c && avail >= 0)
2234 if (*++cmpp == '\0')
2235 break;
2236 else
2237 {
2238 if (avail == 0 || inchar () == EOF)
2239 break;
2240 --avail;
2241 }
2242 if (*cmpp == '\0')
2243 {
2244 if (width > 0)
2245 width = avail;
2246
2247 if (n < 10)
2248 ADDW (L_('0') + n);
2249 else if (n == 11 && !got_dot)
2250 {
2251 /* Add all the characters. */
2252 for (cmpp = decimal; *cmpp != '\0';
2253 ++cmpp)
2254 ADDW ((unsigned char) *cmpp);
2255
2256 got_dot = 1;
2257 }
2258 else if (n == 10 && (flags & GROUP) != 0
4c02bf1a 2259 && ! got_dot)
ecb72bd5
UD
2260 {
2261 /* Add all the characters. */
2262 for (cmpp = thousands; *cmpp != '\0';
2263 ++cmpp)
2264 ADDW ((unsigned char) *cmpp);
2265 }
2266 else
2267 /* The last read character is not part
2268 of the number anymore. */
2269 n = 12;
2270
2271 break;
2272 }
2273
2274 /* We are pushing all read characters back. */
2275 if (cmpp > mbdigits[n])
2276 {
2277 ungetc (c, s);
2278 while (--cmpp > mbdigits[n])
2279 ungetc_not_eof ((unsigned char) *cmpp, s);
2280 c = (unsigned char) *cmpp;
2281 }
2282#endif
2283 }
2284
2285 if (n >= 12)
2286 {
2287 /* The last read character is not part
2288 of the number anymore. */
2289 ungetc (c, s);
2290 break;
2291 }
2292 }
2293
2294 if (width == 0 || inchar () == EOF)
2295 break;
2296
2297 if (width > 0)
2298 --width;
2299 }
2300 }
2301
2302#ifndef COMPILE_WSCANF
2303 no_i18nflt:
2304 ;
2305#endif
2306 }
2307
377a515b
UD
2308 /* Have we read any character? If we try to read a number
2309 in hexadecimal notation and we have read only the `0x'
bd9be679 2310 prefix this is an error. */
11bf311e 2311 if (__builtin_expect (wpsize == 0
bd9be679 2312 || ((flags & HEXA_FLOAT) && wpsize == 2), 0))
96aa2d94 2313 conv_error ();
28f540f4 2314
9b26f5c4 2315 scan_float:
28f540f4 2316 /* Convert the number. */
d64b6ad0 2317 ADDW (L_('\0'));
c6251f03 2318 if ((flags & LONGDBL) && !__ldbl_is_dbl)
28f540f4 2319 {
0793d348
RM
2320 long double d = __strtold_internal (wp, &tw, flags & GROUP);
2321 if (!(flags & SUPPRESS) && tw != wp)
01cdeca0 2322 *ARG (long double *) = negative ? -d : d;
28f540f4 2323 }
c6251f03 2324 else if (flags & (LONG | LONGDBL))
28f540f4 2325 {
0793d348
RM
2326 double d = __strtod_internal (wp, &tw, flags & GROUP);
2327 if (!(flags & SUPPRESS) && tw != wp)
01cdeca0 2328 *ARG (double *) = negative ? -d : d;
28f540f4
RM
2329 }
2330 else
2331 {
0793d348
RM
2332 float d = __strtof_internal (wp, &tw, flags & GROUP);
2333 if (!(flags & SUPPRESS) && tw != wp)
01cdeca0 2334 *ARG (float *) = negative ? -d : d;
28f540f4
RM
2335 }
2336
a1ffb40e 2337 if (__glibc_unlikely (tw == wp))
28f540f4
RM
2338 conv_error ();
2339
0793d348 2340 if (!(flags & SUPPRESS))
28f540f4
RM
2341 ++done;
2342 break;
2343
d64b6ad0 2344 case L_('['): /* Character class. */
2c6fe0bd 2345 if (flags & LONG)
874aa523 2346 STRING_ARG (wstr, wchar_t, 100);
2c6fe0bd 2347 else
874aa523 2348 STRING_ARG (str, char, 100);
28f540f4 2349
d64b6ad0 2350 if (*f == L_('^'))
28f540f4
RM
2351 {
2352 ++f;
2353 not_in = 1;
2354 }
2355 else
2356 not_in = 0;
2357
d64b6ad0
UD
2358 if (width < 0)
2359 /* There is no width given so there is also no limit on the
2360 number of characters we read. Therefore we set width to
2361 a very high value to make the algorithm easier. */
2362 width = INT_MAX;
2363
72acaddf 2364#ifdef COMPILE_WSCANF
d64b6ad0
UD
2365 /* Find the beginning and the end of the scanlist. We are not
2366 creating a lookup table since it would have to be too large.
2367 Instead we search each time through the string. This is not
2368 a constant lookup time but who uses this feature deserves to
2369 be punished. */
2370 tw = (wchar_t *) f; /* Marks the beginning. */
2371
cc7f258f 2372 if (*f == L']')
d64b6ad0
UD
2373 ++f;
2374
2375 while ((fc = *f++) != L'\0' && fc != L']');
2376
a1ffb40e 2377 if (__glibc_unlikely (fc == L'\0'))
d64b6ad0 2378 conv_error ();
4c6b2202 2379 wchar_t *twend = (wchar_t *) f - 1;
d64b6ad0 2380#else
b17178fc
RM
2381 /* Fill WP with byte flags indexed by character.
2382 We will use this flag map for matching input characters. */
44f8759b 2383 if (wpmax < UCHAR_MAX + 1)
b17178fc 2384 {
44f8759b 2385 wpmax = UCHAR_MAX + 1;
b17178fc
RM
2386 wp = (char *) alloca (wpmax);
2387 }
44f8759b 2388 memset (wp, '\0', UCHAR_MAX + 1);
b17178fc
RM
2389
2390 fc = *f;
2391 if (fc == ']' || fc == '-')
2392 {
2393 /* If ] or - appears before any char in the set, it is not
2394 the terminator or separator, but the first char in the
2395 set. */
2396 wp[fc] = 1;
2397 ++f;
2398 }
02ac66c5 2399
28f540f4 2400 while ((fc = *f++) != '\0' && fc != ']')
3f651a4d 2401 if (fc == '-' && *f != '\0' && *f != ']'
d64b6ad0
UD
2402 && (unsigned char) f[-2] <= (unsigned char) *f)
2403 {
2404 /* Add all characters from the one before the '-'
2405 up to (but not including) the next format char. */
44f8759b 2406 for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc)
d64b6ad0
UD
2407 wp[fc] = 1;
2408 }
2409 else
2410 /* Add the character to the flag map. */
2411 wp[fc] = 1;
2412
a1ffb40e 2413 if (__glibc_unlikely (fc == '\0'))
d64b6ad0
UD
2414 conv_error();
2415#endif
28f540f4 2416
2c6fe0bd 2417 if (flags & LONG)
28f540f4 2418 {
d64b6ad0 2419 size_t now = read_in;
72acaddf 2420#ifdef COMPILE_WSCANF
a1ffb40e 2421 if (__glibc_unlikely (inchar () == WEOF))
d64e603a
UD
2422 input_error ();
2423
d64b6ad0
UD
2424 do
2425 {
2426 wchar_t *runp;
2427
d64b6ad0
UD
2428 /* Test whether it's in the scanlist. */
2429 runp = tw;
4c6b2202 2430 while (runp < twend)
d64b6ad0 2431 {
4c6b2202
UD
2432 if (runp[0] == L'-' && runp[1] != '\0'
2433 && runp + 1 != twend
d64b6ad0
UD
2434 && runp != tw
2435 && (unsigned int) runp[-1] <= (unsigned int) runp[1])
2436 {
2437 /* Match against all characters in between the
2438 first and last character of the sequence. */
2439 wchar_t wc;
2440
cc7f258f 2441 for (wc = runp[-1] + 1; wc <= runp[1]; ++wc)
52a7f7c0 2442 if ((wint_t) wc == c)
d64b6ad0
UD
2443 break;
2444
cc7f258f 2445 if (wc <= runp[1] && !not_in)
d64b6ad0 2446 break;
cc7f258f 2447 if (wc <= runp[1] && not_in)
d64b6ad0
UD
2448 {
2449 /* The current character is not in the
f095bb72 2450 scanset. */
73f1b067 2451 ungetc (c, s);
d64b6ad0
UD
2452 goto out;
2453 }
cc7f258f
UD
2454
2455 runp += 2;
d64b6ad0
UD
2456 }
2457 else
2458 {
52a7f7c0 2459 if ((wint_t) *runp == c && !not_in)
d64b6ad0 2460 break;
52a7f7c0 2461 if ((wint_t) *runp == c && not_in)
d64b6ad0 2462 {
73f1b067 2463 ungetc (c, s);
d64b6ad0
UD
2464 goto out;
2465 }
cc7f258f
UD
2466
2467 ++runp;
d64b6ad0 2468 }
cc7f258f 2469 }
d64b6ad0 2470
4c6b2202 2471 if (runp == twend && !not_in)
cc7f258f 2472 {
73f1b067 2473 ungetc (c, s);
cc7f258f 2474 goto out;
d64b6ad0
UD
2475 }
2476
2477 if (!(flags & SUPPRESS))
2478 {
2479 *wstr++ = c;
2480
2481 if ((flags & MALLOC)
2482 && wstr == (wchar_t *) *strptr + strsize)
2483 {
2484 /* Enlarge the buffer. */
2485 wstr = (wchar_t *) realloc (*strptr,
2486 (2 * strsize)
2487 * sizeof (wchar_t));
2488 if (wstr == NULL)
2489 {
2490 /* Can't allocate that much. Last-ditch
2491 effort. */
2492 wstr = (wchar_t *)
d90e1b42
UD
2493 realloc (*strptr, (strsize + 1)
2494 * sizeof (wchar_t));
d64b6ad0
UD
2495 if (wstr == NULL)
2496 {
267c54dc 2497 if (flags & POSIX_MALLOC)
3f8cc204
UD
2498 {
2499 done = EOF;
2500 goto errout;
2501 }
d64b6ad0
UD
2502 /* We lose. Oh well. Terminate the string
2503 and stop converting, so at least we don't
2504 skip any input. */
2505 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
267c54dc 2506 strptr = NULL;
d64b6ad0
UD
2507 ++done;
2508 conv_error ();
2509 }
2510 else
2511 {
2512 *strptr = (char *) wstr;
2513 wstr += strsize;
2514 ++strsize;
2515 }
2516 }
2517 else
2518 {
2519 *strptr = (char *) wstr;
2520 wstr += strsize;
2521 strsize *= 2;
2522 }
2523 }
2524 }
2525 }
d64e603a 2526 while (--width > 0 && inchar () != WEOF);
d64b6ad0
UD
2527 out:
2528#else
2529 char buf[MB_LEN_MAX];
2530 size_t cnt = 0;
2531 mbstate_t cstate;
2532
a1ffb40e 2533 if (__glibc_unlikely (inchar () == EOF))
d64e603a
UD
2534 input_error ();
2535
d64b6ad0 2536 memset (&cstate, '\0', sizeof (cstate));
2c6fe0bd
UD
2537
2538 do
3867ee64 2539 {
d64b6ad0 2540 if (wp[c] == not_in)
2c6fe0bd 2541 {
44f8759b 2542 ungetc_not_eof (c, s);
2c6fe0bd
UD
2543 break;
2544 }
d64b6ad0
UD
2545
2546 /* This is easy. */
2547 if (!(flags & SUPPRESS))
2548 {
2549 size_t n;
2550
2551 /* Convert it into a wide character. */
bed38142
UD
2552 buf[0] = c;
2553 n = __mbrtowc (wstr, buf, 1, &cstate);
d64b6ad0
UD
2554
2555 if (n == (size_t) -2)
2556 {
2557 /* Possibly correct character, just not enough
2558 input. */
bed38142 2559 ++cnt;
d64b6ad0 2560 assert (cnt < MB_CUR_MAX);
d64e603a 2561 continue;
d64b6ad0 2562 }
0f740059 2563 cnt = 0;
d64b6ad0 2564
d64b6ad0
UD
2565 ++wstr;
2566 if ((flags & MALLOC)
2567 && wstr == (wchar_t *) *strptr + strsize)
2568 {
2569 /* Enlarge the buffer. */
2570 wstr = (wchar_t *) realloc (*strptr,
2571 (2 * strsize
2572 * sizeof (wchar_t)));
2573 if (wstr == NULL)
2574 {
2575 /* Can't allocate that much. Last-ditch
2576 effort. */
2577 wstr = (wchar_t *)
2578 realloc (*strptr, ((strsize + 1)
2579 * sizeof (wchar_t)));
2580 if (wstr == NULL)
2581 {
267c54dc 2582 if (flags & POSIX_MALLOC)
3f8cc204
UD
2583 {
2584 done = EOF;
2585 goto errout;
2586 }
d64b6ad0
UD
2587 /* We lose. Oh well. Terminate the
2588 string and stop converting,
2589 so at least we don't skip any input. */
2590 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
267c54dc 2591 strptr = NULL;
d64b6ad0
UD
2592 ++done;
2593 conv_error ();
2594 }
2595 else
2596 {
2597 *strptr = (char *) wstr;
2598 wstr += strsize;
2599 ++strsize;
2600 }
2601 }
2602 else
2603 {
2604 *strptr = (char *) wstr;
2605 wstr += strsize;
2606 strsize *= 2;
2607 }
2608 }
2609 }
d64e603a
UD
2610
2611 if (--width <= 0)
2612 break;
3867ee64 2613 }
d64e603a 2614 while (inchar () != EOF);
d64b6ad0 2615
a1ffb40e 2616 if (__glibc_unlikely (cnt != 0))
d64b6ad0
UD
2617 /* We stopped in the middle of recognizing another
2618 character. That's a problem. */
2619 encode_error ();
2620#endif
3867ee64 2621
a1ffb40e 2622 if (__glibc_unlikely (now == read_in))
d64b6ad0 2623 /* We haven't succesfully read any character. */
2c6fe0bd 2624 conv_error ();
28f540f4 2625
2c6fe0bd
UD
2626 if (!(flags & SUPPRESS))
2627 {
d64b6ad0
UD
2628 *wstr++ = L'\0';
2629
2630 if ((flags & MALLOC)
2631 && wstr - (wchar_t *) *strptr != strsize)
2632 {
2633 wchar_t *cp = (wchar_t *)
2634 realloc (*strptr, ((wstr - (wchar_t *) *strptr)
2635 * sizeof(wchar_t)));
2636 if (cp != NULL)
2637 *strptr = (char *) cp;
2638 }
267c54dc 2639 strptr = NULL;
d64b6ad0 2640
2c6fe0bd
UD
2641 ++done;
2642 }
2643 }
2644 else
28f540f4 2645 {
d64b6ad0 2646 size_t now = read_in;
d64e603a 2647
a1ffb40e 2648 if (__glibc_unlikely (inchar () == EOF))
d64e603a
UD
2649 input_error ();
2650
72acaddf 2651#ifdef COMPILE_WSCANF
d64b6ad0
UD
2652
2653 memset (&state, '\0', sizeof (state));
2654
2655 do
2656 {
2657 wchar_t *runp;
2658 size_t n;
2659
d64b6ad0
UD
2660 /* Test whether it's in the scanlist. */
2661 runp = tw;
4c6b2202 2662 while (runp < twend)
d64b6ad0 2663 {
4c6b2202
UD
2664 if (runp[0] == L'-' && runp[1] != '\0'
2665 && runp + 1 != twend
d64b6ad0
UD
2666 && runp != tw
2667 && (unsigned int) runp[-1] <= (unsigned int) runp[1])
2668 {
2669 /* Match against all characters in between the
2670 first and last character of the sequence. */
2671 wchar_t wc;
2672
cc7f258f 2673 for (wc = runp[-1] + 1; wc <= runp[1]; ++wc)
52a7f7c0 2674 if ((wint_t) wc == c)
d64b6ad0
UD
2675 break;
2676
cc7f258f 2677 if (wc <= runp[1] && !not_in)
d64b6ad0 2678 break;
cc7f258f 2679 if (wc <= runp[1] && not_in)
d64b6ad0
UD
2680 {
2681 /* The current character is not in the
f095bb72 2682 scanset. */
73f1b067 2683 ungetc (c, s);
d64b6ad0
UD
2684 goto out2;
2685 }
cc7f258f
UD
2686
2687 runp += 2;
d64b6ad0
UD
2688 }
2689 else
2690 {
52a7f7c0 2691 if ((wint_t) *runp == c && !not_in)
d64b6ad0 2692 break;
52a7f7c0 2693 if ((wint_t) *runp == c && not_in)
d64b6ad0 2694 {
73f1b067 2695 ungetc (c, s);
d64b6ad0
UD
2696 goto out2;
2697 }
cc7f258f
UD
2698
2699 ++runp;
d64b6ad0 2700 }
cc7f258f 2701 }
d64b6ad0 2702
4c6b2202 2703 if (runp == twend && !not_in)
cc7f258f 2704 {
73f1b067 2705 ungetc (c, s);
cc7f258f 2706 goto out2;
d64b6ad0
UD
2707 }
2708
2709 if (!(flags & SUPPRESS))
2710 {
2711 if ((flags & MALLOC)
2712 && str + MB_CUR_MAX >= *strptr + strsize)
2713 {
2714 /* Enlarge the buffer. */
d90e1b42
UD
2715 size_t strleng = str - *strptr;
2716 char *newstr;
2717
2718 newstr = (char *) realloc (*strptr, 2 * strsize);
2719 if (newstr == NULL)
d64b6ad0
UD
2720 {
2721 /* Can't allocate that much. Last-ditch
2722 effort. */
d90e1b42
UD
2723 newstr = (char *) realloc (*strptr,
2724 strleng + MB_CUR_MAX);
2725 if (newstr == NULL)
d64b6ad0 2726 {
267c54dc 2727 if (flags & POSIX_MALLOC)
3f8cc204
UD
2728 {
2729 done = EOF;
2730 goto errout;
2731 }
d64b6ad0
UD
2732 /* We lose. Oh well. Terminate the string
2733 and stop converting, so at least we don't
2734 skip any input. */
d90e1b42 2735 ((char *) (*strptr))[strleng] = '\0';
267c54dc 2736 strptr = NULL;
d64b6ad0
UD
2737 ++done;
2738 conv_error ();
2739 }
2740 else
2741 {
d90e1b42
UD
2742 *strptr = newstr;
2743 str = newstr + strleng;
2744 strsize = strleng + MB_CUR_MAX;
d64b6ad0
UD
2745 }
2746 }
2747 else
2748 {
d90e1b42
UD
2749 *strptr = newstr;
2750 str = newstr + strleng;
d64b6ad0
UD
2751 strsize *= 2;
2752 }
2753 }
2754 }
2755
4aebaa6b 2756 n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
a1ffb40e 2757 if (__glibc_unlikely (n == (size_t) -1))
d64b6ad0
UD
2758 encode_error ();
2759
2760 assert (n <= MB_CUR_MAX);
2761 str += n;
2762 }
d64e603a 2763 while (--width > 0 && inchar () != WEOF);
d64b6ad0
UD
2764 out2:
2765#else
2c6fe0bd
UD
2766 do
2767 {
2768 if (wp[c] == not_in)
2769 {
44f8759b 2770 ungetc_not_eof (c, s);
2c6fe0bd
UD
2771 break;
2772 }
d64b6ad0
UD
2773
2774 /* This is easy. */
2775 if (!(flags & SUPPRESS))
2776 {
2777 *str++ = c;
2778 if ((flags & MALLOC)
2779 && (char *) str == *strptr + strsize)
2780 {
2781 /* Enlarge the buffer. */
e3b22ad3
UD
2782 size_t newsize = 2 * strsize;
2783
2784 allocagain:
2785 str = (char *) realloc (*strptr, newsize);
d64b6ad0
UD
2786 if (str == NULL)
2787 {
2788 /* Can't allocate that much. Last-ditch
2789 effort. */
e3b22ad3 2790 if (newsize > strsize + 1)
d64b6ad0 2791 {
e3b22ad3
UD
2792 newsize = strsize + 1;
2793 goto allocagain;
d64b6ad0 2794 }
267c54dc 2795 if (flags & POSIX_MALLOC)
3f8cc204
UD
2796 {
2797 done = EOF;
2798 goto errout;
2799 }
e3b22ad3
UD
2800 /* We lose. Oh well. Terminate the
2801 string and stop converting,
2802 so at least we don't skip any input. */
2803 ((char *) (*strptr))[strsize - 1] = '\0';
267c54dc 2804 strptr = NULL;
e3b22ad3
UD
2805 ++done;
2806 conv_error ();
d64b6ad0
UD
2807 }
2808 else
2809 {
2810 *strptr = (char *) str;
2811 str += strsize;
e3b22ad3 2812 strsize = newsize;
d64b6ad0
UD
2813 }
2814 }
2815 }
2c6fe0bd 2816 }
d64e603a 2817 while (--width > 0 && inchar () != EOF);
d64b6ad0 2818#endif
2c6fe0bd 2819
a1ffb40e 2820 if (__glibc_unlikely (now == read_in))
d64b6ad0 2821 /* We haven't succesfully read any character. */
2c6fe0bd
UD
2822 conv_error ();
2823
2824 if (!(flags & SUPPRESS))
2825 {
72acaddf 2826#ifdef COMPILE_WSCANF
44f8759b 2827 /* We have to emit the code to get into the initial
d64b6ad0
UD
2828 state. */
2829 char buf[MB_LEN_MAX];
4aebaa6b 2830 size_t n = __wcrtomb (buf, L'\0', &state);
d64b6ad0
UD
2831 if (n > 0 && (flags & MALLOC)
2832 && str + n >= *strptr + strsize)
2833 {
2834 /* Enlarge the buffer. */
d90e1b42
UD
2835 size_t strleng = str - *strptr;
2836 char *newstr;
2837
2838 newstr = (char *) realloc (*strptr, strleng + n + 1);
2839 if (newstr == NULL)
d64b6ad0 2840 {
267c54dc 2841 if (flags & POSIX_MALLOC)
3f8cc204
UD
2842 {
2843 done = EOF;
2844 goto errout;
2845 }
d64b6ad0
UD
2846 /* We lose. Oh well. Terminate the string
2847 and stop converting, so at least we don't
2848 skip any input. */
d90e1b42 2849 ((char *) (*strptr))[strleng] = '\0';
267c54dc 2850 strptr = NULL;
d64b6ad0
UD
2851 ++done;
2852 conv_error ();
2853 }
2854 else
2855 {
d90e1b42
UD
2856 *strptr = newstr;
2857 str = newstr + strleng;
2858 strsize = strleng + n + 1;
d64b6ad0
UD
2859 }
2860 }
2861
2862 str = __mempcpy (str, buf, n);
2863#endif
d90e1b42 2864 *str++ = '\0';
d64b6ad0
UD
2865
2866 if ((flags & MALLOC) && str - *strptr != strsize)
2867 {
2868 char *cp = (char *) realloc (*strptr, str - *strptr);
2869 if (cp != NULL)
2870 *strptr = cp;
2871 }
267c54dc 2872 strptr = NULL;
d64b6ad0 2873
2c6fe0bd
UD
2874 ++done;
2875 }
28f540f4
RM
2876 }
2877 break;
2878
d64b6ad0 2879 case L_('p'): /* Generic pointer. */
28f540f4
RM
2880 base = 16;
2881 /* A PTR must be the same size as a `long int'. */
0793d348 2882 flags &= ~(SHORT|LONGDBL);
859a09cf
UD
2883 if (need_long)
2884 flags |= LONG;
4c02bf1a 2885 flags |= READ_POINTER;
28f540f4 2886 goto number;
47b856a9
UD
2887
2888 default:
2889 /* If this is an unknown format character punt. */
27658f20 2890 conv_error ();
28f540f4
RM
2891 }
2892 }
2893
14ea22e9 2894 /* The last thing we saw int the format string was a white space.
05be689b
RM
2895 Consume the last white spaces. */
2896 if (skip_space)
3867ee64
RM
2897 {
2898 do
2899 c = inchar ();
655c0697 2900 while (ISSPACE (c));
3867ee64
RM
2901 ungetc (c, s);
2902 }
05be689b 2903
e3b22ad3 2904 errout:
7c713e28 2905 /* Unlock stream. */
c0fb8a56 2906 UNLOCK_STREAM (s);
aa1075ea 2907
3f8cc204
UD
2908 if (use_malloc)
2909 free (wp);
2910
e3b22ad3
UD
2911 if (errp != NULL)
2912 *errp |= errval;
2913
a1ffb40e 2914 if (__glibc_unlikely (done == EOF))
267c54dc 2915 {
a1ffb40e 2916 if (__glibc_unlikely (ptrs_to_free != NULL))
267c54dc
UD
2917 {
2918 struct ptrs_to_free *p = ptrs_to_free;
2919 while (p != NULL)
2920 {
2921 for (size_t cnt = 0; cnt < p->count; ++cnt)
2922 {
2923 free (*p->ptrs[cnt]);
2924 *p->ptrs[cnt] = NULL;
2925 }
2926 p = p->next;
267c54dc
UD
2927 ptrs_to_free = p;
2928 }
2929 }
267c54dc 2930 }
a1ffb40e 2931 else if (__glibc_unlikely (strptr != NULL))
267c54dc
UD
2932 {
2933 free (*strptr);
2934 *strptr = NULL;
2935 }
3867ee64 2936 return done;
28f540f4
RM
2937}
2938
e3b22ad3 2939#ifdef COMPILE_WSCANF
d64b6ad0
UD
2940int
2941__vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
2942{
2943 return _IO_vfwscanf (s, format, argptr, NULL);
2944}
c6251f03 2945ldbl_weak_alias (__vfwscanf, vfwscanf)
e3b22ad3 2946#else
b2518f55 2947int
c6251f03 2948___vfscanf (FILE *s, const char *format, va_list argptr)
b2518f55 2949{
c6251f03 2950 return _IO_vfscanf_internal (s, format, argptr, NULL);
b2518f55 2951}
c6251f03 2952ldbl_strong_alias (_IO_vfscanf_internal, _IO_vfscanf)
d18ea0c5 2953ldbl_hidden_def (_IO_vfscanf_internal, _IO_vfscanf)
c6251f03
RM
2954ldbl_strong_alias (___vfscanf, __vfscanf)
2955ldbl_hidden_def (___vfscanf, __vfscanf)
2956ldbl_weak_alias (___vfscanf, vfscanf)
d64b6ad0 2957#endif