Update.
[glibc.git] / stdio-common / vfscanf.c
blob1b6dc6537dbb9ce2a844cbb1d16262f37c403243
1 /* Copyright (C) 1991,92,93,94,95,96,97,98 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 <errno.h>
20 #include <limits.h>
21 #include <ctype.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <wctype.h>
28 #include <bits/libc-lock.h>
29 #include <locale/localeinfo.h>
31 #ifdef __GNUC__
32 # define HAVE_LONGLONG
33 # define LONGLONG long long
34 #else
35 # define LONGLONG long
36 #endif
38 /* Those are flags in the conversion format. */
39 # define LONG 0x001 /* l: long or double */
40 # define LONGDBL 0x002 /* L: long long or long double */
41 # define SHORT 0x004 /* h: short */
42 # define SUPPRESS 0x008 /* *: suppress assignment */
43 # define POINTER 0x010 /* weird %p pointer (`fake hex') */
44 # define NOSKIP 0x020 /* do not skip blanks */
45 # define WIDTH 0x040 /* width was given */
46 # define GROUP 0x080 /* ': group numbers */
47 # define MALLOC 0x100 /* a: malloc strings */
48 # define CHAR 0x200 /* hh: char */
51 #ifdef USE_IN_LIBIO
52 # include <libioP.h>
53 # include <libio.h>
55 # undef va_list
56 # define va_list _IO_va_list
57 # define ungetc(c, s) ((void) ((int) c == EOF \
58 || (--read_in, \
59 _IO_sputbackc (s, (unsigned char) c))))
60 # define inchar() (c == EOF ? EOF \
61 : ((c = _IO_getc_unlocked (s)), \
62 (void) (c != EOF && ++read_in), c))
63 # define encode_error() do { \
64 if (errp != NULL) *errp |= 4; \
65 _IO_funlockfile (s); \
66 __libc_cleanup_end (0); \
67 __set_errno (EILSEQ); \
68 return done; \
69 } while (0)
70 # define conv_error() do { \
71 if (errp != NULL) *errp |= 2; \
72 _IO_funlockfile (s); \
73 __libc_cleanup_end (0); \
74 return done; \
75 } while (0)
76 # define input_error() do { \
77 _IO_funlockfile (s); \
78 if (errp != NULL) *errp |= 1; \
79 __libc_cleanup_end (0); \
80 return done ?: EOF; \
81 } while (0)
82 # define memory_error() do { \
83 _IO_funlockfile (s); \
84 __set_errno (ENOMEM); \
85 __libc_cleanup_end (0); \
86 return EOF; \
87 } while (0)
88 # define ARGCHECK(s, format) \
89 do \
90 { \
91 /* Check file argument for consistence. */ \
92 CHECK_FILE (s, EOF); \
93 if (s->_flags & _IO_NO_READS) \
94 { \
95 __set_errno (EBADF); \
96 return EOF; \
97 } \
98 else if (format == NULL) \
99 { \
100 MAYBE_SET_EINVAL; \
101 return EOF; \
103 } while (0)
104 # define LOCK_STREAM(S) \
105 __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \
106 _IO_flockfile (S)
107 # define UNLOCK_STREAM(S) \
108 _IO_funlockfile (S); \
109 __libc_cleanup_region_end (0)
110 #else
111 # define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s))
112 # define inchar() (c == EOF ? EOF \
113 : ((c = getc (s)), (void) (c != EOF && ++read_in), c))
114 # define encode_error() do { \
115 funlockfile (s); \
116 __set_errno (EILSEQ); \
117 return done; \
118 } while (0)
119 # define conv_error() do { \
120 funlockfile (s); \
121 return done; \
122 } while (0)
123 # define input_error() do { \
124 funlockfile (s); \
125 return done ?: EOF; \
126 } while (0)
127 # define memory_error() do { \
128 funlockfile (s); \
129 __set_errno (ENOMEM); \
130 return EOF; \
131 } while (0)
132 # define ARGCHECK(s, format) \
133 do \
135 /* Check file argument for consistence. */ \
136 if (!__validfp (s) || !s->__mode.__read) \
138 __set_errno (EBADF); \
139 return EOF; \
141 else if (format == NULL) \
143 __set_errno (EINVAL); \
144 return EOF; \
146 } while (0)
147 #if 1
148 /* XXX For now !!! */
149 # define flockfile(S) /* nothing */
150 # define funlockfile(S) /* nothing */
151 # define LOCK_STREAM(S)
152 # define UNLOCK_STREAM(S)
153 #else
154 # define LOCK_STREAM(S) \
155 __libc_cleanup_region_start (&__funlockfile, (S)); \
156 __flockfile (S)
157 # define UNLOCK_STREAM(S) \
158 __funlockfile (S); \
159 __libc_cleanup_region_end (0)
160 #endif
161 #endif
164 /* Read formatted input from S according to the format string
165 FORMAT, using the argument list in ARG.
166 Return the number of assignments made, or -1 for an input error. */
167 #ifdef USE_IN_LIBIO
169 _IO_vfscanf (s, format, argptr, errp)
170 _IO_FILE *s;
171 const char *format;
172 _IO_va_list argptr;
173 int *errp;
174 #else
176 __vfscanf (FILE *s, const char *format, va_list argptr)
177 #endif
179 va_list arg;
180 register const char *f = format;
181 register unsigned char fc; /* Current character of the format. */
182 register size_t done = 0; /* Assignments done. */
183 register size_t read_in = 0; /* Chars read in. */
184 register int c = 0; /* Last char read. */
185 register int width; /* Maximum field width. */
186 register int flags; /* Modifiers for current format element. */
188 /* Status for reading F-P nums. */
189 char got_dot, got_e, negative;
190 /* If a [...] is a [^...]. */
191 char not_in;
192 #define exp_char not_in
193 /* Base for integral numbers. */
194 int base;
195 /* Signedness for integral numbers. */
196 int number_signed;
197 #define is_hexa number_signed
198 /* Decimal point character. */
199 wchar_t decimal;
200 /* The thousands character of the current locale. */
201 wchar_t thousands;
202 /* Integral holding variables. */
203 union
205 long long int q;
206 unsigned long long int uq;
207 long int l;
208 unsigned long int ul;
209 } num;
210 /* Character-buffer pointer. */
211 char *str = NULL;
212 wchar_t *wstr = NULL;
213 char **strptr = NULL;
214 size_t strsize = 0;
215 /* We must not react on white spaces immediately because they can
216 possibly be matched even if in the input stream no character is
217 available anymore. */
218 int skip_space = 0;
219 /* Nonzero if we are reading a pointer. */
220 int read_pointer;
221 /* Workspace. */
222 char *tw; /* Temporary pointer. */
223 char *wp = NULL; /* Workspace. */
224 size_t wpmax = 0; /* Maximal size of workspace. */
225 size_t wpsize; /* Currently used bytes in workspace. */
226 #define ADDW(Ch) \
227 do \
229 if (wpsize == wpmax) \
231 char *old = wp; \
232 wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \
233 wp = (char *) alloca (wpmax); \
234 if (old != NULL) \
235 memcpy (wp, old, wpsize); \
237 wp[wpsize++] = (Ch); \
239 while (0)
241 #ifdef __va_copy
242 __va_copy (arg, argptr);
243 #else
244 arg = (va_list) argptr;
245 #endif
247 ARGCHECK (s, format);
249 /* Figure out the decimal point character. */
250 if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
251 strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
252 decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
253 /* Figure out the thousands separator character. */
254 if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
255 strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
256 thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
258 /* Lock the stream. */
259 LOCK_STREAM (s);
261 /* Run through the format string. */
262 while (*f != '\0')
264 unsigned int argpos;
265 /* Extract the next argument, which is of type TYPE.
266 For a %N$... spec, this is the Nth argument from the beginning;
267 otherwise it is the next argument after the state now in ARG. */
268 #ifdef __va_copy
269 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
270 ({ unsigned int pos = argpos; \
271 va_list arg; \
272 __va_copy (arg, argptr); \
273 while (--pos > 0) \
274 (void) va_arg (arg, void *); \
275 va_arg (arg, type); \
277 #else
278 # if 0
279 /* XXX Possible optimization. */
280 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
281 ({ va_list arg = (va_list) argptr; \
282 arg = (va_list) ((char *) arg \
283 + (argpos - 1) \
284 * __va_rounded_size (void *)); \
285 va_arg (arg, type); \
287 # else
288 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
289 ({ unsigned int pos = argpos; \
290 va_list arg = (va_list) argptr; \
291 while (--pos > 0) \
292 (void) va_arg (arg, void *); \
293 va_arg (arg, type); \
295 # endif
296 #endif
298 if (!isascii (*f))
300 /* Non-ASCII, may be a multibyte. */
301 int len = mblen (f, strlen (f));
302 if (len > 0)
306 c = inchar ();
307 if (c == EOF)
308 input_error ();
309 else if (c != *f++)
311 ungetc (c, s);
312 conv_error ();
315 while (--len > 0);
316 continue;
320 fc = *f++;
321 if (fc != '%')
323 /* Remember to skip spaces. */
324 if (isspace (fc))
326 skip_space = 1;
327 continue;
330 /* Read a character. */
331 c = inchar ();
333 /* Characters other than format specs must just match. */
334 if (c == EOF)
335 input_error ();
337 /* We saw white space char as the last character in the format
338 string. Now it's time to skip all leading white space. */
339 if (skip_space)
341 while (isspace (c))
342 if (inchar () == EOF && errno == EINTR)
343 conv_error ();
344 skip_space = 0;
347 if (c != fc)
349 ungetc (c, s);
350 conv_error ();
353 continue;
356 /* This is the start of the conversion string. */
357 flags = 0;
359 /* Not yet decided whether we read a pointer or not. */
360 read_pointer = 0;
362 /* Initialize state of modifiers. */
363 argpos = 0;
365 /* Prepare temporary buffer. */
366 wpsize = 0;
368 /* Check for a positional parameter specification. */
369 if (isdigit (*f))
371 argpos = *f++ - '0';
372 while (isdigit (*f))
373 argpos = argpos * 10 + (*f++ - '0');
374 if (*f == '$')
375 ++f;
376 else
378 /* Oops; that was actually the field width. */
379 width = argpos;
380 flags |= WIDTH;
381 argpos = 0;
382 goto got_width;
386 /* Check for the assignment-suppressing and the number grouping flag. */
387 while (*f == '*' || *f == '\'')
388 switch (*f++)
390 case '*':
391 flags |= SUPPRESS;
392 break;
393 case '\'':
394 flags |= GROUP;
395 break;
398 /* We have seen width. */
399 if (isdigit (*f))
400 flags |= WIDTH;
402 /* Find the maximum field width. */
403 width = 0;
404 while (isdigit (*f))
406 width *= 10;
407 width += *f++ - '0';
409 got_width:
410 if (width == 0)
411 width = -1;
413 /* Check for type modifiers. */
414 switch (*f++)
416 case 'h':
417 /* ints are short ints or chars. */
418 if (*f == 'h')
420 ++f;
421 flags |= CHAR;
423 else
424 flags |= SHORT;
425 break;
426 case 'l':
427 if (*f == 'l')
429 /* A double `l' is equivalent to an `L'. */
430 ++f;
431 flags |= LONGDBL;
433 else
434 /* ints are long ints. */
435 flags |= LONG;
436 break;
437 case 'q':
438 case 'L':
439 /* doubles are long doubles, and ints are long long ints. */
440 flags |= LONGDBL;
441 break;
442 case 'a':
443 /* The `a' is used as a flag only if followed by `s', `S' or
444 `['. */
445 if (*f != 's' && *f != 'S' && *f != '[')
447 --f;
448 break;
450 /* String conversions (%s, %[) take a `char **'
451 arg and fill it in with a malloc'd pointer. */
452 flags |= MALLOC;
453 break;
454 case 'z':
455 if (sizeof (size_t) > sizeof (unsigned long int))
456 flags |= LONGDBL;
457 else if (sizeof (size_t) > sizeof (unsigned int))
458 flags |= LONG;
459 break;
460 case 'j':
461 if (sizeof (uintmax_t) > sizeof (unsigned long int))
462 flags |= LONGDBL;
463 else if (sizeof (uintmax_t) > sizeof (unsigned int))
464 flags |= LONG;
465 break;
466 case 't':
467 if (sizeof (ptrdiff_t) > sizeof (long int))
468 flags |= LONGDBL;
469 else if (sizeof (ptrdiff_t) > sizeof (int))
470 flags |= LONG;
471 break;
472 default:
473 /* Not a recognized modifier. Backup. */
474 --f;
475 break;
478 /* End of the format string? */
479 if (*f == '\0')
480 conv_error ();
482 /* Find the conversion specifier. */
483 fc = *f++;
484 if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
486 /* Eat whitespace. */
487 int save_errno = errno;
488 errno = 0;
490 if (inchar () == EOF && errno == EINTR)
491 input_error ();
492 while (isspace (c));
493 errno = save_errno;
494 ungetc (c, s);
495 skip_space = 0;
498 switch (fc)
500 case '%': /* Must match a literal '%'. */
501 c = inchar ();
502 if (c == EOF)
503 input_error ();
504 if (c != fc)
506 ungetc (c, s);
507 conv_error ();
509 break;
511 case 'n': /* Answer number of assignments done. */
512 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
513 with the 'n' conversion specifier. */
514 if (!(flags & SUPPRESS))
516 /* Don't count the read-ahead. */
517 if (flags & LONGDBL)
518 *ARG (long long int *) = read_in;
519 else if (flags & LONG)
520 *ARG (long int *) = read_in;
521 else if (flags & SHORT)
522 *ARG (short int *) = read_in;
523 else
524 *ARG (int *) = read_in;
526 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
527 /* We have a severe problem here. The ISO C standard
528 contradicts itself in explaining the effect of the %n
529 format in `scanf'. While in ISO C:1990 and the ISO C
530 Amendement 1:1995 the result is described as
532 Execution of a %n directive does not effect the
533 assignment count returned at the completion of
534 execution of the f(w)scanf function.
536 in ISO C Corrigendum 1:1994 the following was added:
538 Subclause 7.9.6.2
539 Add the following fourth example:
541 #include <stdio.h>
542 int d1, d2, n1, n2, i;
543 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
544 the value 123 is assigned to d1 and the value3 to n1.
545 Because %n can never get an input failure the value
546 of 3 is also assigned to n2. The value of d2 is not
547 affected. The value 3 is assigned to i.
549 We go for now with the historically correct code from ISO C,
550 i.e., we don't count the %n assignments. When it ever
551 should proof to be wrong just remove the #ifdef above. */
552 ++done;
553 #endif
555 break;
557 case 'c': /* Match characters. */
558 if ((flags & LONG) == 0)
560 if (!(flags & SUPPRESS))
562 str = ARG (char *);
563 if (str == NULL)
564 conv_error ();
567 c = inchar ();
568 if (c == EOF)
569 input_error ();
571 if (width == -1)
572 width = 1;
574 if (!(flags & SUPPRESS))
577 *str++ = c;
578 while (--width > 0 && inchar () != EOF);
580 else
581 while (--width > 0 && inchar () != EOF);
583 if (!(flags & SUPPRESS))
584 ++done;
586 break;
588 /* FALLTHROUGH */
589 case 'C':
590 /* Get UTF-8 encoded wide character. Here we assume (as in
591 other parts of the libc) that we only have to handle
592 UTF-8. */
594 wint_t val;
595 size_t cnt = 0;
596 int first = 1;
598 if (!(flags & SUPPRESS))
600 wstr = ARG (wchar_t *);
601 if (str == NULL)
602 conv_error ();
607 #define NEXT_WIDE_CHAR(First) \
608 c = inchar (); \
609 if (c == EOF) \
611 /* EOF is only an error for the first character. */ \
612 if (First) \
613 input_error (); \
614 else \
615 break; \
617 val = c; \
618 if (val >= 0x80) \
620 if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
621 encode_error (); \
622 if ((c & 0xe0) == 0xc0) \
624 /* We expect two bytes. */ \
625 cnt = 1; \
626 val &= 0x1f; \
628 else if ((c & 0xf0) == 0xe0) \
630 /* We expect three bytes. */ \
631 cnt = 2; \
632 val &= 0x0f; \
634 else if ((c & 0xf8) == 0xf0) \
636 /* We expect four bytes. */ \
637 cnt = 3; \
638 val &= 0x07; \
640 else if ((c & 0xfc) == 0xf8) \
642 /* We expect five bytes. */ \
643 cnt = 4; \
644 val &= 0x03; \
646 else \
648 /* We expect six bytes. */ \
649 cnt = 5; \
650 val &= 0x01; \
653 do \
655 c = inchar (); \
656 if (c == EOF \
657 || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
658 encode_error (); \
659 val <<= 6; \
660 val |= c & 0x3f; \
662 while (--cnt > 0); \
665 if (!(flags & SUPPRESS)) \
666 *wstr++ = val; \
667 First = 0
669 NEXT_WIDE_CHAR (first);
671 while (--width > 0);
673 if (!(flags & SUPPRESS))
674 ++done;
676 break;
678 case 's': /* Read a string. */
679 if (flags & LONG)
680 /* We have to process a wide character string. */
681 goto wide_char_string;
683 #define STRING_ARG(Str, Type) \
684 if (!(flags & SUPPRESS)) \
686 if (flags & MALLOC) \
688 /* The string is to be stored in a malloc'd buffer. */ \
689 strptr = ARG (char **); \
690 if (strptr == NULL) \
691 conv_error (); \
692 /* Allocate an initial buffer. */ \
693 strsize = 100; \
694 *strptr = malloc (strsize * sizeof (Type)); \
695 Str = (Type *) *strptr; \
697 else \
698 Str = ARG (Type *); \
699 if (Str == NULL) \
700 conv_error (); \
702 STRING_ARG (str, char);
704 c = inchar ();
705 if (c == EOF)
706 input_error ();
710 if (isspace (c))
712 ungetc (c, s);
713 break;
715 #define STRING_ADD_CHAR(Str, c, Type) \
716 if (!(flags & SUPPRESS)) \
718 *Str++ = c; \
719 if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \
721 /* Enlarge the buffer. */ \
722 Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \
723 if (Str == NULL) \
725 /* Can't allocate that much. Last-ditch effort. */\
726 Str = realloc (*strptr, \
727 (strsize + 1) * sizeof (Type)); \
728 if (Str == NULL) \
730 /* We lose. Oh well. \
731 Terminate the string and stop converting, \
732 so at least we don't skip any input. */ \
733 ((Type *) (*strptr))[strsize] = '\0'; \
734 ++done; \
735 conv_error (); \
737 else \
739 *strptr = (char *) Str; \
740 Str = ((Type *) *strptr) + strsize; \
741 ++strsize; \
744 else \
746 *strptr = (char *) Str; \
747 Str = ((Type *) *strptr) + strsize; \
748 strsize *= 2; \
752 STRING_ADD_CHAR (str, c, char);
753 } while ((width <= 0 || --width > 0) && inchar () != EOF);
755 if (!(flags & SUPPRESS))
757 *str = '\0';
758 ++done;
760 break;
762 case 'S':
763 /* Wide character string. */
764 wide_char_string:
766 wint_t val;
767 int first = 1;
768 STRING_ARG (wstr, wchar_t);
772 size_t cnt = 0;
773 NEXT_WIDE_CHAR (first);
775 if (iswspace (val))
777 /* XXX We would have to push back the whole wide char
778 with possibly many bytes. But since scanf does
779 not make a difference for white space characters
780 we can simply push back a simple <SP> which is
781 guaranteed to be in the [:space:] class. */
782 ungetc (' ', s);
783 break;
786 STRING_ADD_CHAR (wstr, val, wchar_t);
787 first = 0;
789 while (width <= 0 || --width > 0);
791 if (!(flags & SUPPRESS))
793 *wstr = L'\0';
794 ++done;
797 break;
799 case 'x': /* Hexadecimal integer. */
800 case 'X': /* Ditto. */
801 base = 16;
802 number_signed = 0;
803 goto number;
805 case 'o': /* Octal integer. */
806 base = 8;
807 number_signed = 0;
808 goto number;
810 case 'u': /* Unsigned decimal integer. */
811 base = 10;
812 number_signed = 0;
813 goto number;
815 case 'd': /* Signed decimal integer. */
816 base = 10;
817 number_signed = 1;
818 goto number;
820 case 'i': /* Generic number. */
821 base = 0;
822 number_signed = 1;
824 number:
825 c = inchar ();
826 if (c == EOF)
827 input_error ();
829 /* Check for a sign. */
830 if (c == '-' || c == '+')
832 ADDW (c);
833 if (width > 0)
834 --width;
835 c = inchar ();
838 /* Look for a leading indication of base. */
839 if (width != 0 && c == '0')
841 if (width > 0)
842 --width;
844 ADDW (c);
845 c = inchar ();
847 if (width != 0 && tolower (c) == 'x')
849 if (base == 0)
850 base = 16;
851 if (base == 16)
853 if (width > 0)
854 --width;
855 c = inchar ();
858 else if (base == 0)
859 base = 8;
862 if (base == 0)
863 base = 10;
865 /* Read the number into workspace. */
866 while (c != EOF && width != 0)
868 if (base == 16 ? !isxdigit (c) :
869 ((!isdigit (c) || c - '0' >= base) &&
870 !((flags & GROUP) && base == 10 && c == thousands)))
871 break;
872 ADDW (c);
873 if (width > 0)
874 --width;
876 c = inchar ();
879 if (wpsize == 0 ||
880 (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
882 /* There was no number. If we are supposed to read a pointer
883 we must recognize "(nil)" as well. */
884 if (wpsize == 0 && read_pointer && (width < 0 || width >= 0)
885 && c == '('
886 && tolower (inchar ()) == 'n'
887 && tolower (inchar ()) == 'i'
888 && tolower (inchar ()) == 'l'
889 && inchar () == ')')
890 /* We must produce the value of a NULL pointer. A single
891 '0' digit is enough. */
892 ADDW ('0');
893 else
895 /* The last read character is not part of the number
896 anymore. */
897 ungetc (c, s);
899 conv_error ();
902 else
903 /* The just read character is not part of the number anymore. */
904 ungetc (c, s);
906 /* Convert the number. */
907 ADDW ('\0');
908 if (flags & LONGDBL)
910 if (number_signed)
911 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
912 else
913 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
915 else
917 if (number_signed)
918 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
919 else
920 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
922 if (wp == tw)
923 conv_error ();
925 if (!(flags & SUPPRESS))
927 if (! number_signed)
929 if (flags & LONGDBL)
930 *ARG (unsigned LONGLONG int *) = num.uq;
931 else if (flags & LONG)
932 *ARG (unsigned long int *) = num.ul;
933 else if (flags & SHORT)
934 *ARG (unsigned short int *)
935 = (unsigned short int) num.ul;
936 else if (flags & CHAR)
937 *ARG (unsigned char *) = (unsigned char) num.ul;
938 else
939 *ARG (unsigned int *) = (unsigned int) num.ul;
941 else
943 if (flags & LONGDBL)
944 *ARG (LONGLONG int *) = num.q;
945 else if (flags & LONG)
946 *ARG (long int *) = num.l;
947 else if (flags & SHORT)
948 *ARG (short int *) = (short int) num.l;
949 else if (flags & CHAR)
950 *ARG (signed char *) = (signed char) num.ul;
951 else
952 *ARG (int *) = (int) num.l;
954 ++done;
956 break;
958 case 'e': /* Floating-point numbers. */
959 case 'E':
960 case 'f':
961 case 'g':
962 case 'G':
963 case 'a':
964 case 'A':
965 c = inchar ();
966 if (c == EOF)
967 input_error ();
969 /* Check for a sign. */
970 if (c == '-' || c == '+')
972 negative = c == '-';
973 if (inchar () == EOF)
974 /* EOF is only an input error before we read any chars. */
975 conv_error ();
976 if (width > 0)
977 --width;
979 else
980 negative = 0;
982 /* Take care for the special arguments "nan" and "inf". */
983 if (tolower (c) == 'n')
985 /* Maybe "nan". */
986 ADDW (c);
987 if (inchar () == EOF || tolower (c) != 'a')
988 input_error ();
989 ADDW (c);
990 if (inchar () == EOF || tolower (c) != 'n')
991 input_error ();
992 ADDW (c);
993 /* It is "nan". */
994 goto scan_float;
996 else if (tolower (c) == 'i')
998 /* Maybe "inf" or "infinity". */
999 ADDW (c);
1000 if (inchar () == EOF || tolower (c) != 'n')
1001 input_error ();
1002 ADDW (c);
1003 if (inchar () == EOF || tolower (c) != 'f')
1004 input_error ();
1005 ADDW (c);
1006 /* It is as least "inf". */
1007 if (inchar () != EOF)
1009 if (tolower (c) == 'i')
1011 /* No we have to read the rest as well. */
1012 ADDW (c);
1013 if (inchar () == EOF || tolower (c) != 'n')
1014 input_error ();
1015 ADDW (c);
1016 if (inchar () == EOF || tolower (c) != 'i')
1017 input_error ();
1018 ADDW (c);
1019 if (inchar () == EOF || tolower (c) != 't')
1020 input_error ();
1021 ADDW (c);
1022 if (inchar () == EOF || tolower (c) != 'y')
1023 input_error ();
1024 ADDW (c);
1026 else
1027 /* Never mind. */
1028 ungetc (c, s);
1030 goto scan_float;
1033 is_hexa = 0;
1034 exp_char = 'e';
1035 if (c == '0')
1037 ADDW (c);
1038 c = inchar ();
1039 if (tolower (c) == 'x')
1041 /* It is a number in hexadecimal format. */
1042 ADDW (c);
1044 is_hexa = 1;
1045 exp_char = 'p';
1047 /* Grouping is not allowed. */
1048 flags &= ~GROUP;
1049 c = inchar ();
1053 got_dot = got_e = 0;
1056 if (isdigit (c))
1057 ADDW (c);
1058 else if (!got_e && is_hexa && isxdigit (c))
1059 ADDW (c);
1060 else if (got_e && wp[wpsize - 1] == exp_char
1061 && (c == '-' || c == '+'))
1062 ADDW (c);
1063 else if (wpsize > 0 && !got_e && tolower (c) == exp_char)
1065 ADDW (exp_char);
1066 got_e = got_dot = 1;
1068 else if (c == decimal && !got_dot)
1070 ADDW (c);
1071 got_dot = 1;
1073 else if ((flags & GROUP) && c == thousands && !got_dot)
1074 ADDW (c);
1075 else
1077 /* The last read character is not part of the number
1078 anymore. */
1079 ungetc (c, s);
1080 break;
1082 if (width > 0)
1083 --width;
1085 while (width != 0 && inchar () != EOF);
1087 /* Have we read any character? If we try to read a number
1088 in hexadecimal notation and we have read only the `0x'
1089 prefix this is an error. */
1090 if (wpsize == 0 || (is_hexa && wpsize == 2))
1091 conv_error ();
1093 scan_float:
1094 /* Convert the number. */
1095 ADDW ('\0');
1096 if (flags & LONGDBL)
1098 long double d = __strtold_internal (wp, &tw, flags & GROUP);
1099 if (!(flags & SUPPRESS) && tw != wp)
1100 *ARG (long double *) = negative ? -d : d;
1102 else if (flags & LONG)
1104 double d = __strtod_internal (wp, &tw, flags & GROUP);
1105 if (!(flags & SUPPRESS) && tw != wp)
1106 *ARG (double *) = negative ? -d : d;
1108 else
1110 float d = __strtof_internal (wp, &tw, flags & GROUP);
1111 if (!(flags & SUPPRESS) && tw != wp)
1112 *ARG (float *) = negative ? -d : d;
1115 if (tw == wp)
1116 conv_error ();
1118 if (!(flags & SUPPRESS))
1119 ++done;
1120 break;
1122 case '[': /* Character class. */
1123 if (flags & LONG)
1125 STRING_ARG (wstr, wchar_t);
1126 c = '\0'; /* This is to keep gcc quiet. */
1128 else
1130 STRING_ARG (str, char);
1132 c = inchar ();
1133 if (c == EOF)
1134 input_error ();
1137 if (*f == '^')
1139 ++f;
1140 not_in = 1;
1142 else
1143 not_in = 0;
1145 /* Fill WP with byte flags indexed by character.
1146 We will use this flag map for matching input characters. */
1147 if (wpmax < UCHAR_MAX)
1149 wpmax = UCHAR_MAX;
1150 wp = (char *) alloca (wpmax);
1152 memset (wp, 0, UCHAR_MAX);
1154 fc = *f;
1155 if (fc == ']' || fc == '-')
1157 /* If ] or - appears before any char in the set, it is not
1158 the terminator or separator, but the first char in the
1159 set. */
1160 wp[fc] = 1;
1161 ++f;
1164 while ((fc = *f++) != '\0' && fc != ']')
1166 if (fc == '-' && *f != '\0' && *f != ']' &&
1167 (unsigned char) f[-2] <= (unsigned char) *f)
1169 /* Add all characters from the one before the '-'
1170 up to (but not including) the next format char. */
1171 for (fc = f[-2]; fc < *f; ++fc)
1172 wp[fc] = 1;
1174 else
1175 /* Add the character to the flag map. */
1176 wp[fc] = 1;
1178 if (fc == '\0')
1180 if (!(flags & LONG))
1181 ungetc (c, s);
1182 conv_error();
1185 if (flags & LONG)
1187 wint_t val;
1188 int first = 1;
1192 size_t cnt = 0;
1193 NEXT_WIDE_CHAR (first);
1194 if (val <= 255 && wp[val] == not_in)
1196 ungetc (val, s);
1197 break;
1199 STRING_ADD_CHAR (wstr, val, wchar_t);
1200 if (width > 0)
1201 --width;
1202 first = 0;
1204 while (width != 0);
1206 if (first)
1207 conv_error ();
1209 if (!(flags & SUPPRESS))
1211 *wstr = L'\0';
1212 ++done;
1215 else
1217 num.ul = read_in - 1; /* -1 because we already read one char. */
1220 if (wp[c] == not_in)
1222 ungetc (c, s);
1223 break;
1225 STRING_ADD_CHAR (str, c, char);
1226 if (width > 0)
1227 --width;
1229 while (width != 0 && inchar () != EOF);
1231 if (read_in == num.ul)
1232 conv_error ();
1234 if (!(flags & SUPPRESS))
1236 *str = '\0';
1237 ++done;
1240 break;
1242 case 'p': /* Generic pointer. */
1243 base = 16;
1244 /* A PTR must be the same size as a `long int'. */
1245 flags &= ~(SHORT|LONGDBL);
1246 flags |= LONG;
1247 number_signed = 0;
1248 read_pointer = 1;
1249 goto number;
1251 default:
1252 /* If this is an unknown format character punt. */
1253 conv_error ();
1257 /* The last thing we saw int the format string was a white space.
1258 Consume the last white spaces. */
1259 if (skip_space)
1262 c = inchar ();
1263 while (isspace (c));
1264 ungetc (c, s);
1267 /* Unlock stream. */
1268 UNLOCK_STREAM (s);
1270 return done;
1273 #ifdef USE_IN_LIBIO
1275 __vfscanf (FILE *s, const char *format, va_list argptr)
1277 return _IO_vfscanf (s, format, argptr, NULL);
1279 #endif
1281 weak_alias (__vfscanf, vfscanf)