Enable exception handling for genops, wgenops, fileops, and wfileops.
[glibc.git] / stdio-common / vfscanf.c
blobd618851a8948f1b888b20be39f7dd5592573c03a
1 /* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
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
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #include <assert.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <ctype.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <wchar.h>
29 #include <wctype.h>
30 #include <bits/libc-lock.h>
31 #include <locale/localeinfo.h>
33 #ifdef __GNUC__
34 # define HAVE_LONGLONG
35 # define LONGLONG long long
36 #else
37 # define LONGLONG long
38 #endif
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
47 /* Determine whether we have to handle `long'. */
48 #if INT_MAX == LONG_MAX
49 # define need_long 0
50 #else
51 # define need_long 1
52 #endif
54 /* Those are flags in the conversion format. */
55 #define LONG 0x001 /* l: long or double */
56 #define LONGDBL 0x002 /* L: long long or long double */
57 #define SHORT 0x004 /* h: short */
58 #define SUPPRESS 0x008 /* *: suppress assignment */
59 #define POINTER 0x010 /* weird %p pointer (`fake hex') */
60 #define NOSKIP 0x020 /* do not skip blanks */
61 #define WIDTH 0x040 /* width was given */
62 #define GROUP 0x080 /* ': group numbers */
63 #define MALLOC 0x100 /* a: malloc strings */
64 #define CHAR 0x200 /* hh: char */
65 #define I18N 0x400 /* I: use locale's digits */
68 #ifdef USE_IN_LIBIO
69 # include <libioP.h>
70 # include <libio.h>
72 # undef va_list
73 # define va_list _IO_va_list
75 # ifdef COMPILE_WSCANF
76 # define ungetc(c, s) ((void) (c == WEOF \
77 || (--read_in, \
78 _IO_sputbackwc (s, c))))
79 # define inchar() (c == WEOF ? WEOF \
80 : ((c = _IO_getwc_unlocked (s)), \
81 (void) (c != WEOF && ++read_in), c))
83 # define MEMCPY(d, s, n) wmemcpy (d, s, n)
84 # define ISSPACE(Ch) iswspace (Ch)
85 # define ISDIGIT(Ch) iswdigit (Ch)
86 # define ISXDIGIT(Ch) iswxdigit (Ch)
87 # define TOLOWER(Ch) towlower (Ch)
88 # define ORIENT if (s->_vtable_offset == 0 && _IO_fwide (s, 1) != 1)\
89 return WEOF
90 # define __strtoll_internal __wcstoll_internal
91 # define __strtoull_internal __wcstoull_internal
92 # define __strtol_internal __wcstol_internal
93 # define __strtoul_internal __wcstoul_internal
94 # define __strtold_internal __wcstold_internal
95 # define __strtod_internal __wcstod_internal
96 # define __strtof_internal __wcstof_internal
98 # define L_(Str) L##Str
99 # define CHAR_T wchar_t
100 # define UCHAR_T unsigned int
101 # define WINT_T wint_t
102 # undef EOF
103 # define EOF WEOF
104 # else
105 # define ungetc(c, s) ((void) ((int) c == EOF \
106 || (--read_in, \
107 _IO_sputbackc (s, (unsigned char) c))))
108 # define inchar() (c == EOF ? EOF \
109 : ((c = _IO_getc_unlocked (s)), \
110 (void) (c != EOF && ++read_in), c))
111 # define MEMCPY(d, s, n) memcpy (d, s, n)
112 # define ISSPACE(Ch) isspace (Ch)
113 # define ISDIGIT(Ch) isdigit (Ch)
114 # define ISXDIGIT(Ch) isxdigit (Ch)
115 # define TOLOWER(Ch) tolower (Ch)
116 # define ORIENT if (_IO_fwide (s, -1) != -1) return EOF
118 # define L_(Str) Str
119 # define CHAR_T char
120 # define UCHAR_T unsigned char
121 # define WINT_T int
122 # endif
124 # define encode_error() do { \
125 if (errp != NULL) *errp |= 4; \
126 _IO_funlockfile (s); \
127 __libc_cleanup_end (0); \
128 __set_errno (EILSEQ); \
129 return done; \
130 } while (0)
131 # define conv_error() do { \
132 if (errp != NULL) *errp |= 2; \
133 _IO_funlockfile (s); \
134 __libc_cleanup_end (0); \
135 return done; \
136 } while (0)
137 # define input_error() do { \
138 _IO_funlockfile (s); \
139 if (errp != NULL) *errp |= 1; \
140 __libc_cleanup_end (0); \
141 return done ?: EOF; \
142 } while (0)
143 # define memory_error() do { \
144 _IO_funlockfile (s); \
145 __set_errno (ENOMEM); \
146 __libc_cleanup_end (0); \
147 return EOF; \
148 } while (0)
149 # define ARGCHECK(s, format) \
150 do \
152 /* Check file argument for consistence. */ \
153 CHECK_FILE (s, EOF); \
154 if (s->_flags & _IO_NO_READS) \
156 __set_errno (EBADF); \
157 return EOF; \
159 else if (format == NULL) \
161 MAYBE_SET_EINVAL; \
162 return EOF; \
164 } while (0)
165 # define LOCK_STREAM(S) \
166 __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \
167 _IO_flockfile (S)
168 # define UNLOCK_STREAM(S) \
169 _IO_funlockfile (S); \
170 __libc_cleanup_region_end (0)
171 #else
172 # define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s))
173 # define inchar() (c == EOF ? EOF \
174 : ((c = getc (s)), (void) (c != EOF && ++read_in), c))
175 # define MEMCPY(d, s, n) memcpy (d, s, n)
176 # define ISSPACE(Ch) isspace (Ch)
177 # define ISDIGIT(Ch) isdigit (Ch)
178 # define ISXDIGIT(Ch) isxdigit (Ch)
179 # define TOLOWER(Ch) tolower (Ch)
181 # define L_(Str) Str
182 # define CHAR_T char
183 # define UCHAR_T unsigned char
184 # define WINT_T int
186 # define encode_error() do { \
187 funlockfile (s); \
188 __set_errno (EILSEQ); \
189 return done; \
190 } while (0)
191 # define conv_error() do { \
192 funlockfile (s); \
193 return done; \
194 } while (0)
195 # define input_error() do { \
196 funlockfile (s); \
197 return done ?: EOF; \
198 } while (0)
199 # define memory_error() do { \
200 funlockfile (s); \
201 __set_errno (ENOMEM); \
202 return EOF; \
203 } while (0)
204 # define ARGCHECK(s, format) \
205 do \
207 /* Check file argument for consistence. */ \
208 if (!__validfp (s) || !s->__mode.__read) \
210 __set_errno (EBADF); \
211 return EOF; \
213 else if (format == NULL) \
215 __set_errno (EINVAL); \
216 return EOF; \
218 } while (0)
219 #if 1
220 /* XXX For now !!! */
221 # define flockfile(S) /* nothing */
222 # define funlockfile(S) /* nothing */
223 # define LOCK_STREAM(S)
224 # define UNLOCK_STREAM(S)
225 #else
226 # define LOCK_STREAM(S) \
227 __libc_cleanup_region_start (&__funlockfile, (S)); \
228 __flockfile (S)
229 # define UNLOCK_STREAM(S) \
230 __funlockfile (S); \
231 __libc_cleanup_region_end (0)
232 #endif
233 #endif
236 /* Read formatted input from S according to the format string
237 FORMAT, using the argument list in ARG.
238 Return the number of assignments made, or -1 for an input error. */
239 #ifdef USE_IN_LIBIO
240 # ifdef COMPILE_WSCANF
242 _IO_vfwscanf (s, format, argptr, errp)
243 _IO_FILE *s;
244 const wchar_t *format;
245 _IO_va_list argptr;
246 int *errp;
247 # else
249 _IO_vfscanf (s, format, argptr, errp)
250 _IO_FILE *s;
251 const char *format;
252 _IO_va_list argptr;
253 int *errp;
254 # endif
255 #else
257 __vfscanf (FILE *s, const char *format, va_list argptr)
258 #endif
260 va_list arg;
261 register const CHAR_T *f = format;
262 register UCHAR_T fc; /* Current character of the format. */
263 register size_t done = 0; /* Assignments done. */
264 register size_t read_in = 0; /* Chars read in. */
265 register WINT_T c = 0; /* Last char read. */
266 register int width; /* Maximum field width. */
267 register int flags; /* Modifiers for current format element. */
269 /* Status for reading F-P nums. */
270 char got_dot, got_e, negative;
271 /* If a [...] is a [^...]. */
272 CHAR_T not_in;
273 #define exp_char not_in
274 /* Base for integral numbers. */
275 int base;
276 /* Signedness for integral numbers. */
277 int number_signed;
278 #define is_hexa number_signed
279 /* Decimal point character. */
280 #ifdef COMPILE_WSCANF
281 wchar_t decimal;
282 #else
283 const char *decimal;
284 #endif
285 /* The thousands character of the current locale. */
286 #ifdef COMPILE_WSCANF
287 wchar_t thousands;
288 #else
289 const char *thousands;
290 #endif
291 /* State for the conversions. */
292 mbstate_t state;
293 /* Integral holding variables. */
294 union
296 long long int q;
297 unsigned long long int uq;
298 long int l;
299 unsigned long int ul;
300 } num;
301 /* Character-buffer pointer. */
302 char *str = NULL;
303 wchar_t *wstr = NULL;
304 char **strptr = NULL;
305 size_t strsize = 0;
306 /* We must not react on white spaces immediately because they can
307 possibly be matched even if in the input stream no character is
308 available anymore. */
309 int skip_space = 0;
310 /* Nonzero if we are reading a pointer. */
311 int read_pointer;
312 /* Workspace. */
313 CHAR_T *tw; /* Temporary pointer. */
314 CHAR_T *wp = NULL; /* Workspace. */
315 size_t wpmax = 0; /* Maximal size of workspace. */
316 size_t wpsize; /* Currently used bytes in workspace. */
317 #define ADDW(Ch) \
318 do \
320 if (wpsize == wpmax) \
322 CHAR_T *old = wp; \
323 wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \
324 wp = (CHAR_T *) alloca (wpmax * sizeof (wchar_t)); \
325 if (old != NULL) \
326 MEMCPY (wp, old, wpsize); \
328 wp[wpsize++] = (Ch); \
330 while (0)
332 #ifdef __va_copy
333 __va_copy (arg, argptr);
334 #else
335 arg = (va_list) argptr;
336 #endif
338 #ifdef ORIENT
339 ORIENT;
340 #endif
342 ARGCHECK (s, format);
344 /* Figure out the decimal point character. */
345 #ifdef COMPILE_WSCANF
346 decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
347 #else
348 decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
349 #endif
350 /* Figure out the thousands separator character. */
351 #ifdef COMPILE_WSCANF
352 thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC);
353 #else
354 thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
355 if (*thousands == '\0')
356 thousands = NULL;
357 #endif
359 /* Lock the stream. */
360 LOCK_STREAM (s);
363 #ifndef COMPILE_WSCANF
364 /* From now on we use `state' to convert the format string. */
365 memset (&state, '\0', sizeof (state));
366 #endif
368 /* Run through the format string. */
369 while (*f != '\0')
371 unsigned int argpos;
372 /* Extract the next argument, which is of type TYPE.
373 For a %N$... spec, this is the Nth argument from the beginning;
374 otherwise it is the next argument after the state now in ARG. */
375 #ifdef __va_copy
376 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
377 ({ unsigned int pos = argpos; \
378 va_list arg; \
379 __va_copy (arg, argptr); \
380 while (--pos > 0) \
381 (void) va_arg (arg, void *); \
382 va_arg (arg, type); \
384 #else
385 # if 0
386 /* XXX Possible optimization. */
387 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
388 ({ va_list arg = (va_list) argptr; \
389 arg = (va_list) ((char *) arg \
390 + (argpos - 1) \
391 * __va_rounded_size (void *)); \
392 va_arg (arg, type); \
394 # else
395 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
396 ({ unsigned int pos = argpos; \
397 va_list arg = (va_list) argptr; \
398 while (--pos > 0) \
399 (void) va_arg (arg, void *); \
400 va_arg (arg, type); \
402 # endif
403 #endif
405 #ifndef COMPILE_WSCANF
406 if (!isascii (*f))
408 /* Non-ASCII, may be a multibyte. */
409 int len = __mbrlen (f, strlen (f), &state);
410 if (len > 0)
414 c = inchar ();
415 if (c == EOF)
416 input_error ();
417 else if (c != *f++)
419 ungetc (c, s);
420 conv_error ();
423 while (--len > 0);
424 continue;
427 #endif
429 fc = *f++;
430 if (fc != '%')
432 /* Remember to skip spaces. */
433 if (ISSPACE (fc))
435 skip_space = 1;
436 continue;
439 /* Read a character. */
440 c = inchar ();
442 /* Characters other than format specs must just match. */
443 if (c == EOF)
444 input_error ();
446 /* We saw white space char as the last character in the format
447 string. Now it's time to skip all leading white space. */
448 if (skip_space)
450 while (ISSPACE (c))
451 if (inchar () == EOF && errno == EINTR)
452 conv_error ();
453 skip_space = 0;
456 if (c != fc)
458 ungetc (c, s);
459 conv_error ();
462 continue;
465 /* This is the start of the conversion string. */
466 flags = 0;
468 /* Not yet decided whether we read a pointer or not. */
469 read_pointer = 0;
471 /* Initialize state of modifiers. */
472 argpos = 0;
474 /* Prepare temporary buffer. */
475 wpsize = 0;
477 /* Check for a positional parameter specification. */
478 if (ISDIGIT (*f))
480 argpos = *f++ - L_('0');
481 while (ISDIGIT (*f))
482 argpos = argpos * 10 + (*f++ - L_('0'));
483 if (*f == L_('$'))
484 ++f;
485 else
487 /* Oops; that was actually the field width. */
488 width = argpos;
489 flags |= WIDTH;
490 argpos = 0;
491 goto got_width;
495 /* Check for the assignment-suppressing, the number grouping flag,
496 and the signal to use the locale's digit representation. */
497 while (*f == L_('*') || *f == L_('\'') || *f == L_('I'))
498 switch (*f++)
500 case L_('*'):
501 flags |= SUPPRESS;
502 break;
503 case L_('\''):
504 flags |= GROUP;
505 break;
506 case L_('I'):
507 flags |= I18N;
508 break;
511 /* We have seen width. */
512 if (ISDIGIT (*f))
513 flags |= WIDTH;
515 /* Find the maximum field width. */
516 width = 0;
517 while (ISDIGIT (*f))
519 width *= 10;
520 width += *f++ - L_('0');
522 got_width:
523 if (width == 0)
524 width = -1;
526 /* Check for type modifiers. */
527 switch (*f++)
529 case L_('h'):
530 /* ints are short ints or chars. */
531 if (*f == L_('h'))
533 ++f;
534 flags |= CHAR;
536 else
537 flags |= SHORT;
538 break;
539 case L_('l'):
540 if (*f == L_('l'))
542 /* A double `l' is equivalent to an `L'. */
543 ++f;
544 flags |= LONGDBL | LONG;
546 else
547 /* ints are long ints. */
548 flags |= LONG;
549 break;
550 case L_('q'):
551 case L_('L'):
552 /* doubles are long doubles, and ints are long long ints. */
553 flags |= LONGDBL | LONG;
554 break;
555 case L_('a'):
556 /* The `a' is used as a flag only if followed by `s', `S' or
557 `['. */
558 if (*f != L_('s') && *f != L_('S') && *f != L_('['))
560 --f;
561 break;
563 /* String conversions (%s, %[) take a `char **'
564 arg and fill it in with a malloc'd pointer. */
565 flags |= MALLOC;
566 break;
567 case L_('z'):
568 if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
569 flags |= LONGDBL;
570 else if (sizeof (size_t) > sizeof (unsigned int))
571 flags |= LONG;
572 break;
573 case L_('j'):
574 if (need_longlong && sizeof (uintmax_t) > sizeof (unsigned long int))
575 flags |= LONGDBL;
576 else if (sizeof (uintmax_t) > sizeof (unsigned int))
577 flags |= LONG;
578 break;
579 case L_('t'):
580 if (need_longlong && sizeof (ptrdiff_t) > sizeof (long int))
581 flags |= LONGDBL;
582 else if (sizeof (ptrdiff_t) > sizeof (int))
583 flags |= LONG;
584 break;
585 default:
586 /* Not a recognized modifier. Backup. */
587 --f;
588 break;
591 /* End of the format string? */
592 if (*f == L_('\0'))
593 conv_error ();
595 /* Find the conversion specifier. */
596 fc = *f++;
597 if (skip_space || (fc != L_('[') && fc != L_('c')
598 && fc != L_('C') && fc != L_('n')))
600 /* Eat whitespace. */
601 int save_errno = errno;
602 errno = 0;
604 if (inchar () == EOF && errno == EINTR)
605 input_error ();
606 while (ISSPACE (c));
607 errno = save_errno;
608 ungetc (c, s);
609 skip_space = 0;
612 switch (fc)
614 case L_('%'): /* Must match a literal '%'. */
615 c = inchar ();
616 if (c == EOF)
617 input_error ();
618 if (c != fc)
620 ungetc (c, s);
621 conv_error ();
623 break;
625 case L_('n'): /* Answer number of assignments done. */
626 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
627 with the 'n' conversion specifier. */
628 if (!(flags & SUPPRESS))
630 /* Don't count the read-ahead. */
631 if (need_longlong && (flags & LONGDBL))
632 *ARG (long long int *) = read_in;
633 else if (need_long && (flags & LONG))
634 *ARG (long int *) = read_in;
635 else if (flags & SHORT)
636 *ARG (short int *) = read_in;
637 else if (!(flags & CHAR))
638 *ARG (int *) = read_in;
639 else
640 *ARG (char *) = read_in;
642 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
643 /* We have a severe problem here. The ISO C standard
644 contradicts itself in explaining the effect of the %n
645 format in `scanf'. While in ISO C:1990 and the ISO C
646 Amendement 1:1995 the result is described as
648 Execution of a %n directive does not effect the
649 assignment count returned at the completion of
650 execution of the f(w)scanf function.
652 in ISO C Corrigendum 1:1994 the following was added:
654 Subclause 7.9.6.2
655 Add the following fourth example:
657 #include <stdio.h>
658 int d1, d2, n1, n2, i;
659 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
660 the value 123 is assigned to d1 and the value3 to n1.
661 Because %n can never get an input failure the value
662 of 3 is also assigned to n2. The value of d2 is not
663 affected. The value 3 is assigned to i.
665 We go for now with the historically correct code from ISO C,
666 i.e., we don't count the %n assignments. When it ever
667 should proof to be wrong just remove the #ifdef above. */
668 ++done;
669 #endif
671 break;
673 case L_('c'): /* Match characters. */
674 if ((flags & LONG) == 0)
676 if (!(flags & SUPPRESS))
678 str = ARG (char *);
679 if (str == NULL)
680 conv_error ();
683 c = inchar ();
684 if (c == EOF)
685 input_error ();
687 if (width == -1)
688 width = 1;
690 #ifdef COMPILE_WSCANF
691 /* We have to convert the wide character(s) into multibyte
692 characters and store the result. */
693 memset (&state, '\0', sizeof (state));
697 size_t n;
699 n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
700 if (n == (size_t) -1)
701 /* No valid wide character. */
702 input_error ();
704 /* Increment the output pointer. Even if we don't
705 write anything. */
706 str += n;
708 while (--width > 0 && inchar () != EOF);
709 #else
710 if (!(flags & SUPPRESS))
713 *str++ = c;
714 while (--width > 0 && inchar () != EOF);
716 else
717 while (--width > 0 && inchar () != EOF);
718 #endif
720 if (!(flags & SUPPRESS))
721 ++done;
723 break;
725 /* FALLTHROUGH */
726 case L_('C'):
727 if (!(flags & SUPPRESS))
729 wstr = ARG (wchar_t *);
730 if (wstr == NULL)
731 conv_error ();
734 c = inchar ();
735 if (c == EOF)
736 input_error ();
738 #ifdef COMPILE_WSCANF
739 /* Just store the incoming wide characters. */
740 if (!(flags & SUPPRESS))
743 *wstr++ = c;
744 while (--width > 0 && inchar () != EOF);
746 else
747 while (--width > 0 && inchar () != EOF);
748 #else
750 /* We have to convert the multibyte input sequence to wide
751 characters. */
752 char buf[MB_LEN_MAX];
753 mbstate_t cstate;
755 memset (&cstate, '\0', sizeof (cstate));
759 size_t cnt;
761 /* This is what we present the mbrtowc function first. */
762 buf[0] = c;
763 cnt = 1;
765 while (1)
767 size_t n;
769 n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
770 buf, cnt, &cstate);
772 if (n == (size_t) -2)
774 /* Possibly correct character, just not enough
775 input. */
776 assert (cnt < MB_CUR_MAX);
778 if (inchar () == EOF)
779 encode_error ();
781 buf[cnt++] = c;
782 continue;
785 if (n != cnt)
786 encode_error ();
788 /* We have a match. */
789 break;
792 /* Advance the result pointer. */
793 ++wstr;
795 while (--width > 0 && inchar () != EOF);
797 #endif
799 if (!(flags & SUPPRESS))
800 ++done;
802 break;
804 case L_('s'): /* Read a string. */
805 if (!(flags & LONG))
807 #define STRING_ARG(Str, Type) \
808 do if (!(flags & SUPPRESS)) \
810 if (flags & MALLOC) \
812 /* The string is to be stored in a malloc'd buffer. */ \
813 strptr = ARG (char **); \
814 if (strptr == NULL) \
815 conv_error (); \
816 /* Allocate an initial buffer. */ \
817 strsize = 100; \
818 *strptr = (char *) malloc (strsize * sizeof (Type)); \
819 Str = (Type *) *strptr; \
821 else \
822 Str = ARG (Type *); \
823 if (Str == NULL) \
824 conv_error (); \
825 } while (0)
826 STRING_ARG (str, char);
828 c = inchar ();
829 if (c == EOF)
830 input_error ();
832 #ifdef COMPILE_WSCANF
833 memset (&state, '\0', sizeof (state));
834 #endif
838 if (ISSPACE (c))
840 ungetc (c, s);
841 break;
844 #ifdef COMPILE_WSCANF
845 /* This is quite complicated. We have to convert the
846 wide characters into multibyte characters and then
847 store them. */
849 size_t n;
851 if (!(flags & SUPPRESS) && (flags & MALLOC)
852 && str + MB_CUR_MAX >= *strptr + strsize)
854 /* We have to enlarge the buffer if the `a' flag
855 was given. */
856 str = (char *) realloc (*strptr, strsize * 2);
857 if (str == NULL)
859 /* Can't allocate that much. Last-ditch
860 effort. */
861 str = (char *) realloc (*strptr, strsize + 1);
862 if (str == NULL)
864 /* We lose. Oh well. Terminate the
865 string and stop converting,
866 so at least we don't skip any input. */
867 ((char *) (*strptr))[strsize - 1] = '\0';
868 ++done;
869 conv_error ();
871 else
873 *strptr = (char *) str;
874 str += strsize;
875 ++strsize;
878 else
880 *strptr = (char *) str;
881 str += strsize;
882 strsize *= 2;
886 n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
887 if (n == (size_t) -1)
888 encode_error ();
890 assert (n <= MB_CUR_MAX);
891 str += n;
893 #else
894 /* This is easy. */
895 if (!(flags & SUPPRESS))
897 *str++ = c;
898 if ((flags & MALLOC)
899 && (char *) str == *strptr + strsize)
901 /* Enlarge the buffer. */
902 str = (char *) realloc (*strptr, 2 * strsize);
903 if (str == NULL)
905 /* Can't allocate that much. Last-ditch
906 effort. */
907 str = (char *) realloc (*strptr, strsize + 1);
908 if (str == NULL)
910 /* We lose. Oh well. Terminate the
911 string and stop converting,
912 so at least we don't skip any input. */
913 ((char *) (*strptr))[strsize - 1] = '\0';
914 ++done;
915 conv_error ();
917 else
919 *strptr = (char *) str;
920 str += strsize;
921 ++strsize;
924 else
926 *strptr = (char *) str;
927 str += strsize;
928 strsize *= 2;
932 #endif
934 while ((width <= 0 || --width > 0) && inchar () != EOF);
936 if (!(flags & SUPPRESS))
938 #ifdef COMPILE_WSCANF
939 /* We have to emit the code to get into the intial
940 state. */
941 char buf[MB_LEN_MAX];
942 size_t n = wcrtomb (buf, L'\0', &state);
943 if (n > 0 && (flags & MALLOC)
944 && str + n >= *strptr + strsize)
946 /* Enlarge the buffer. */
947 str = (char *) realloc (*strptr,
948 (str + n + 1) - *strptr);
949 if (str == NULL)
951 /* We lose. Oh well. Terminate the string
952 and stop converting, so at least we don't
953 skip any input. */
954 ((char *) (*strptr))[strsize - 1] = '\0';
955 ++done;
956 conv_error ();
958 else
960 *strptr = (char *) str;
961 str = ((char *) *strptr) + strsize;
962 strsize = (str + n + 1) - *strptr;
966 str = __mempcpy (str, buf, n);
967 #endif
968 *str = '\0';
970 if ((flags & MALLOC) && str - *strptr != strsize)
972 char *cp = (char *) realloc (*strptr, str - *strptr);
973 if (cp != NULL)
974 *strptr = cp;
977 ++done;
979 break;
981 /* FALLTHROUGH */
983 case L_('S'):
985 #ifndef COMPILE_WSCANF
986 mbstate_t cstate;
987 #endif
989 /* Wide character string. */
990 STRING_ARG (wstr, wchar_t);
992 c = inchar ();
993 if (c == EOF)
994 input_error ();
996 #ifndef COMPILE_WSCANF
997 memset (&cstate, '\0', sizeof (cstate));
998 #endif
1002 if (ISSPACE (c))
1004 ungetc (c, s);
1005 break;
1008 #ifdef COMPILE_WSCANF
1009 /* This is easy. */
1010 if (!(flags & SUPPRESS))
1012 *wstr++ = c;
1013 if ((flags & MALLOC)
1014 && wstr == (wchar_t *) *strptr + strsize)
1016 /* Enlarge the buffer. */
1017 wstr = (wchar_t *) realloc (*strptr,
1018 (2 * strsize)
1019 * sizeof (wchar_t));
1020 if (wstr == NULL)
1022 /* Can't allocate that much. Last-ditch
1023 effort. */
1024 wstr = (wchar_t *) realloc (*strptr,
1025 (strsize
1026 + sizeof (wchar_t)));
1027 if (wstr == NULL)
1029 /* We lose. Oh well. Terminate the string
1030 and stop converting, so at least we don't
1031 skip any input. */
1032 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1033 ++done;
1034 conv_error ();
1036 else
1038 *strptr = (char *) wstr;
1039 wstr += strsize;
1040 ++strsize;
1043 else
1045 *strptr = (char *) wstr;
1046 wstr += strsize;
1047 strsize *= 2;
1051 #else
1053 char buf[MB_LEN_MAX];
1054 size_t cnt;
1056 buf[0] = c;
1057 cnt = 1;
1059 while (1)
1061 size_t n;
1063 n = __mbrtowc (!(flags & SUPPRESS) ? wstr : NULL,
1064 buf, cnt, &cstate);
1066 if (n == (size_t) -2)
1068 /* Possibly correct character, just not enough
1069 input. */
1070 assert (cnt < MB_CUR_MAX);
1072 if (inchar () == EOF)
1073 encode_error ();
1075 buf[cnt++] = c;
1076 continue;
1079 if (n != cnt)
1080 encode_error ();
1082 /* We have a match. */
1083 break;
1086 if (!(flags & SUPPRESS) && (flags & MALLOC)
1087 && wstr == (wchar_t *) *strptr + strsize)
1089 /* Enlarge the buffer. */
1090 wstr = (wchar_t *) realloc (*strptr,
1091 (2 * strsize
1092 * sizeof (wchar_t)));
1093 if (wstr == NULL)
1095 /* Can't allocate that much. Last-ditch effort. */
1096 wstr = (wchar_t *) realloc (*strptr,
1097 ((strsize + 1)
1098 * sizeof (wchar_t)));
1099 if (wstr == NULL)
1101 /* We lose. Oh well. Terminate the
1102 string and stop converting, so at
1103 least we don't skip any input. */
1104 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
1105 ++done;
1106 conv_error ();
1108 else
1110 *strptr = (char *) wstr;
1111 wstr += strsize;
1112 ++strsize;
1115 else
1117 *strptr = (char *) wstr;
1118 wstr += strsize;
1119 strsize *= 2;
1123 #endif
1125 while ((width <= 0 || --width > 0) && inchar () != EOF);
1127 if (!(flags & SUPPRESS))
1129 *wstr++ = L'\0';
1131 if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
1133 wchar_t *cp = (wchar_t *) realloc (*strptr,
1134 ((wstr
1135 - (wchar_t *) *strptr)
1136 * sizeof(wchar_t)));
1137 if (cp != NULL)
1138 *strptr = (char *) cp;
1141 ++done;
1144 break;
1146 case L_('x'): /* Hexadecimal integer. */
1147 case L_('X'): /* Ditto. */
1148 base = 16;
1149 number_signed = 0;
1150 goto number;
1152 case L_('o'): /* Octal integer. */
1153 base = 8;
1154 number_signed = 0;
1155 goto number;
1157 case L_('u'): /* Unsigned decimal integer. */
1158 base = 10;
1159 number_signed = 0;
1160 goto number;
1162 case L_('d'): /* Signed decimal integer. */
1163 base = 10;
1164 number_signed = 1;
1165 goto number;
1167 case L_('i'): /* Generic number. */
1168 base = 0;
1169 number_signed = 1;
1171 number:
1172 c = inchar ();
1173 if (c == EOF)
1174 input_error ();
1176 /* Check for a sign. */
1177 if (c == L_('-') || c == L_('+'))
1179 ADDW (c);
1180 if (width > 0)
1181 --width;
1182 c = inchar ();
1185 /* Look for a leading indication of base. */
1186 if (width != 0 && c == L_('0'))
1188 if (width > 0)
1189 --width;
1191 ADDW (c);
1192 c = inchar ();
1194 if (width != 0 && TOLOWER (c) == L_('x'))
1196 if (base == 0)
1197 base = 16;
1198 if (base == 16)
1200 if (width > 0)
1201 --width;
1202 c = inchar ();
1205 else if (base == 0)
1206 base = 8;
1209 if (base == 0)
1210 base = 10;
1212 if (base == 10 && (flags & I18N) != 0)
1214 int from_level;
1215 int to_level;
1216 int level;
1217 #ifdef COMPILE_WSCANF
1218 const wchar_t *wcdigits[10];
1219 #else
1220 const char *mbdigits[10];
1221 #endif
1222 int n;
1224 from_level = 0;
1225 #ifdef COMPILE_WSCANF
1226 to_level = _NL_CURRENT_WORD (LC_CTYPE,
1227 _NL_CTYPE_INDIGITS_WC_LEN) - 1;
1228 #else
1229 to_level = _NL_CURRENT_WORD (LC_CTYPE,
1230 _NL_CTYPE_INDIGITS_MB_LEN) - 1;
1231 #endif
1233 /* Read the number into workspace. */
1234 while (c != EOF && width != 0)
1236 /* In this round we get the pointer to the digit strings
1237 and also perform the first round of comparisons. */
1238 for (n = 0; n < 10; ++n)
1240 /* Get the string for the digits with value N. */
1241 #ifdef COMPILE_WSCANF
1242 wcdigits[n] = (const wchar_t *)
1243 _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
1244 wcdigits[n] += from_level;
1246 if (c == *wcdigits[n])
1248 to_level = from_level;
1249 break;
1252 /* Advance the pointer to the next string. */
1253 ++wcdigits[n];
1254 #else
1255 const char *cmpp;
1256 int avail = width > 0 ? width : INT_MAX;
1258 mbdigits[n] = _NL_CURRENT (LC_CTYPE,
1259 _NL_CTYPE_INDIGITS0_MB + n);
1261 for (level = 0; level < from_level; level++)
1262 mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1264 cmpp = mbdigits[n];
1265 while (*cmpp == c && avail > 0)
1267 if (*++cmpp == '\0')
1268 break;
1269 else
1271 if ((c = inchar ()) == EOF)
1272 break;
1273 --avail;
1277 if (*cmpp == '\0')
1279 if (width > 0)
1280 width = avail;
1281 to_level = from_level;
1282 break;
1285 /* We are pushing all read characters back. */
1286 if (cmpp > mbdigits[n])
1288 ungetc (c, s);
1289 while (--cmpp > mbdigits[n])
1290 ungetc (*cmpp, s);
1291 c = *cmpp;
1294 /* Advance the pointer to the next string. */
1295 mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1296 #endif
1299 if (n == 10)
1301 /* Have not yet found the digit. */
1302 for (level = from_level + 1; level <= to_level; ++level)
1304 /* Search all ten digits of this level. */
1305 for (n = 0; n < 10; ++n)
1307 #ifdef COMPILE_WSCANF
1308 if (c == *wcdigits[n])
1309 break;
1311 /* Advance the pointer to the next string. */
1312 ++wcdigits[n];
1313 #else
1314 const char *cmpp;
1315 int avail = width > 0 ? width : INT_MAX;
1317 cmpp = mbdigits[n];
1318 while (*cmpp == c && avail > 0)
1320 if (*++cmpp == '\0')
1321 break;
1322 else
1324 if ((c = inchar ()) == EOF)
1325 break;
1326 --avail;
1330 if (*cmpp == '\0')
1332 if (width > 0)
1333 width = avail;
1334 break;
1337 /* We are pushing all read characters back. */
1338 if (cmpp > mbdigits[n])
1340 ungetc (c, s);
1341 while (--cmpp > mbdigits[n])
1342 ungetc (*cmpp, s);
1343 c = *cmpp;
1346 /* Advance the pointer to the next string. */
1347 mbdigits[n] = strchr (mbdigits[n], '\0') + 1;
1348 #endif
1351 if (n < 10)
1353 /* Found it. */
1354 from_level = level;
1355 to_level = level;
1356 break;
1361 if (n < 10)
1362 c = L_('0') + n;
1363 else if ((flags & GROUP)
1364 #ifdef COMPILE_WSCANF
1365 && thousands != L'\0'
1366 #else
1367 && thousands != NULL
1368 #endif
1371 /* Try matching against the thousands separator. */
1372 #ifdef COMPILE_WSCANF
1373 if (c != thousands)
1374 break;
1375 #else
1376 const char *cmpp = thousands;
1377 int avail = width > 0 ? width : INT_MAX;
1379 while (*cmpp == c && avail > 0)
1381 ADDW (c);
1382 if (*++cmpp == '\0')
1383 break;
1384 else
1386 if ((c = inchar ()) == EOF)
1387 break;
1388 --avail;
1392 if (*cmpp != '\0')
1394 /* We are pushing all read characters back. */
1395 if (cmpp > thousands)
1397 wpsize -= cmpp - thousands;
1398 ungetc (c, s);
1399 while (--cmpp > thousands)
1400 ungetc (*cmpp, s);
1401 c = *cmpp;
1403 break;
1406 if (width > 0)
1407 width = avail;
1409 /* The last thousands character will be added back by
1410 the ADDW below. */
1411 --wpsize;
1412 #endif
1414 else
1415 break;
1417 ADDW (c);
1418 if (width > 0)
1419 --width;
1421 c = inchar ();
1424 else
1425 /* Read the number into workspace. */
1426 while (c != EOF && width != 0)
1428 if (base == 16)
1430 if (!ISXDIGIT (c))
1431 break;
1433 else if (!ISDIGIT (c) || c - L_('0') >= base)
1435 if (base == 10 && (flags & GROUP)
1436 #ifdef COMPILE_WSCANF
1437 && thousands != L'\0'
1438 #else
1439 && thousands != NULL
1440 #endif
1443 /* Try matching against the thousands separator. */
1444 #ifdef COMPILE_WSCANF
1445 if (c != thousands)
1446 break;
1447 #else
1448 const char *cmpp = thousands;
1449 int avail = width > 0 ? width : INT_MAX;
1451 while (*cmpp == c && avail > 0)
1453 ADDW (c);
1454 if (*++cmpp == '\0')
1455 break;
1456 else
1458 if ((c = inchar ()) == EOF)
1459 break;
1460 --avail;
1464 if (*cmpp != '\0')
1466 /* We are pushing all read characters back. */
1467 if (cmpp > thousands)
1469 wpsize -= cmpp - thousands;
1470 ungetc (c, s);
1471 while (--cmpp > thousands)
1472 ungetc (*cmpp, s);
1473 c = *cmpp;
1475 break;
1478 if (width > 0)
1479 width = avail;
1481 /* The last thousands character will be added back by
1482 the ADDW below. */
1483 --wpsize;
1484 #endif
1486 else
1487 break;
1489 ADDW (c);
1490 if (width > 0)
1491 --width;
1493 c = inchar ();
1496 if (wpsize == 0
1497 || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-'))))
1499 /* There was no number. If we are supposed to read a pointer
1500 we must recognize "(nil)" as well. */
1501 if (wpsize == 0 && read_pointer && (width < 0 || width >= 0)
1502 && c == '('
1503 && TOLOWER (inchar ()) == L_('n')
1504 && TOLOWER (inchar ()) == L_('i')
1505 && TOLOWER (inchar ()) == L_('l')
1506 && inchar () == L_(')'))
1507 /* We must produce the value of a NULL pointer. A single
1508 '0' digit is enough. */
1509 ADDW (L_('0'));
1510 else
1512 /* The last read character is not part of the number
1513 anymore. */
1514 ungetc (c, s);
1516 conv_error ();
1519 else
1520 /* The just read character is not part of the number anymore. */
1521 ungetc (c, s);
1523 /* Convert the number. */
1524 ADDW (L_('\0'));
1525 if (need_longlong && (flags & LONGDBL))
1527 if (number_signed)
1528 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
1529 else
1530 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
1532 else
1534 if (number_signed)
1535 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
1536 else
1537 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
1539 if (wp == tw)
1540 conv_error ();
1542 if (!(flags & SUPPRESS))
1544 if (! number_signed)
1546 if (need_longlong && (flags & LONGDBL))
1547 *ARG (unsigned LONGLONG int *) = num.uq;
1548 else if (need_long && (flags & LONG))
1549 *ARG (unsigned long int *) = num.ul;
1550 else if (flags & SHORT)
1551 *ARG (unsigned short int *)
1552 = (unsigned short int) num.ul;
1553 else if (!(flags & CHAR))
1554 *ARG (unsigned int *) = (unsigned int) num.ul;
1555 else
1556 *ARG (unsigned char *) = (unsigned char) num.ul;
1558 else
1560 if (need_longlong && (flags & LONGDBL))
1561 *ARG (LONGLONG int *) = num.q;
1562 else if (need_long && (flags & LONG))
1563 *ARG (long int *) = num.l;
1564 else if (flags & SHORT)
1565 *ARG (short int *) = (short int) num.l;
1566 else if (!(flags & CHAR))
1567 *ARG (int *) = (int) num.l;
1568 else
1569 *ARG (signed char *) = (signed char) num.ul;
1571 ++done;
1573 break;
1575 case L_('e'): /* Floating-point numbers. */
1576 case L_('E'):
1577 case L_('f'):
1578 case L_('g'):
1579 case L_('G'):
1580 case L_('a'):
1581 case L_('A'):
1582 c = inchar ();
1583 if (c == EOF)
1584 input_error ();
1586 /* Check for a sign. */
1587 if (c == L_('-') || c == L_('+'))
1589 negative = c == L_('-');
1590 if (width == 0 || inchar () == EOF)
1591 /* EOF is only an input error before we read any chars. */
1592 conv_error ();
1593 if (! ISDIGIT (c))
1595 #ifdef COMPILE_WSCANF
1596 if (c != decimal)
1598 /* This is no valid number. */
1599 ungetc (c, s);
1600 conv_error ();
1602 #else
1603 /* Match against the decimal point. At this point
1604 we are taking advantage of the fact that we can
1605 push more than one character back. This is
1606 (almost) never necessary since the decimal point
1607 string hopefully never contains more than one
1608 byte. */
1609 const char *cmpp = decimal;
1610 int avail = width > 0 ? width : INT_MAX;
1612 while (*cmpp == c && avail > 0)
1613 if (*++cmpp == '\0')
1614 break;
1615 else
1617 if (inchar () == EOF)
1618 break;
1619 --avail;
1622 if (*cmpp != '\0')
1624 /* This is no valid number. */
1625 while (1)
1627 ungetc (c, s);
1628 if (cmpp == decimal)
1629 break;
1630 c = *--cmpp;
1633 conv_error ();
1635 if (width > 0)
1636 width = avail;
1637 #endif
1639 if (width > 0)
1640 --width;
1642 else
1643 negative = 0;
1645 /* Take care for the special arguments "nan" and "inf". */
1646 if (TOLOWER (c) == L_('n'))
1648 /* Maybe "nan". */
1649 ADDW (c);
1650 if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('a'))
1651 input_error ();
1652 if (width > 0)
1653 --width;
1654 ADDW (c);
1655 if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1656 input_error ();
1657 if (width > 0)
1658 --width;
1659 ADDW (c);
1660 /* It is "nan". */
1661 goto scan_float;
1663 else if (TOLOWER (c) == L_('i'))
1665 /* Maybe "inf" or "infinity". */
1666 ADDW (c);
1667 if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('n'))
1668 input_error ();
1669 if (width > 0)
1670 --width;
1671 ADDW (c);
1672 if (width == 0 || inchar () == EOF || TOLOWER (c) != L_('f'))
1673 input_error ();
1674 if (width > 0)
1675 --width;
1676 ADDW (c);
1677 /* It is as least "inf". */
1678 if (width != 0 && inchar () != EOF)
1680 if (TOLOWER (c) == L_('i'))
1682 if (width > 0)
1683 --width;
1684 /* Now we have to read the rest as well. */
1685 ADDW (c);
1686 if (width == 0 || inchar () == EOF
1687 || TOLOWER (c) != L_('n'))
1688 input_error ();
1689 if (width > 0)
1690 --width;
1691 ADDW (c);
1692 if (width == 0 || inchar () == EOF
1693 || TOLOWER (c) != L_('i'))
1694 input_error ();
1695 if (width > 0)
1696 --width;
1697 ADDW (c);
1698 if (width == 0 || inchar () == EOF
1699 || TOLOWER (c) != L_('t'))
1700 input_error ();
1701 if (width > 0)
1702 --width;
1703 ADDW (c);
1704 if (width == 0 || inchar () == EOF
1705 || TOLOWER (c) != L_('y'))
1706 input_error ();
1707 if (width > 0)
1708 --width;
1709 ADDW (c);
1711 else
1712 /* Never mind. */
1713 ungetc (c, s);
1715 goto scan_float;
1718 is_hexa = 0;
1719 exp_char = L_('e');
1720 if (width != 0 && c == L_('0'))
1722 ADDW (c);
1723 c = inchar ();
1724 if (width > 0)
1725 --width;
1726 if (width != 0 && TOLOWER (c) == L_('x'))
1728 /* It is a number in hexadecimal format. */
1729 ADDW (c);
1731 is_hexa = 1;
1732 exp_char = L_('p');
1734 /* Grouping is not allowed. */
1735 flags &= ~GROUP;
1736 c = inchar ();
1737 if (width > 0)
1738 --width;
1742 got_dot = got_e = 0;
1745 if (ISDIGIT (c))
1746 ADDW (c);
1747 else if (!got_e && is_hexa && ISXDIGIT (c))
1748 ADDW (c);
1749 else if (got_e && wp[wpsize - 1] == exp_char
1750 && (c == L_('-') || c == L_('+')))
1751 ADDW (c);
1752 else if (wpsize > 0 && !got_e && TOLOWER (c) == exp_char)
1754 ADDW (exp_char);
1755 got_e = got_dot = 1;
1757 else
1759 #ifdef COMPILE_WSCANF
1760 if (! got_dot && c == decimal)
1762 ADDW (c);
1763 got_dot = 1;
1765 else if (thousands != L'\0' && ! got_dot && c == thousands)
1766 ADDW (c);
1767 else
1769 /* The last read character is not part of the number
1770 anymore. */
1771 ungetc (c, s);
1772 break;
1774 #else
1775 const char *cmpp = decimal;
1776 int avail = width > 0 ? width : INT_MAX;
1778 if (! got_dot)
1780 while (*cmpp == c && avail > 0)
1781 if (*++cmpp == '\0')
1782 break;
1783 else
1785 if (inchar () == EOF)
1786 break;
1787 --avail;
1791 if (*cmpp == '\0')
1793 /* Add all the characters. */
1794 for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
1795 ADDW (*cmpp);
1796 if (width > 0)
1797 width = avail;
1798 got_dot = 1;
1800 else
1802 /* Figure out whether it is a thousands separator.
1803 There is one problem: we possibly read more than
1804 one character. We cannot push them back but since
1805 we know that parts of the `decimal' string matched,
1806 we can compare against it. */
1807 const char *cmp2p = thousands;
1809 if (thousands != NULL && ! got_dot)
1811 while (cmp2p < cmpp
1812 && *cmp2p == decimal[cmp2p - thousands])
1813 ++cmp2p;
1814 if (cmp2p == cmpp)
1816 while (*cmp2p == c && avail > 0)
1817 if (*++cmp2p == '\0')
1818 break;
1819 else
1821 if (inchar () == EOF)
1822 break;
1823 --avail;
1828 if (cmp2p != NULL && *cmp2p == '\0')
1830 /* Add all the characters. */
1831 for (cmpp = thousands; *cmpp != '\0'; ++cmpp)
1832 ADDW (*cmpp);
1833 if (width > 0)
1834 width = avail;
1836 else
1838 /* The last read character is not part of the number
1839 anymore. */
1840 ungetc (c, s);
1841 break;
1844 #endif
1846 if (width > 0)
1847 --width;
1849 while (width != 0 && inchar () != EOF);
1851 /* Have we read any character? If we try to read a number
1852 in hexadecimal notation and we have read only the `0x'
1853 prefix or no exponent this is an error. */
1854 if (wpsize == 0 || (is_hexa && (wpsize == 2 || ! got_e)))
1855 conv_error ();
1857 scan_float:
1858 /* Convert the number. */
1859 ADDW (L_('\0'));
1860 if (flags & LONGDBL)
1862 long double d = __strtold_internal (wp, &tw, flags & GROUP);
1863 if (!(flags & SUPPRESS) && tw != wp)
1864 *ARG (long double *) = negative ? -d : d;
1866 else if (flags & LONG)
1868 double d = __strtod_internal (wp, &tw, flags & GROUP);
1869 if (!(flags & SUPPRESS) && tw != wp)
1870 *ARG (double *) = negative ? -d : d;
1872 else
1874 float d = __strtof_internal (wp, &tw, flags & GROUP);
1875 if (!(flags & SUPPRESS) && tw != wp)
1876 *ARG (float *) = negative ? -d : d;
1879 if (tw == wp)
1880 conv_error ();
1882 if (!(flags & SUPPRESS))
1883 ++done;
1884 break;
1886 case L_('['): /* Character class. */
1887 if (flags & LONG)
1888 STRING_ARG (wstr, wchar_t);
1889 else
1890 STRING_ARG (str, char);
1892 if (*f == L_('^'))
1894 ++f;
1895 not_in = 1;
1897 else
1898 not_in = 0;
1900 if (width < 0)
1901 /* There is no width given so there is also no limit on the
1902 number of characters we read. Therefore we set width to
1903 a very high value to make the algorithm easier. */
1904 width = INT_MAX;
1906 #ifdef COMPILE_WSCANF
1907 /* Find the beginning and the end of the scanlist. We are not
1908 creating a lookup table since it would have to be too large.
1909 Instead we search each time through the string. This is not
1910 a constant lookup time but who uses this feature deserves to
1911 be punished. */
1912 tw = (wchar_t *) f; /* Marks the beginning. */
1914 if (*f == ']' || *f == '-')
1915 ++f;
1917 while ((fc = *f++) != L'\0' && fc != L']');
1919 if (fc == L'\0')
1920 conv_error ();
1921 wp = (wchar_t *) f - 1;
1922 #else
1923 /* Fill WP with byte flags indexed by character.
1924 We will use this flag map for matching input characters. */
1925 if (wpmax < UCHAR_MAX)
1927 wpmax = UCHAR_MAX;
1928 wp = (char *) alloca (wpmax);
1930 memset (wp, '\0', UCHAR_MAX);
1932 fc = *f;
1933 if (fc == ']' || fc == '-')
1935 /* If ] or - appears before any char in the set, it is not
1936 the terminator or separator, but the first char in the
1937 set. */
1938 wp[fc] = 1;
1939 ++f;
1942 while ((fc = *f++) != '\0' && fc != ']')
1943 if (fc == '-' && *f != '\0' && *f != ']'
1944 && (unsigned char) f[-2] <= (unsigned char) *f)
1946 /* Add all characters from the one before the '-'
1947 up to (but not including) the next format char. */
1948 for (fc = f[-2]; fc < *f; ++fc)
1949 wp[fc] = 1;
1951 else
1952 /* Add the character to the flag map. */
1953 wp[fc] = 1;
1955 if (fc == '\0')
1956 conv_error();
1957 #endif
1959 if (flags & LONG)
1961 size_t now = read_in;
1962 #ifdef COMPILE_WSCANF
1965 wchar_t *runp;
1967 if (inchar () == WEOF)
1968 break;
1970 /* Test whether it's in the scanlist. */
1971 runp = tw;
1972 while (runp < wp)
1974 if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
1975 && runp != tw
1976 && (unsigned int) runp[-1] <= (unsigned int) runp[1])
1978 /* Match against all characters in between the
1979 first and last character of the sequence. */
1980 wchar_t wc;
1982 for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
1983 if (wc == c)
1984 break;
1986 if (wc == runp[1] && !not_in)
1987 break;
1988 if (wc == runp[1] && not_in)
1990 /* The current character is not in the
1991 scanset. */
1992 ungetwc (c, s);
1993 goto out;
1996 else
1998 if (*runp == runp[1] && !not_in)
1999 break;
2000 if (*runp != runp[1] && not_in)
2002 ungetwc (c ,s);
2003 goto out;
2007 ++runp;
2010 if (!(flags & SUPPRESS))
2012 *wstr++ = c;
2014 if ((flags & MALLOC)
2015 && wstr == (wchar_t *) *strptr + strsize)
2017 /* Enlarge the buffer. */
2018 wstr = (wchar_t *) realloc (*strptr,
2019 (2 * strsize)
2020 * sizeof (wchar_t));
2021 if (wstr == NULL)
2023 /* Can't allocate that much. Last-ditch
2024 effort. */
2025 wstr = (wchar_t *)
2026 realloc (*strptr, (strsize
2027 + sizeof (wchar_t)));
2028 if (wstr == NULL)
2030 /* We lose. Oh well. Terminate the string
2031 and stop converting, so at least we don't
2032 skip any input. */
2033 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2034 ++done;
2035 conv_error ();
2037 else
2039 *strptr = (char *) wstr;
2040 wstr += strsize;
2041 ++strsize;
2044 else
2046 *strptr = (char *) wstr;
2047 wstr += strsize;
2048 strsize *= 2;
2053 while (--width > 0);
2054 out:
2055 #else
2056 char buf[MB_LEN_MAX];
2057 size_t cnt = 0;
2058 mbstate_t cstate;
2060 memset (&cstate, '\0', sizeof (cstate));
2064 again:
2065 if (inchar () == EOF)
2066 break;
2068 if (wp[c] == not_in)
2070 ungetc (c, s);
2071 break;
2074 /* This is easy. */
2075 if (!(flags & SUPPRESS))
2077 size_t n;
2079 /* Convert it into a wide character. */
2080 n = __mbrtowc (wstr, buf, cnt, &cstate);
2082 if (n == (size_t) -2)
2084 /* Possibly correct character, just not enough
2085 input. */
2086 assert (cnt < MB_CUR_MAX);
2087 goto again;
2090 if (n != cnt)
2091 encode_error ();
2093 ++wstr;
2094 if ((flags & MALLOC)
2095 && wstr == (wchar_t *) *strptr + strsize)
2097 /* Enlarge the buffer. */
2098 wstr = (wchar_t *) realloc (*strptr,
2099 (2 * strsize
2100 * sizeof (wchar_t)));
2101 if (wstr == NULL)
2103 /* Can't allocate that much. Last-ditch
2104 effort. */
2105 wstr = (wchar_t *)
2106 realloc (*strptr, ((strsize + 1)
2107 * sizeof (wchar_t)));
2108 if (wstr == NULL)
2110 /* We lose. Oh well. Terminate the
2111 string and stop converting,
2112 so at least we don't skip any input. */
2113 ((wchar_t *) (*strptr))[strsize - 1] = L'\0';
2114 ++done;
2115 conv_error ();
2117 else
2119 *strptr = (char *) wstr;
2120 wstr += strsize;
2121 ++strsize;
2124 else
2126 *strptr = (char *) wstr;
2127 wstr += strsize;
2128 strsize *= 2;
2133 while (--width > 0);
2135 if (cnt != 0)
2136 /* We stopped in the middle of recognizing another
2137 character. That's a problem. */
2138 encode_error ();
2139 #endif
2141 if (now == read_in)
2142 /* We haven't succesfully read any character. */
2143 conv_error ();
2145 if (!(flags & SUPPRESS))
2147 *wstr++ = L'\0';
2149 if ((flags & MALLOC)
2150 && wstr - (wchar_t *) *strptr != strsize)
2152 wchar_t *cp = (wchar_t *)
2153 realloc (*strptr, ((wstr - (wchar_t *) *strptr)
2154 * sizeof(wchar_t)));
2155 if (cp != NULL)
2156 *strptr = (char *) cp;
2159 ++done;
2162 else
2164 size_t now = read_in;
2165 #ifdef COMPILE_WSCANF
2167 memset (&state, '\0', sizeof (state));
2171 wchar_t *runp;
2172 size_t n;
2174 if (inchar () == WEOF)
2175 break;
2177 /* Test whether it's in the scanlist. */
2178 runp = tw;
2179 while (runp < wp)
2181 if (runp[0] == L'-' && runp[1] != '\0' && runp[1] != ']'
2182 && runp != tw
2183 && (unsigned int) runp[-1] <= (unsigned int) runp[1])
2185 /* Match against all characters in between the
2186 first and last character of the sequence. */
2187 wchar_t wc;
2189 for (wc = runp[-1] + 1; wc < runp[1]; ++wc)
2190 if (wc == c)
2191 break;
2193 if (wc == runp[1] && !not_in)
2194 break;
2195 if (wc == runp[1] && not_in)
2197 /* The current character is not in the
2198 scanset. */
2199 ungetwc (c, s);
2200 goto out2;
2203 else
2205 if (*runp == runp[1] && !not_in)
2206 break;
2207 if (*runp != runp[1] && not_in)
2209 ungetwc (c ,s);
2210 goto out2;
2214 ++runp;
2217 if (!(flags & SUPPRESS))
2219 if ((flags & MALLOC)
2220 && str + MB_CUR_MAX >= *strptr + strsize)
2222 /* Enlarge the buffer. */
2223 str = (char *) realloc (*strptr, 2 * strsize);
2224 if (str == NULL)
2226 /* Can't allocate that much. Last-ditch
2227 effort. */
2228 str = (char *) realloc (*strptr, strsize + 1);
2229 if (str == NULL)
2231 /* We lose. Oh well. Terminate the string
2232 and stop converting, so at least we don't
2233 skip any input. */
2234 (*strptr)[strsize - 1] = '\0';
2235 ++done;
2236 conv_error ();
2238 else
2240 *strptr = str;
2241 str += strsize;
2242 ++strsize;
2245 else
2247 *strptr = str;
2248 str += strsize;
2249 strsize *= 2;
2254 n = wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
2255 if (n == (size_t) -1)
2256 encode_error ();
2258 assert (n <= MB_CUR_MAX);
2259 str += n;
2261 while (--width > 0);
2262 out2:
2263 #else
2266 if (inchar () == EOF)
2267 break;
2269 if (wp[c] == not_in)
2271 ungetc (c, s);
2272 break;
2275 /* This is easy. */
2276 if (!(flags & SUPPRESS))
2278 *str++ = c;
2279 if ((flags & MALLOC)
2280 && (char *) str == *strptr + strsize)
2282 /* Enlarge the buffer. */
2283 str = (char *) realloc (*strptr, 2 * strsize);
2284 if (str == NULL)
2286 /* Can't allocate that much. Last-ditch
2287 effort. */
2288 str = (char *) realloc (*strptr, strsize + 1);
2289 if (str == NULL)
2291 /* We lose. Oh well. Terminate the
2292 string and stop converting,
2293 so at least we don't skip any input. */
2294 ((char *) (*strptr))[strsize - 1] = '\0';
2295 ++done;
2296 conv_error ();
2298 else
2300 *strptr = (char *) str;
2301 str += strsize;
2302 ++strsize;
2305 else
2307 *strptr = (char *) str;
2308 str += strsize;
2309 strsize *= 2;
2314 while (--width > 0);
2315 #endif
2317 if (now == read_in)
2318 /* We haven't succesfully read any character. */
2319 conv_error ();
2321 if (!(flags & SUPPRESS))
2323 #ifdef COMPILE_WSCANF
2324 /* We have to emit the code to get into the intial
2325 state. */
2326 char buf[MB_LEN_MAX];
2327 size_t n = wcrtomb (buf, L'\0', &state);
2328 if (n > 0 && (flags & MALLOC)
2329 && str + n >= *strptr + strsize)
2331 /* Enlarge the buffer. */
2332 str = (char *) realloc (*strptr,
2333 (str + n + 1) - *strptr);
2334 if (str == NULL)
2336 /* We lose. Oh well. Terminate the string
2337 and stop converting, so at least we don't
2338 skip any input. */
2339 ((char *) (*strptr))[strsize - 1] = '\0';
2340 ++done;
2341 conv_error ();
2343 else
2345 *strptr = (char *) str;
2346 str = ((char *) *strptr) + strsize;
2347 strsize = (str + n + 1) - *strptr;
2351 str = __mempcpy (str, buf, n);
2352 #endif
2353 *str = '\0';
2355 if ((flags & MALLOC) && str - *strptr != strsize)
2357 char *cp = (char *) realloc (*strptr, str - *strptr);
2358 if (cp != NULL)
2359 *strptr = cp;
2362 ++done;
2365 break;
2367 case L_('p'): /* Generic pointer. */
2368 base = 16;
2369 /* A PTR must be the same size as a `long int'. */
2370 flags &= ~(SHORT|LONGDBL);
2371 if (need_long)
2372 flags |= LONG;
2373 number_signed = 0;
2374 read_pointer = 1;
2375 goto number;
2377 default:
2378 /* If this is an unknown format character punt. */
2379 conv_error ();
2383 /* The last thing we saw int the format string was a white space.
2384 Consume the last white spaces. */
2385 if (skip_space)
2388 c = inchar ();
2389 while (ISSPACE (c));
2390 ungetc (c, s);
2393 /* Unlock stream. */
2394 UNLOCK_STREAM (s);
2396 return done;
2399 #ifdef USE_IN_LIBIO
2400 # ifdef COMPILE_WSCANF
2402 __vfwscanf (FILE *s, const wchar_t *format, va_list argptr)
2404 return _IO_vfwscanf (s, format, argptr, NULL);
2406 # else
2408 __vfscanf (FILE *s, const char *format, va_list argptr)
2410 return _IO_vfscanf (s, format, argptr, NULL);
2412 # endif
2413 #endif
2415 #ifdef COMPILE_WSCANF
2416 weak_alias (__vfwscanf, vfwscanf)
2417 #else
2418 weak_alias (__vfscanf, vfscanf)
2419 #endif