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