Update.
[glibc.git] / stdio-common / vfscanf.c
blobce5e5125f701c0084a46734289da4dd4ca78746c
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 */
50 # define TYPEMOD (LONG|LONGDBL|SHORT|CHAR)
53 #ifdef USE_IN_LIBIO
54 # include <libioP.h>
55 # include <libio.h>
57 # undef va_list
58 # define va_list _IO_va_list
59 # define ungetc(c, s) ((void) ((int) c == EOF \
60 || (--read_in, \
61 _IO_sputbackc (s, (unsigned char) c))))
62 # define inchar() (c == EOF ? EOF \
63 : ((c = _IO_getc_unlocked (s)), \
64 (void) (c != EOF && ++read_in), c))
65 # define encode_error() do { \
66 if (errp != NULL) *errp |= 4; \
67 _IO_funlockfile (s); \
68 __libc_cleanup_end (0); \
69 __set_errno (EILSEQ); \
70 return done; \
71 } while (0)
72 # define conv_error() do { \
73 if (errp != NULL) *errp |= 2; \
74 _IO_funlockfile (s); \
75 __libc_cleanup_end (0); \
76 return done; \
77 } while (0)
78 # define input_error() do { \
79 _IO_funlockfile (s); \
80 if (errp != NULL) *errp |= 1; \
81 __libc_cleanup_end (0); \
82 return done ?: EOF; \
83 } while (0)
84 # define memory_error() do { \
85 _IO_funlockfile (s); \
86 __set_errno (ENOMEM); \
87 __libc_cleanup_end (0); \
88 return EOF; \
89 } while (0)
90 # define ARGCHECK(s, format) \
91 do \
92 { \
93 /* Check file argument for consistence. */ \
94 CHECK_FILE (s, EOF); \
95 if (s->_flags & _IO_NO_READS) \
96 { \
97 __set_errno (EBADF); \
98 return EOF; \
99 } \
100 else if (format == NULL) \
102 MAYBE_SET_EINVAL; \
103 return EOF; \
105 } while (0)
106 # define LOCK_STREAM(S) \
107 __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \
108 _IO_flockfile (S)
109 # define UNLOCK_STREAM(S) \
110 _IO_funlockfile (S); \
111 __libc_cleanup_region_end (0)
112 #else
113 # define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s))
114 # define inchar() (c == EOF ? EOF \
115 : ((c = getc (s)), (void) (c != EOF && ++read_in), c))
116 # define encode_error() do { \
117 funlockfile (s); \
118 __set_errno (EILSEQ); \
119 return done; \
120 } while (0)
121 # define conv_error() do { \
122 funlockfile (s); \
123 return done; \
124 } while (0)
125 # define input_error() do { \
126 funlockfile (s); \
127 return done ?: EOF; \
128 } while (0)
129 # define memory_error() do { \
130 funlockfile (s); \
131 __set_errno (ENOMEM); \
132 return EOF; \
133 } while (0)
134 # define ARGCHECK(s, format) \
135 do \
137 /* Check file argument for consistence. */ \
138 if (!__validfp (s) || !s->__mode.__read) \
140 __set_errno (EBADF); \
141 return EOF; \
143 else if (format == NULL) \
145 __set_errno (EINVAL); \
146 return EOF; \
148 } while (0)
149 #if 1
150 /* XXX For now !!! */
151 # define flockfile(S) /* nothing */
152 # define funlockfile(S) /* nothing */
153 # define LOCK_STREAM(S)
154 # define UNLOCK_STREAM(S)
155 #else
156 # define LOCK_STREAM(S) \
157 __libc_cleanup_region_start (&__funlockfile, (S)); \
158 __flockfile (S)
159 # define UNLOCK_STREAM(S) \
160 __funlockfile (S); \
161 __libc_cleanup_region_end (0)
162 #endif
163 #endif
166 /* Read formatted input from S according to the format string
167 FORMAT, using the argument list in ARG.
168 Return the number of assignments made, or -1 for an input error. */
169 #ifdef USE_IN_LIBIO
171 _IO_vfscanf (s, format, argptr, errp)
172 _IO_FILE *s;
173 const char *format;
174 _IO_va_list argptr;
175 int *errp;
176 #else
178 __vfscanf (FILE *s, const char *format, va_list argptr)
179 #endif
181 va_list arg;
182 register const char *f = format;
183 register unsigned char fc; /* Current character of the format. */
184 register size_t done = 0; /* Assignments done. */
185 register size_t read_in = 0; /* Chars read in. */
186 register int c = 0; /* Last char read. */
187 register int width; /* Maximum field width. */
188 register int flags; /* Modifiers for current format element. */
190 /* Status for reading F-P nums. */
191 char got_dot, got_e, negative;
192 /* If a [...] is a [^...]. */
193 char not_in;
194 #define exp_char not_in
195 /* Base for integral numbers. */
196 int base;
197 /* Signedness for integral numbers. */
198 int number_signed;
199 #define is_hexa number_signed
200 /* Decimal point character. */
201 wchar_t decimal;
202 /* The thousands character of the current locale. */
203 wchar_t thousands;
204 /* Integral holding variables. */
205 union
207 long long int q;
208 unsigned long long int uq;
209 long int l;
210 unsigned long int ul;
211 } num;
212 /* Character-buffer pointer. */
213 char *str = NULL;
214 wchar_t *wstr = NULL;
215 char **strptr = NULL;
216 size_t strsize = 0;
217 /* We must not react on white spaces immediately because they can
218 possibly be matched even if in the input stream no character is
219 available anymore. */
220 int skip_space = 0;
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 /* Initialize state of modifiers. */
360 argpos = 0;
362 /* Prepare temporary buffer. */
363 wpsize = 0;
365 /* Check for a positional parameter specification. */
366 if (isdigit (*f))
368 argpos = *f++ - '0';
369 while (isdigit (*f))
370 argpos = argpos * 10 + (*f++ - '0');
371 if (*f == '$')
372 ++f;
373 else
375 /* Oops; that was actually the field width. */
376 width = argpos;
377 flags |= WIDTH;
378 argpos = 0;
379 goto got_width;
383 /* Check for the assignment-suppressing and the number grouping flag. */
384 while (*f == '*' || *f == '\'')
385 switch (*f++)
387 case '*':
388 flags |= SUPPRESS;
389 break;
390 case '\'':
391 flags |= GROUP;
392 break;
395 /* We have seen width. */
396 if (isdigit (*f))
397 flags |= WIDTH;
399 /* Find the maximum field width. */
400 width = 0;
401 while (isdigit (*f))
403 width *= 10;
404 width += *f++ - '0';
406 got_width:
407 if (width == 0)
408 width = -1;
410 /* Check for type modifiers. */
411 while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q'
412 || *f == 'z' || *f == 't' || *f == 'j')
413 switch (*f++)
415 case 'h':
416 /* int's are short int's. */
417 if (flags & (LONG|LONGDBL|CHAR))
418 /* Signal illegal format element. */
419 conv_error ();
420 if (flags & SHORT)
422 flags &= ~SHORT;
423 flags |= CHAR;
425 else
426 flags |= SHORT;
427 break;
428 case 'l':
429 if (flags & (SHORT|LONGDBL|CHAR))
430 conv_error ();
431 else if (flags & LONG)
433 /* A double `l' is equivalent to an `L'. */
434 flags &= ~LONG;
435 flags |= LONGDBL;
437 else
438 /* int's are long int's. */
439 flags |= LONG;
440 break;
441 case 'q':
442 case 'L':
443 /* double's are long double's, and int's are long long int's. */
444 if (flags & TYPEMOD)
445 /* Signal illegal format element. */
446 conv_error ();
447 flags |= LONGDBL;
448 break;
449 case 'a':
450 /* The `a' is used as a flag only if followed by `s', `S' or
451 `['. */
452 if (*f != 's' && *f != 'S' && *f != '[')
454 --f;
455 break;
457 if (flags & TYPEMOD)
458 /* Signal illegal format element. */
459 conv_error ();
460 /* String conversions (%s, %[) take a `char **'
461 arg and fill it in with a malloc'd pointer. */
462 flags |= MALLOC;
463 break;
464 case 'z':
465 if (flags & (SHORT|LONGDBL|CHAR))
466 conv_error ();
467 if (sizeof (size_t) > sizeof (unsigned long int))
468 flags |= LONGDBL;
469 else if (sizeof (size_t) > sizeof (unsigned int))
470 flags |= LONG;
471 break;
472 case 'j':
473 if (flags & (SHORT|LONGDBL|CHAR))
474 conv_error ();
475 if (sizeof (intmax_t) > sizeof (unsigned long int))
476 flags |= LONGDBL;
477 else if (sizeof (intmax_t) > sizeof (unsigned int))
478 flags |= LONG;
479 break;
480 case 't':
481 if (flags & (SHORT|LONGDBL|CHAR))
482 conv_error ();
483 if (sizeof (ptrdiff_t) > sizeof (unsigned long int))
484 flags |= LONGDBL;
485 else if (sizeof (ptrdiff_t) > sizeof (unsigned int))
486 flags |= LONG;
487 break;
490 /* End of the format string? */
491 if (*f == '\0')
492 conv_error ();
494 /* Find the conversion specifier. */
495 fc = *f++;
496 if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
498 /* Eat whitespace. */
499 int save_errno = errno;
500 errno = 0;
502 if (inchar () == EOF && errno == EINTR)
503 input_error ();
504 while (isspace (c));
505 errno = save_errno;
506 ungetc (c, s);
507 skip_space = 0;
510 switch (fc)
512 case '%': /* Must match a literal '%'. */
513 c = inchar ();
514 if (c == EOF)
515 input_error ();
516 if (c != fc)
518 ungetc (c, s);
519 conv_error ();
521 break;
523 case 'n': /* Answer number of assignments done. */
524 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
525 with the 'n' conversion specifier. */
526 if (!(flags & SUPPRESS))
528 /* Don't count the read-ahead. */
529 if (flags & LONGDBL)
530 *ARG (long long int *) = read_in;
531 else if (flags & LONG)
532 *ARG (long int *) = read_in;
533 else if (flags & SHORT)
534 *ARG (short int *) = read_in;
535 else
536 *ARG (int *) = read_in;
538 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
539 /* We have a severe problem here. The ISO C standard
540 contradicts itself in explaining the effect of the %n
541 format in `scanf'. While in ISO C:1990 and the ISO C
542 Amendement 1:1995 the result is described as
544 Execution of a %n directive does not effect the
545 assignment count returned at the completion of
546 execution of the f(w)scanf function.
548 in ISO C Corrigendum 1:1994 the following was added:
550 Subclause 7.9.6.2
551 Add the following fourth example:
553 #include <stdio.h>
554 int d1, d2, n1, n2, i;
555 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
556 the value 123 is assigned to d1 and the value3 to n1.
557 Because %n can never get an input failure the value
558 of 3 is also assigned to n2. The value of d2 is not
559 affected. The value 3 is assigned to i.
561 We go for now with the historically correct code from ISO C,
562 i.e., we don't count the %n assignments. When it ever
563 should proof to be wrong just remove the #ifdef above. */
564 ++done;
565 #endif
567 break;
569 case 'c': /* Match characters. */
570 if ((flags & LONG) == 0)
572 if (!(flags & SUPPRESS))
574 str = ARG (char *);
575 if (str == NULL)
576 conv_error ();
579 c = inchar ();
580 if (c == EOF)
581 input_error ();
583 if (width == -1)
584 width = 1;
586 if (!(flags & SUPPRESS))
589 *str++ = c;
590 while (--width > 0 && inchar () != EOF);
592 else
593 while (--width > 0 && inchar () != EOF);
595 if (!(flags & SUPPRESS))
596 ++done;
598 break;
600 /* FALLTHROUGH */
601 case 'C':
602 /* Get UTF-8 encoded wide character. Here we assume (as in
603 other parts of the libc) that we only have to handle
604 UTF-8. */
606 wint_t val;
607 size_t cnt = 0;
608 int first = 1;
610 if (!(flags & SUPPRESS))
612 wstr = ARG (wchar_t *);
613 if (str == NULL)
614 conv_error ();
619 #define NEXT_WIDE_CHAR(First) \
620 c = inchar (); \
621 if (c == EOF) \
622 /* EOF is only an error for the first character. */ \
623 if (First) \
624 input_error (); \
625 else \
626 break; \
627 val = c; \
628 if (val >= 0x80) \
630 if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
631 encode_error (); \
632 if ((c & 0xe0) == 0xc0) \
634 /* We expect two bytes. */ \
635 cnt = 1; \
636 val &= 0x1f; \
638 else if ((c & 0xf0) == 0xe0) \
640 /* We expect three bytes. */ \
641 cnt = 2; \
642 val &= 0x0f; \
644 else if ((c & 0xf8) == 0xf0) \
646 /* We expect four bytes. */ \
647 cnt = 3; \
648 val &= 0x07; \
650 else if ((c & 0xfc) == 0xf8) \
652 /* We expect five bytes. */ \
653 cnt = 4; \
654 val &= 0x03; \
656 else \
658 /* We expect six bytes. */ \
659 cnt = 5; \
660 val &= 0x01; \
663 do \
665 c = inchar (); \
666 if (c == EOF \
667 || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
668 encode_error (); \
669 val <<= 6; \
670 val |= c & 0x3f; \
672 while (--cnt > 0); \
675 if (!(flags & SUPPRESS)) \
676 *wstr++ = val; \
677 First = 0
679 NEXT_WIDE_CHAR (first);
681 while (--width > 0);
683 if (!(flags & SUPPRESS))
684 ++done;
686 break;
688 case 's': /* Read a string. */
689 if (flags & LONG)
690 /* We have to process a wide character string. */
691 goto wide_char_string;
693 #define STRING_ARG(Str, Type) \
694 if (!(flags & SUPPRESS)) \
696 if (flags & MALLOC) \
698 /* The string is to be stored in a malloc'd buffer. */ \
699 strptr = ARG (char **); \
700 if (strptr == NULL) \
701 conv_error (); \
702 /* Allocate an initial buffer. */ \
703 strsize = 100; \
704 *strptr = malloc (strsize * sizeof (Type)); \
705 Str = (Type *) *strptr; \
707 else \
708 Str = ARG (Type *); \
709 if (Str == NULL) \
710 conv_error (); \
712 STRING_ARG (str, char);
714 c = inchar ();
715 if (c == EOF)
716 input_error ();
720 if (isspace (c))
722 ungetc (c, s);
723 break;
725 #define STRING_ADD_CHAR(Str, c, Type) \
726 if (!(flags & SUPPRESS)) \
728 *Str++ = c; \
729 if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \
731 /* Enlarge the buffer. */ \
732 Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \
733 if (Str == NULL) \
735 /* Can't allocate that much. Last-ditch effort. */\
736 Str = realloc (*strptr, \
737 (strsize + 1) * sizeof (Type)); \
738 if (Str == NULL) \
740 /* We lose. Oh well. \
741 Terminate the string and stop converting, \
742 so at least we don't skip any input. */ \
743 ((Type *) (*strptr))[strsize] = '\0'; \
744 ++done; \
745 conv_error (); \
747 else \
749 *strptr = (char *) Str; \
750 Str = ((Type *) *strptr) + strsize; \
751 ++strsize; \
754 else \
756 *strptr = (char *) Str; \
757 Str = ((Type *) *strptr) + strsize; \
758 strsize *= 2; \
762 STRING_ADD_CHAR (str, c, char);
763 } while ((width <= 0 || --width > 0) && inchar () != EOF);
765 if (!(flags & SUPPRESS))
767 *str = '\0';
768 ++done;
770 break;
772 case 'S':
773 /* Wide character string. */
774 wide_char_string:
776 wint_t val;
777 int first = 1;
778 STRING_ARG (wstr, wchar_t);
782 size_t cnt = 0;
783 NEXT_WIDE_CHAR (first);
785 if (iswspace (val))
787 /* XXX We would have to push back the whole wide char
788 with possibly many bytes. But since scanf does
789 not make a difference for white space characters
790 we can simply push back a simple <SP> which is
791 guaranteed to be in the [:space:] class. */
792 ungetc (' ', s);
793 break;
796 STRING_ADD_CHAR (wstr, val, wchar_t);
797 first = 0;
799 while (width <= 0 || --width > 0);
801 if (!(flags & SUPPRESS))
803 *wstr = L'\0';
804 ++done;
807 break;
809 case 'x': /* Hexadecimal integer. */
810 case 'X': /* Ditto. */
811 base = 16;
812 number_signed = 0;
813 goto number;
815 case 'o': /* Octal integer. */
816 base = 8;
817 number_signed = 0;
818 goto number;
820 case 'u': /* Unsigned decimal integer. */
821 base = 10;
822 number_signed = 0;
823 goto number;
825 case 'd': /* Signed decimal integer. */
826 base = 10;
827 number_signed = 1;
828 goto number;
830 case 'i': /* Generic number. */
831 base = 0;
832 number_signed = 1;
834 number:
835 c = inchar ();
836 if (c == EOF)
837 input_error ();
839 /* Check for a sign. */
840 if (c == '-' || c == '+')
842 ADDW (c);
843 if (width > 0)
844 --width;
845 c = inchar ();
848 /* Look for a leading indication of base. */
849 if (width != 0 && c == '0')
851 if (width > 0)
852 --width;
854 ADDW (c);
855 c = inchar ();
857 if (width != 0 && tolower (c) == 'x')
859 if (base == 0)
860 base = 16;
861 if (base == 16)
863 if (width > 0)
864 --width;
865 c = inchar ();
868 else if (base == 0)
869 base = 8;
872 if (base == 0)
873 base = 10;
875 /* Read the number into workspace. */
876 while (c != EOF && width != 0)
878 if (base == 16 ? !isxdigit (c) :
879 ((!isdigit (c) || c - '0' >= base) &&
880 !((flags & GROUP) && base == 10 && c == thousands)))
881 break;
882 ADDW (c);
883 if (width > 0)
884 --width;
886 c = inchar ();
889 /* The just read character is not part of the number anymore. */
890 ungetc (c, s);
892 if (wpsize == 0 ||
893 (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
894 /* There was no number. */
895 conv_error ();
897 /* Convert the number. */
898 ADDW ('\0');
899 if (flags & LONGDBL)
901 if (number_signed)
902 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
903 else
904 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
906 else
908 if (number_signed)
909 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
910 else
911 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
913 if (wp == tw)
914 conv_error ();
916 if (!(flags & SUPPRESS))
918 if (! number_signed)
920 if (flags & LONGDBL)
921 *ARG (unsigned LONGLONG int *) = num.uq;
922 else if (flags & LONG)
923 *ARG (unsigned long int *) = num.ul;
924 else if (flags & SHORT)
925 *ARG (unsigned short int *)
926 = (unsigned short int) num.ul;
927 else if (flags & CHAR)
928 *ARG (unsigned char *) = (unsigned char) num.ul;
929 else
930 *ARG (unsigned int *) = (unsigned int) num.ul;
932 else
934 if (flags & LONGDBL)
935 *ARG (LONGLONG int *) = num.q;
936 else if (flags & LONG)
937 *ARG (long int *) = num.l;
938 else if (flags & SHORT)
939 *ARG (short int *) = (short int) num.l;
940 else if (flags & CHAR)
941 *ARG (signed char *) = (signed char) num.ul;
942 else
943 *ARG (int *) = (int) num.l;
945 ++done;
947 break;
949 case 'e': /* Floating-point numbers. */
950 case 'E':
951 case 'f':
952 case 'g':
953 case 'G':
954 case 'a':
955 case 'A':
956 c = inchar ();
957 if (c == EOF)
958 input_error ();
960 /* Check for a sign. */
961 if (c == '-' || c == '+')
963 negative = c == '-';
964 if (inchar () == EOF)
965 /* EOF is only an input error before we read any chars. */
966 conv_error ();
967 if (width > 0)
968 --width;
970 else
971 negative = 0;
973 /* Take care for the special arguments "nan" and "inf". */
974 if (tolower (c) == 'n')
976 /* Maybe "nan". */
977 ADDW (c);
978 if (inchar () == EOF || tolower (c) != 'a')
979 input_error ();
980 ADDW (c);
981 if (inchar () == EOF || tolower (c) != 'n')
982 input_error ();
983 ADDW (c);
984 /* It is "nan". */
985 goto scan_float;
987 else if (tolower (c) == 'i')
989 /* Maybe "inf" or "infinity". */
990 ADDW (c);
991 if (inchar () == EOF || tolower (c) != 'n')
992 input_error ();
993 ADDW (c);
994 if (inchar () == EOF || tolower (c) != 'f')
995 input_error ();
996 ADDW (c);
997 /* It is as least "inf". */
998 if (inchar () != EOF)
1000 if (tolower (c) == 'i')
1002 /* No we have to read the rest as well. */
1003 ADDW (c);
1004 if (inchar () == EOF || tolower (c) != 'n')
1005 input_error ();
1006 ADDW (c);
1007 if (inchar () == EOF || tolower (c) != 'i')
1008 input_error ();
1009 ADDW (c);
1010 if (inchar () == EOF || tolower (c) != 't')
1011 input_error ();
1012 ADDW (c);
1013 if (inchar () == EOF || tolower (c) != 'y')
1014 input_error ();
1015 ADDW (c);
1017 else
1018 /* Never mind. */
1019 ungetc (c, s);
1021 goto scan_float;
1024 is_hexa = 0;
1025 exp_char = 'e';
1026 if (c == '0')
1028 ADDW (c);
1029 c = inchar ();
1030 if (tolower (c) == 'x')
1032 /* It is a number in hexadecimal format. */
1033 ADDW (c);
1035 is_hexa = 1;
1036 exp_char = 'p';
1038 /* Grouping is not allowed. */
1039 flags &= ~GROUP;
1040 c = inchar ();
1044 got_dot = got_e = 0;
1047 if (isdigit (c))
1048 ADDW (c);
1049 else if (!got_e && is_hexa && isxdigit (c))
1050 ADDW (c);
1051 else if (got_e && wp[wpsize - 1] == exp_char
1052 && (c == '-' || c == '+'))
1053 ADDW (c);
1054 else if (wpsize > 0 && !got_e && tolower (c) == exp_char)
1056 ADDW (exp_char);
1057 got_e = got_dot = 1;
1059 else if (c == decimal && !got_dot)
1061 ADDW (c);
1062 got_dot = 1;
1064 else if ((flags & GROUP) && c == thousands && !got_dot)
1065 ADDW (c);
1066 else
1068 /* The last read character is not part of the number
1069 anymore. */
1070 ungetc (c, s);
1071 break;
1073 if (width > 0)
1074 --width;
1076 while (width != 0 && inchar () != EOF);
1078 /* Have we read any character? If we try to read a number
1079 in hexadecimal notation and we have read only the `0x'
1080 prefix this is an error. */
1081 if (wpsize == 0 || (is_hexa && wpsize == 2))
1082 conv_error ();
1084 scan_float:
1085 /* Convert the number. */
1086 ADDW ('\0');
1087 if (flags & LONGDBL)
1089 long double d = __strtold_internal (wp, &tw, flags & GROUP);
1090 if (!(flags & SUPPRESS) && tw != wp)
1091 *ARG (long double *) = negative ? -d : d;
1093 else if (flags & LONG)
1095 double d = __strtod_internal (wp, &tw, flags & GROUP);
1096 if (!(flags & SUPPRESS) && tw != wp)
1097 *ARG (double *) = negative ? -d : d;
1099 else
1101 float d = __strtof_internal (wp, &tw, flags & GROUP);
1102 if (!(flags & SUPPRESS) && tw != wp)
1103 *ARG (float *) = negative ? -d : d;
1106 if (tw == wp)
1107 conv_error ();
1109 if (!(flags & SUPPRESS))
1110 ++done;
1111 break;
1113 case '[': /* Character class. */
1114 if (flags & LONG)
1116 STRING_ARG (wstr, wchar_t);
1117 c = '\0'; /* This is to keep gcc quiet. */
1119 else
1121 STRING_ARG (str, char);
1123 c = inchar ();
1124 if (c == EOF)
1125 input_error ();
1128 if (*f == '^')
1130 ++f;
1131 not_in = 1;
1133 else
1134 not_in = 0;
1136 /* Fill WP with byte flags indexed by character.
1137 We will use this flag map for matching input characters. */
1138 if (wpmax < UCHAR_MAX)
1140 wpmax = UCHAR_MAX;
1141 wp = (char *) alloca (wpmax);
1143 memset (wp, 0, UCHAR_MAX);
1145 fc = *f;
1146 if (fc == ']' || fc == '-')
1148 /* If ] or - appears before any char in the set, it is not
1149 the terminator or separator, but the first char in the
1150 set. */
1151 wp[fc] = 1;
1152 ++f;
1155 while ((fc = *f++) != '\0' && fc != ']')
1157 if (fc == '-' && *f != '\0' && *f != ']' &&
1158 (unsigned char) f[-2] <= (unsigned char) *f)
1160 /* Add all characters from the one before the '-'
1161 up to (but not including) the next format char. */
1162 for (fc = f[-2]; fc < *f; ++fc)
1163 wp[fc] = 1;
1165 else
1166 /* Add the character to the flag map. */
1167 wp[fc] = 1;
1169 if (fc == '\0')
1171 if (!(flags & LONG))
1172 ungetc (c, s);
1173 conv_error();
1176 if (flags & LONG)
1178 wint_t val;
1179 int first = 1;
1183 size_t cnt = 0;
1184 NEXT_WIDE_CHAR (first);
1185 if (val <= 255 && wp[val] == not_in)
1187 ungetc (val, s);
1188 break;
1190 STRING_ADD_CHAR (wstr, val, wchar_t);
1191 if (width > 0)
1192 --width;
1193 first = 0;
1195 while (width != 0);
1197 if (first)
1198 conv_error ();
1200 if (!(flags & SUPPRESS))
1202 *wstr = L'\0';
1203 ++done;
1206 else
1208 num.ul = read_in - 1; /* -1 because we already read one char. */
1211 if (wp[c] == not_in)
1213 ungetc (c, s);
1214 break;
1216 STRING_ADD_CHAR (str, c, char);
1217 if (width > 0)
1218 --width;
1220 while (width != 0 && inchar () != EOF);
1222 if (read_in == num.ul)
1223 conv_error ();
1225 if (!(flags & SUPPRESS))
1227 *str = '\0';
1228 ++done;
1231 break;
1233 case 'p': /* Generic pointer. */
1234 base = 16;
1235 /* A PTR must be the same size as a `long int'. */
1236 flags &= ~(SHORT|LONGDBL);
1237 flags |= LONG;
1238 number_signed = 0;
1239 goto number;
1243 /* The last thing we saw int the format string was a white space.
1244 Consume the last white spaces. */
1245 if (skip_space)
1248 c = inchar ();
1249 while (isspace (c));
1250 ungetc (c, s);
1253 /* Unlock stream. */
1254 UNLOCK_STREAM (s);
1256 return done;
1259 #ifdef USE_IN_LIBIO
1261 __vfscanf (FILE *s, const char *format, va_list argptr)
1263 return _IO_vfscanf (s, format, argptr, NULL);
1265 #endif
1267 weak_alias (__vfscanf, vfscanf)