Regenerated: autoconf configure.in
[glibc/history.git] / stdio-common / vfscanf.c
blobbce319eeaf3dae09432a27935a42c05c7adf132f
1 /* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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 "../locale/localeinfo.h"
20 #include <errno.h>
21 #include <limits.h>
22 #include <ctype.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <wctype.h>
28 #include <bits/libc-lock.h>
30 #ifdef __GNUC__
31 #define HAVE_LONGLONG
32 #define LONGLONG long long
33 #else
34 #define LONGLONG long
35 #endif
37 /* Those are flags in the conversion format. */
38 # define LONG 0x001 /* l: long or double */
39 # define LONGDBL 0x002 /* L: long long or long double */
40 # define SHORT 0x004 /* h: short */
41 # define SUPPRESS 0x008 /* *: suppress assignment */
42 # define POINTER 0x010 /* weird %p pointer (`fake hex') */
43 # define NOSKIP 0x020 /* do not skip blanks */
44 # define WIDTH 0x040 /* width was given */
45 # define GROUP 0x080 /* ': group numbers */
46 # define MALLOC 0x100 /* a: malloc strings */
48 # define TYPEMOD (LONG|LONGDBL|SHORT)
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 && --read_in), \
58 _IO_ungetc (c, s))
59 # define inchar() ((c = _IO_getc_unlocked (s)), \
60 (void) (c != EOF && ++read_in), c)
61 # define encode_error() do { \
62 if (errp != NULL) *errp |= 4; \
63 _IO_funlockfile (s); \
64 __set_errno (EILSEQ); \
65 return done; \
66 } while (0)
67 # define conv_error() do { \
68 if (errp != NULL) *errp |= 2; \
69 _IO_funlockfile (s); \
70 return done; \
71 } while (0)
72 # define input_error() do { \
73 _IO_funlockfile (s); \
74 if (errp != NULL) *errp |= 1; \
75 return done ?: EOF; \
76 } while (0)
77 # define memory_error() do { \
78 _IO_funlockfile (s); \
79 __set_errno (ENOMEM); \
80 return EOF; \
81 } while (0)
82 # define ARGCHECK(s, format) \
83 do \
84 { \
85 /* Check file argument for consistence. */ \
86 CHECK_FILE (s, EOF); \
87 if (s->_flags & _IO_NO_READS) \
88 { \
89 __set_errno (EBADF); \
90 return EOF; \
91 } \
92 else if (format == NULL) \
93 { \
94 MAYBE_SET_EINVAL; \
95 return EOF; \
96 } \
97 } while (0)
98 # define LOCK_STREAM(S) \
99 __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \
100 _IO_flockfile (S)
101 # define UNLOCK_STREAM __libc_cleanup_region_end (1)
102 #else
103 # define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s))
104 # define inchar() ((c = getc (s)), (void) (c != EOF && ++read_in), c)
105 # define encode_error() do { \
106 funlockfile (s); \
107 __set_errno (EILSEQ); \
108 return done; \
109 } while (0)
110 # define conv_error() do { \
111 funlockfile (s); \
112 return done; \
113 } while (0)
114 # define input_error() do { \
115 funlockfile (s); \
116 return done ?: EOF; \
117 } while (0)
118 # define memory_error() do { \
119 funlockfile (s); \
120 __set_errno (ENOMEM); \
121 return EOF; \
122 } while (0)
123 # define ARGCHECK(s, format) \
124 do \
126 /* Check file argument for consistence. */ \
127 if (!__validfp (s) || !s->__mode.__read) \
129 __set_errno (EBADF); \
130 return EOF; \
132 else if (format == NULL) \
134 __set_errno (EINVAL); \
135 return EOF; \
137 } while (0)
138 #if 1
139 /* XXX For now !!! */
140 # define flockfile(S) /* nothing */
141 # define funlockfile(S) /* nothing */
142 # define LOCK_STREAM(S)
143 # define UNLOCK_STREAM
144 #else
145 # define LOCK_STREAM(S) \
146 __libc_cleanup_region_start (&__funlockfile, (S)); \
147 __flockfile (S)
148 # define UNLOCK_STREAM __libc_cleanup_region_end (1)
149 #endif
150 #endif
153 /* Read formatted input from S according to the format string
154 FORMAT, using the argument list in ARG.
155 Return the number of assignments made, or -1 for an input error. */
156 #ifdef USE_IN_LIBIO
158 _IO_vfscanf (s, format, argptr, errp)
159 _IO_FILE *s;
160 const char *format;
161 _IO_va_list argptr;
162 int *errp;
163 #else
165 __vfscanf (FILE *s, const char *format, va_list argptr)
166 #endif
168 va_list arg;
169 register const char *f = format;
170 register unsigned char fc; /* Current character of the format. */
171 register size_t done = 0; /* Assignments done. */
172 register size_t read_in = 0; /* Chars read in. */
173 register int c = 0; /* Last char read. */
174 register int width; /* Maximum field width. */
175 register int flags; /* Modifiers for current format element. */
177 /* Status for reading F-P nums. */
178 char got_dot, got_e, negative;
179 /* If a [...] is a [^...]. */
180 char not_in;
181 #define exp_char not_in
182 /* Base for integral numbers. */
183 int base;
184 /* Signedness for integral numbers. */
185 int number_signed;
186 #define is_hexa number_signed
187 /* Decimal point character. */
188 wchar_t decimal;
189 /* The thousands character of the current locale. */
190 wchar_t thousands;
191 /* Integral holding variables. */
192 union
194 long long int q;
195 unsigned long long int uq;
196 long int l;
197 unsigned long int ul;
198 } num;
199 /* Character-buffer pointer. */
200 char *str = NULL;
201 wchar_t *wstr = NULL;
202 char **strptr = NULL;
203 size_t strsize = 0;
204 /* We must not react on white spaces immediately because they can
205 possibly be matched even if in the input stream no character is
206 available anymore. */
207 int skip_space = 0;
208 /* Workspace. */
209 char *tw; /* Temporary pointer. */
210 char *wp = NULL; /* Workspace. */
211 size_t wpmax = 0; /* Maximal size of workspace. */
212 size_t wpsize; /* Currently used bytes in workspace. */
213 #define ADDW(Ch) \
214 do \
216 if (wpsize == wpmax) \
218 char *old = wp; \
219 wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \
220 wp = (char *) alloca (wpmax); \
221 if (old != NULL) \
222 memcpy (wp, old, wpsize); \
224 wp[wpsize++] = (Ch); \
226 while (0)
228 #ifdef __va_copy
229 __va_copy (arg, argptr);
230 #else
231 arg = (va_list) argptr;
232 #endif
234 ARGCHECK (s, format);
236 /* Figure out the decimal point character. */
237 if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
238 strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
239 decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
240 /* Figure out the thousands separator character. */
241 if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
242 strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
243 thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
245 /* Lock the stream. */
246 LOCK_STREAM (s);
248 /* Run through the format string. */
249 while (*f != '\0')
251 unsigned int argpos;
252 /* Extract the next argument, which is of type TYPE.
253 For a %N$... spec, this is the Nth argument from the beginning;
254 otherwise it is the next argument after the state now in ARG. */
255 #ifdef __va_copy
256 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
257 ({ unsigned int pos = argpos; \
258 va_list arg; \
259 __va_copy (arg, argptr); \
260 while (--pos > 0) \
261 (void) va_arg (arg, void *); \
262 va_arg (arg, type); \
264 #else
265 # if 0
266 /* XXX Possible optimization. */
267 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
268 ({ va_list arg = (va_list) argptr; \
269 arg = (va_list) ((char *) arg \
270 + (argpos - 1) \
271 * __va_rounded_size (void *)); \
272 va_arg (arg, type); \
274 # else
275 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
276 ({ unsigned int pos = argpos; \
277 va_list arg = (va_list) argptr; \
278 while (--pos > 0) \
279 (void) va_arg (arg, void *); \
280 va_arg (arg, type); \
282 # endif
283 #endif
285 if (!isascii (*f))
287 /* Non-ASCII, may be a multibyte. */
288 int len = mblen (f, strlen (f));
289 if (len > 0)
293 c = inchar ();
294 if (c == EOF)
295 input_error ();
296 else if (c != *f++)
298 ungetc (c, s);
299 conv_error ();
302 while (--len > 0);
303 continue;
307 fc = *f++;
308 if (fc != '%')
310 /* Remember to skip spaces. */
311 if (isspace (fc))
313 skip_space = 1;
314 continue;
317 /* Read a character. */
318 c = inchar ();
320 /* Characters other than format specs must just match. */
321 if (c == EOF)
322 input_error ();
324 /* We saw white space char as the last character in the format
325 string. Now it's time to skip all leading white space. */
326 if (skip_space)
328 while (isspace (c))
329 if (inchar () == EOF && errno == EINTR)
330 conv_error ();
331 skip_space = 0;
334 if (c != fc)
336 ungetc (c, s);
337 conv_error ();
340 continue;
343 /* This is the start of the conversion string. */
344 flags = 0;
346 /* Initialize state of modifiers. */
347 argpos = 0;
349 /* Prepare temporary buffer. */
350 wpsize = 0;
352 /* Check for a positional parameter specification. */
353 if (isdigit (*f))
355 argpos = *f++ - '0';
356 while (isdigit (*f))
357 argpos = argpos * 10 + (*f++ - '0');
358 if (*f == '$')
359 ++f;
360 else
362 /* Oops; that was actually the field width. */
363 width = argpos;
364 flags |= WIDTH;
365 argpos = 0;
366 goto got_width;
370 /* Check for the assignment-suppressing and the number grouping flag. */
371 while (*f == '*' || *f == '\'')
372 switch (*f++)
374 case '*':
375 flags |= SUPPRESS;
376 break;
377 case '\'':
378 flags |= GROUP;
379 break;
382 /* We have seen width. */
383 if (isdigit (*f))
384 flags |= WIDTH;
386 /* Find the maximum field width. */
387 width = 0;
388 while (isdigit (*f))
390 width *= 10;
391 width += *f++ - '0';
393 got_width:
394 if (width == 0)
395 width = -1;
397 /* Check for type modifiers. */
398 while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
399 switch (*f++)
401 case 'h':
402 /* int's are short int's. */
403 if (flags & TYPEMOD)
404 /* Signal illegal format element. */
405 conv_error ();
406 flags |= SHORT;
407 break;
408 case 'l':
409 if (flags & (SHORT|LONGDBL))
410 conv_error ();
411 else if (flags & LONG)
413 /* A double `l' is equivalent to an `L'. */
414 flags &= ~LONG;
415 flags |= LONGDBL;
417 else
418 /* int's are long int's. */
419 flags |= LONG;
420 break;
421 case 'q':
422 case 'L':
423 /* double's are long double's, and int's are long long int's. */
424 if (flags & TYPEMOD)
425 /* Signal illegal format element. */
426 conv_error ();
427 flags |= LONGDBL;
428 break;
429 case 'a':
430 if (flags & TYPEMOD)
431 /* Signal illegal format element. */
432 conv_error ();
433 /* String conversions (%s, %[) take a `char **'
434 arg and fill it in with a malloc'd pointer. */
435 flags |= MALLOC;
436 break;
439 /* End of the format string? */
440 if (*f == '\0')
441 conv_error ();
443 /* We must take care for EINTR errors. */
444 if (c == EOF && errno == EINTR)
445 input_error ();
447 /* Find the conversion specifier. */
448 fc = *f++;
449 if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
451 /* Eat whitespace. */
453 if (inchar () == EOF && errno == EINTR)
454 input_error ();
455 while (isspace (c));
456 ungetc (c, s);
457 skip_space = 0;
460 switch (fc)
462 case '%': /* Must match a literal '%'. */
463 c = inchar ();
464 if (c != fc)
466 ungetc (c, s);
467 conv_error ();
469 break;
471 case 'n': /* Answer number of assignments done. */
472 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
473 with the 'n' conversion specifier. */
474 if (!(flags & SUPPRESS))
476 /* Don't count the read-ahead. */
477 if (flags & LONGDBL)
478 *ARG (long long int *) = read_in;
479 else if (flags & LONG)
480 *ARG (long int *) = read_in;
481 else if (flags & SHORT)
482 *ARG (short int *) = read_in;
483 else
484 *ARG (int *) = read_in;
486 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
487 /* We have a severe problem here. The ISO C standard
488 contradicts itself in explaining the effect of the %n
489 format in `scanf'. While in ISO C:1990 and the ISO C
490 Amendement 1:1995 the result is described as
492 Execution of a %n directive does not effect the
493 assignment count returned at the completion of
494 execution of the f(w)scanf function.
496 in ISO C Corrigendum 1:1994 the following was added:
498 Subclause 7.9.6.2
499 Add the following fourth example:
501 #include <stdio.h>
502 int d1, d2, n1, n2, i;
503 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
504 the value 123 is assigned to d1 and the value3 to n1.
505 Because %n can never get an input failure the value
506 of 3 is also assigned to n2. The value of d2 is not
507 affected. The value 3 is assigned to i.
509 We go for now with the historically correct code fro ISO C,
510 i.e., we don't count the %n assignments. When it ever
511 should proof to be wrong just remove the #ifdef above. */
512 ++done;
513 #endif
515 break;
517 case 'c': /* Match characters. */
518 if ((flags & LONG) == 0)
520 if (!(flags & SUPPRESS))
522 str = ARG (char *);
523 if (str == NULL)
524 conv_error ();
527 c = inchar ();
528 if (c == EOF)
529 input_error ();
531 if (width == -1)
532 width = 1;
534 if (!(flags & SUPPRESS))
537 *str++ = c;
538 while (--width > 0 && inchar () != EOF);
540 else
541 while (--width > 0 && inchar () != EOF);
543 if (width > 0)
544 /* I.e., EOF was read. */
545 --read_in;
547 if (!(flags & SUPPRESS))
548 ++done;
550 break;
552 /* FALLTHROUGH */
553 case 'C':
554 /* Get UTF-8 encoded wide character. Here we assume (as in
555 other parts of the libc) that we only have to handle
556 UTF-8. */
558 wint_t val;
559 size_t cnt = 0;
560 int first = 1;
562 if (!(flags & SUPPRESS))
564 wstr = ARG (wchar_t *);
565 if (str == NULL)
566 conv_error ();
571 #define NEXT_WIDE_CHAR(First) \
572 c = inchar (); \
573 if (c == EOF) \
574 /* EOF is only an error for the first character. */ \
575 if (First) \
576 input_error (); \
577 else \
579 --read_in; \
580 break; \
582 val = c; \
583 if (val >= 0x80) \
585 if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
586 encode_error (); \
587 if ((c & 0xe0) == 0xc0) \
589 /* We expect two bytes. */ \
590 cnt = 1; \
591 val &= 0x1f; \
593 else if ((c & 0xf0) == 0xe0) \
595 /* We expect three bytes. */ \
596 cnt = 2; \
597 val &= 0x0f; \
599 else if ((c & 0xf8) == 0xf0) \
601 /* We expect four bytes. */ \
602 cnt = 3; \
603 val &= 0x07; \
605 else if ((c & 0xfc) == 0xf8) \
607 /* We expect five bytes. */ \
608 cnt = 4; \
609 val &= 0x03; \
611 else \
613 /* We expect six bytes. */ \
614 cnt = 5; \
615 val &= 0x01; \
618 do \
620 c = inchar (); \
621 if (c == EOF \
622 || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
623 encode_error (); \
624 val <<= 6; \
625 val |= c & 0x3f; \
627 while (--cnt > 0); \
630 if (!(flags & SUPPRESS)) \
631 *wstr++ = val; \
632 first = 0
634 NEXT_WIDE_CHAR (first);
636 while (--width > 0);
638 if (width > 0)
639 /* I.e., EOF was read. */
640 --read_in;
642 if (!(flags & SUPPRESS))
643 ++done;
645 break;
647 case 's': /* Read a string. */
648 if (flags & LONG)
649 /* We have to process a wide character string. */
650 goto wide_char_string;
652 #define STRING_ARG(Str, Type) \
653 if (!(flags & SUPPRESS)) \
655 if (flags & MALLOC) \
657 /* The string is to be stored in a malloc'd buffer. */ \
658 strptr = ARG (char **); \
659 if (strptr == NULL) \
660 conv_error (); \
661 /* Allocate an initial buffer. */ \
662 strsize = 100; \
663 *strptr = malloc (strsize * sizeof (Type)); \
664 Str = (Type *) *strptr; \
666 else \
667 Str = ARG (Type *); \
668 if (Str == NULL) \
669 conv_error (); \
671 STRING_ARG (str, char);
673 c = inchar ();
674 if (c == EOF)
675 input_error ();
679 if (isspace (c))
681 ungetc (c, s);
682 break;
684 #define STRING_ADD_CHAR(Str, c, Type) \
685 if (!(flags & SUPPRESS)) \
687 *Str++ = c; \
688 if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \
690 /* Enlarge the buffer. */ \
691 Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \
692 if (Str == NULL) \
694 /* Can't allocate that much. Last-ditch effort. */\
695 Str = realloc (*strptr, \
696 (strsize + 1) * sizeof (Type)); \
697 if (Str == NULL) \
699 /* We lose. Oh well. \
700 Terminate the string and stop converting, \
701 so at least we don't skip any input. */ \
702 ((Type *) (*strptr))[strsize] = '\0'; \
703 ++done; \
704 conv_error (); \
706 else \
708 *strptr = (char *) Str; \
709 Str = ((Type *) *strptr) + strsize; \
710 ++strsize; \
713 else \
715 *strptr = (char *) Str; \
716 Str = ((Type *) *strptr) + strsize; \
717 strsize *= 2; \
721 STRING_ADD_CHAR (str, c, char);
722 } while ((width <= 0 || --width > 0) && inchar () != EOF);
724 if (!(flags & SUPPRESS))
726 *str = '\0';
727 ++done;
729 break;
731 case 'S':
732 /* Wide character string. */
733 wide_char_string:
735 wint_t val;
736 int first = 1;
737 STRING_ARG (wstr, wchar_t);
741 size_t cnt = 0;
742 NEXT_WIDE_CHAR (first);
744 if (iswspace (val))
746 /* XXX We would have to push back the whole wide char
747 with possibly many bytes. But since scanf does
748 not make a difference for white space characters
749 we can simply push back a simple <SP> which is
750 guaranteed to be in the [:space:] class. */
751 ungetc (' ', s);
752 break;
755 STRING_ADD_CHAR (wstr, val, wchar_t);
756 first = 0;
758 while (width <= 0 || --width > 0);
760 if (!(flags & SUPPRESS))
762 *wstr = L'\0';
763 ++done;
766 break;
768 case 'x': /* Hexadecimal integer. */
769 case 'X': /* Ditto. */
770 base = 16;
771 number_signed = 0;
772 goto number;
774 case 'o': /* Octal integer. */
775 base = 8;
776 number_signed = 0;
777 goto number;
779 case 'u': /* Unsigned decimal integer. */
780 base = 10;
781 number_signed = 0;
782 goto number;
784 case 'd': /* Signed decimal integer. */
785 base = 10;
786 number_signed = 1;
787 goto number;
789 case 'i': /* Generic number. */
790 base = 0;
791 number_signed = 1;
793 number:
794 c = inchar ();
795 if (c == EOF)
796 input_error ();
798 /* Check for a sign. */
799 if (c == '-' || c == '+')
801 ADDW (c);
802 if (width > 0)
803 --width;
804 c = inchar ();
807 /* Look for a leading indication of base. */
808 if (width != 0 && c == '0')
810 if (width > 0)
811 --width;
813 ADDW (c);
814 c = inchar ();
816 if (width != 0 && tolower (c) == 'x')
818 if (base == 0)
819 base = 16;
820 if (base == 16)
822 if (width > 0)
823 --width;
824 c = inchar ();
827 else if (base == 0)
828 base = 8;
831 if (base == 0)
832 base = 10;
834 /* Read the number into workspace. */
835 while (c != EOF && width != 0)
837 if (base == 16 ? !isxdigit (c) :
838 ((!isdigit (c) || c - '0' >= base) &&
839 !((flags & GROUP) && base == 10 && c == thousands)))
840 break;
841 ADDW (c);
842 if (width > 0)
843 --width;
845 c = inchar ();
848 /* The just read character is not part of the number anymore. */
849 ungetc (c, s);
851 if (wpsize == 0 ||
852 (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
853 /* There was no number. */
854 conv_error ();
856 /* Convert the number. */
857 ADDW ('\0');
858 if (flags & LONGDBL)
860 if (number_signed)
861 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
862 else
863 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
865 else
867 if (number_signed)
868 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
869 else
870 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
872 if (wp == tw)
873 conv_error ();
875 if (!(flags & SUPPRESS))
877 if (! number_signed)
879 if (flags & LONGDBL)
880 *ARG (unsigned LONGLONG int *) = num.uq;
881 else if (flags & LONG)
882 *ARG (unsigned long int *) = num.ul;
883 else if (flags & SHORT)
884 *ARG (unsigned short int *)
885 = (unsigned short int) num.ul;
886 else
887 *ARG (unsigned int *) = (unsigned int) num.ul;
889 else
891 if (flags & LONGDBL)
892 *ARG (LONGLONG int *) = num.q;
893 else if (flags & LONG)
894 *ARG (long int *) = num.l;
895 else if (flags & SHORT)
896 *ARG (short int *) = (short int) num.l;
897 else
898 *ARG (int *) = (int) num.l;
900 ++done;
902 break;
904 case 'e': /* Floating-point numbers. */
905 case 'E':
906 case 'f':
907 case 'g':
908 case 'G':
909 case 'A':
910 c = inchar ();
911 if (c == EOF)
912 input_error ();
914 /* Check for a sign. */
915 if (c == '-' || c == '+')
917 negative = c == '-';
918 if (inchar () == EOF)
919 /* EOF is only an input error before we read any chars. */
920 conv_error ();
921 if (width > 0)
922 --width;
924 else
925 negative = 0;
927 is_hexa = 0;
928 exp_char = 'e';
929 if (c == '0')
931 ADDW (c);
932 c = inchar ();
933 if (tolower (c) == 'x')
935 /* It is a number in hexadecimal format. */
936 ADDW (c);
938 is_hexa = 1;
939 exp_char = 'p';
941 /* Grouping is not allowed. */
942 flags &= ~GROUP;
943 c = inchar ();
947 got_dot = got_e = 0;
950 if (isdigit (c))
951 ADDW (c);
952 else if (!got_e && is_hexa && isxdigit (c))
953 ADDW (c);
954 else if (got_e && wp[wpsize - 1] == exp_char
955 && (c == '-' || c == '+'))
956 ADDW (c);
957 else if (wpsize > 0 && !got_e && tolower (c) == exp_char)
959 ADDW (exp_char);
960 got_e = got_dot = 1;
962 else if (c == decimal && !got_dot)
964 ADDW (c);
965 got_dot = 1;
967 else if ((flags & GROUP) && c == thousands && !got_dot)
968 ADDW (c);
969 else
971 /* The last read character is not part of the number
972 anymore. */
973 ungetc (c, s);
974 break;
976 if (width > 0)
977 --width;
979 while (width != 0 && inchar () != EOF);
981 /* Have we read any character? If we try to read a number
982 in hexadecimal notation and we have read only the `0x'
983 prefix this is an error. */
984 if (wpsize == 0 || (is_hexa && wpsize == 2))
985 conv_error ();
987 /* Convert the number. */
988 ADDW ('\0');
989 if (flags & LONGDBL)
991 long double d = __strtold_internal (wp, &tw, flags & GROUP);
992 if (!(flags & SUPPRESS) && tw != wp)
993 *ARG (long double *) = negative ? -d : d;
995 else if (flags & LONG)
997 double d = __strtod_internal (wp, &tw, flags & GROUP);
998 if (!(flags & SUPPRESS) && tw != wp)
999 *ARG (double *) = negative ? -d : d;
1001 else
1003 float d = __strtof_internal (wp, &tw, flags & GROUP);
1004 if (!(flags & SUPPRESS) && tw != wp)
1005 *ARG (float *) = negative ? -d : d;
1008 if (tw == wp)
1009 conv_error ();
1011 if (!(flags & SUPPRESS))
1012 ++done;
1013 break;
1015 case '[': /* Character class. */
1016 if (flags & LONG)
1018 STRING_ARG (wstr, wchar_t);
1019 c = '\0'; /* This is to keep gcc quiet. */
1021 else
1023 STRING_ARG (str, char);
1025 c = inchar ();
1026 if (c == EOF)
1027 input_error ();
1030 if (*f == '^')
1032 ++f;
1033 not_in = 1;
1035 else
1036 not_in = 0;
1038 /* Fill WP with byte flags indexed by character.
1039 We will use this flag map for matching input characters. */
1040 if (wpmax < UCHAR_MAX)
1042 wpmax = UCHAR_MAX;
1043 wp = (char *) alloca (wpmax);
1045 memset (wp, 0, UCHAR_MAX);
1047 fc = *f;
1048 if (fc == ']' || fc == '-')
1050 /* If ] or - appears before any char in the set, it is not
1051 the terminator or separator, but the first char in the
1052 set. */
1053 wp[fc] = 1;
1054 ++f;
1057 while ((fc = *f++) != '\0' && fc != ']')
1059 if (fc == '-' && *f != '\0' && *f != ']' &&
1060 (unsigned char) f[-2] <= (unsigned char) *f)
1062 /* Add all characters from the one before the '-'
1063 up to (but not including) the next format char. */
1064 for (fc = f[-2]; fc < *f; ++fc)
1065 wp[fc] = 1;
1067 else
1068 /* Add the character to the flag map. */
1069 wp[fc] = 1;
1071 if (fc == '\0')
1073 if (!(flags & LONG))
1074 ungetc (c, s);
1075 conv_error();
1078 if (flags & LONG)
1080 wint_t val;
1081 int first = 1;
1085 size_t cnt = 0;
1086 NEXT_WIDE_CHAR (first);
1087 if (val > 255 || wp[val] == not_in)
1089 /* XXX We have a problem here. We read a wide
1090 character and this possibly took several
1091 bytes. But we can only push back one single
1092 character. To be sure we don't create wrong
1093 input we push it back only in case it is
1094 representable within one byte. */
1095 if (val < 0x80)
1096 ungetc (val, s);
1097 break;
1099 STRING_ADD_CHAR (wstr, val, wchar_t);
1100 if (width > 0)
1101 --width;
1102 first = 0;
1104 while (width != 0);
1106 if (first)
1107 conv_error ();
1109 if (!(flags & SUPPRESS))
1111 *wstr = L'\0';
1112 ++done;
1115 else
1117 num.ul = read_in - 1; /* -1 because we already read one char. */
1120 if (wp[c] == not_in)
1122 ungetc (c, s);
1123 break;
1125 STRING_ADD_CHAR (str, c, char);
1126 if (width > 0)
1127 --width;
1129 while (width != 0 && inchar () != EOF);
1131 if (read_in == num.ul)
1132 conv_error ();
1134 if (!(flags & SUPPRESS))
1136 *str = '\0';
1137 ++done;
1140 break;
1142 case 'p': /* Generic pointer. */
1143 base = 16;
1144 /* A PTR must be the same size as a `long int'. */
1145 flags &= ~(SHORT|LONGDBL);
1146 flags |= LONG;
1147 number_signed = 0;
1148 goto number;
1152 /* The last thing we saw int the format string was a white space.
1153 Consume the last white spaces. */
1154 if (skip_space)
1157 c = inchar ();
1158 while (isspace (c));
1159 ungetc (c, s);
1162 /* Unlock stream. */
1163 UNLOCK_STREAM;
1165 return done;
1168 #ifdef USE_IN_LIBIO
1170 __vfscanf (FILE *s, const char *format, va_list argptr)
1172 return _IO_vfscanf (s, format, argptr, NULL);
1174 #endif
1176 weak_alias (__vfscanf, vfscanf)