Regenerated: autoconf configure.in
[glibc.git] / stdio-common / vfscanf.c
blobbd167b9a5bc83ea1296f10476806ed56aa144d7e
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 <stdlib.h>
25 #include <string.h>
26 #include <wctype.h>
27 #include <bits/libc-lock.h>
28 #include <locale/localeinfo.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 */
47 # define CHAR 0x200 /* hh: char */
49 # define TYPEMOD (LONG|LONGDBL|SHORT|CHAR)
52 #ifdef USE_IN_LIBIO
53 # include <libioP.h>
54 # include <libio.h>
56 # undef va_list
57 # define va_list _IO_va_list
58 # define ungetc(c, s) ((void) ((int) c == EOF \
59 || (--read_in, \
60 _IO_sputbackc (s, (unsigned char) c))))
61 # define inchar() (c == EOF ? EOF \
62 : ((c = _IO_getc_unlocked (s)), \
63 (void) (c != EOF && ++read_in), c))
64 # define encode_error() do { \
65 if (errp != NULL) *errp |= 4; \
66 _IO_funlockfile (s); \
67 __libc_cleanup_end (0); \
68 __set_errno (EILSEQ); \
69 return done; \
70 } while (0)
71 # define conv_error() do { \
72 if (errp != NULL) *errp |= 2; \
73 _IO_funlockfile (s); \
74 __libc_cleanup_end (0); \
75 return done; \
76 } while (0)
77 # define input_error() do { \
78 _IO_funlockfile (s); \
79 if (errp != NULL) *errp |= 1; \
80 __libc_cleanup_end (0); \
81 return done ?: EOF; \
82 } while (0)
83 # define memory_error() do { \
84 _IO_funlockfile (s); \
85 __set_errno (ENOMEM); \
86 __libc_cleanup_end (0); \
87 return EOF; \
88 } while (0)
89 # define ARGCHECK(s, format) \
90 do \
91 { \
92 /* Check file argument for consistence. */ \
93 CHECK_FILE (s, EOF); \
94 if (s->_flags & _IO_NO_READS) \
95 { \
96 __set_errno (EBADF); \
97 return EOF; \
98 } \
99 else if (format == NULL) \
101 MAYBE_SET_EINVAL; \
102 return EOF; \
104 } while (0)
105 # define LOCK_STREAM(S) \
106 __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \
107 _IO_flockfile (S)
108 # define UNLOCK_STREAM(S) \
109 _IO_funlockfile (S); \
110 __libc_cleanup_region_end (0)
111 #else
112 # define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s))
113 # define inchar() (c == EOF ? EOF \
114 : ((c = getc (s)), (void) (c != EOF && ++read_in), c))
115 # define encode_error() do { \
116 funlockfile (s); \
117 __set_errno (EILSEQ); \
118 return done; \
119 } while (0)
120 # define conv_error() do { \
121 funlockfile (s); \
122 return done; \
123 } while (0)
124 # define input_error() do { \
125 funlockfile (s); \
126 return done ?: EOF; \
127 } while (0)
128 # define memory_error() do { \
129 funlockfile (s); \
130 __set_errno (ENOMEM); \
131 return EOF; \
132 } while (0)
133 # define ARGCHECK(s, format) \
134 do \
136 /* Check file argument for consistence. */ \
137 if (!__validfp (s) || !s->__mode.__read) \
139 __set_errno (EBADF); \
140 return EOF; \
142 else if (format == NULL) \
144 __set_errno (EINVAL); \
145 return EOF; \
147 } while (0)
148 #if 1
149 /* XXX For now !!! */
150 # define flockfile(S) /* nothing */
151 # define funlockfile(S) /* nothing */
152 # define LOCK_STREAM(S)
153 # define UNLOCK_STREAM(S)
154 #else
155 # define LOCK_STREAM(S) \
156 __libc_cleanup_region_start (&__funlockfile, (S)); \
157 __flockfile (S)
158 # define UNLOCK_STREAM(S) \
159 __funlockfile (S); \
160 __libc_cleanup_region_end (0)
161 #endif
162 #endif
165 /* Read formatted input from S according to the format string
166 FORMAT, using the argument list in ARG.
167 Return the number of assignments made, or -1 for an input error. */
168 #ifdef USE_IN_LIBIO
170 _IO_vfscanf (s, format, argptr, errp)
171 _IO_FILE *s;
172 const char *format;
173 _IO_va_list argptr;
174 int *errp;
175 #else
177 __vfscanf (FILE *s, const char *format, va_list argptr)
178 #endif
180 va_list arg;
181 register const char *f = format;
182 register unsigned char fc; /* Current character of the format. */
183 register size_t done = 0; /* Assignments done. */
184 register size_t read_in = 0; /* Chars read in. */
185 register int c = 0; /* Last char read. */
186 register int width; /* Maximum field width. */
187 register int flags; /* Modifiers for current format element. */
189 /* Status for reading F-P nums. */
190 char got_dot, got_e, negative;
191 /* If a [...] is a [^...]. */
192 char not_in;
193 #define exp_char not_in
194 /* Base for integral numbers. */
195 int base;
196 /* Signedness for integral numbers. */
197 int number_signed;
198 #define is_hexa number_signed
199 /* Decimal point character. */
200 wchar_t decimal;
201 /* The thousands character of the current locale. */
202 wchar_t thousands;
203 /* Integral holding variables. */
204 union
206 long long int q;
207 unsigned long long int uq;
208 long int l;
209 unsigned long int ul;
210 } num;
211 /* Character-buffer pointer. */
212 char *str = NULL;
213 wchar_t *wstr = NULL;
214 char **strptr = NULL;
215 size_t strsize = 0;
216 /* We must not react on white spaces immediately because they can
217 possibly be matched even if in the input stream no character is
218 available anymore. */
219 int skip_space = 0;
220 /* Workspace. */
221 char *tw; /* Temporary pointer. */
222 char *wp = NULL; /* Workspace. */
223 size_t wpmax = 0; /* Maximal size of workspace. */
224 size_t wpsize; /* Currently used bytes in workspace. */
225 #define ADDW(Ch) \
226 do \
228 if (wpsize == wpmax) \
230 char *old = wp; \
231 wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \
232 wp = (char *) alloca (wpmax); \
233 if (old != NULL) \
234 memcpy (wp, old, wpsize); \
236 wp[wpsize++] = (Ch); \
238 while (0)
240 #ifdef __va_copy
241 __va_copy (arg, argptr);
242 #else
243 arg = (va_list) argptr;
244 #endif
246 ARGCHECK (s, format);
248 /* Figure out the decimal point character. */
249 if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
250 strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
251 decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
252 /* Figure out the thousands separator character. */
253 if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
254 strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
255 thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
257 /* Lock the stream. */
258 LOCK_STREAM (s);
260 /* Run through the format string. */
261 while (*f != '\0')
263 unsigned int argpos;
264 /* Extract the next argument, which is of type TYPE.
265 For a %N$... spec, this is the Nth argument from the beginning;
266 otherwise it is the next argument after the state now in ARG. */
267 #ifdef __va_copy
268 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
269 ({ unsigned int pos = argpos; \
270 va_list arg; \
271 __va_copy (arg, argptr); \
272 while (--pos > 0) \
273 (void) va_arg (arg, void *); \
274 va_arg (arg, type); \
276 #else
277 # if 0
278 /* XXX Possible optimization. */
279 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
280 ({ va_list arg = (va_list) argptr; \
281 arg = (va_list) ((char *) arg \
282 + (argpos - 1) \
283 * __va_rounded_size (void *)); \
284 va_arg (arg, type); \
286 # else
287 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
288 ({ unsigned int pos = argpos; \
289 va_list arg = (va_list) argptr; \
290 while (--pos > 0) \
291 (void) va_arg (arg, void *); \
292 va_arg (arg, type); \
294 # endif
295 #endif
297 if (!isascii (*f))
299 /* Non-ASCII, may be a multibyte. */
300 int len = mblen (f, strlen (f));
301 if (len > 0)
305 c = inchar ();
306 if (c == EOF)
307 input_error ();
308 else if (c != *f++)
310 ungetc (c, s);
311 conv_error ();
314 while (--len > 0);
315 continue;
319 fc = *f++;
320 if (fc != '%')
322 /* Remember to skip spaces. */
323 if (isspace (fc))
325 skip_space = 1;
326 continue;
329 /* Read a character. */
330 c = inchar ();
332 /* Characters other than format specs must just match. */
333 if (c == EOF)
334 input_error ();
336 /* We saw white space char as the last character in the format
337 string. Now it's time to skip all leading white space. */
338 if (skip_space)
340 while (isspace (c))
341 if (inchar () == EOF && errno == EINTR)
342 conv_error ();
343 skip_space = 0;
346 if (c != fc)
348 ungetc (c, s);
349 conv_error ();
352 continue;
355 /* This is the start of the conversion string. */
356 flags = 0;
358 /* Initialize state of modifiers. */
359 argpos = 0;
361 /* Prepare temporary buffer. */
362 wpsize = 0;
364 /* Check for a positional parameter specification. */
365 if (isdigit (*f))
367 argpos = *f++ - '0';
368 while (isdigit (*f))
369 argpos = argpos * 10 + (*f++ - '0');
370 if (*f == '$')
371 ++f;
372 else
374 /* Oops; that was actually the field width. */
375 width = argpos;
376 flags |= WIDTH;
377 argpos = 0;
378 goto got_width;
382 /* Check for the assignment-suppressing and the number grouping flag. */
383 while (*f == '*' || *f == '\'')
384 switch (*f++)
386 case '*':
387 flags |= SUPPRESS;
388 break;
389 case '\'':
390 flags |= GROUP;
391 break;
394 /* We have seen width. */
395 if (isdigit (*f))
396 flags |= WIDTH;
398 /* Find the maximum field width. */
399 width = 0;
400 while (isdigit (*f))
402 width *= 10;
403 width += *f++ - '0';
405 got_width:
406 if (width == 0)
407 width = -1;
409 /* Check for type modifiers. */
410 while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
411 switch (*f++)
413 case 'h':
414 /* int's are short int's. */
415 if (flags & (LONG|LONGDBL|CHAR))
416 /* Signal illegal format element. */
417 conv_error ();
418 if (flags & SHORT)
420 flags &= ~SHORT;
421 flags |= CHAR;
423 else
424 flags |= SHORT;
425 break;
426 case 'l':
427 if (flags & (SHORT|LONGDBL|CHAR))
428 conv_error ();
429 else if (flags & LONG)
431 /* A double `l' is equivalent to an `L'. */
432 flags &= ~LONG;
433 flags |= LONGDBL;
435 else
436 /* int's are long int's. */
437 flags |= LONG;
438 break;
439 case 'q':
440 case 'L':
441 /* double's are long double's, and int's are long long int's. */
442 if (flags & TYPEMOD)
443 /* Signal illegal format element. */
444 conv_error ();
445 flags |= LONGDBL;
446 break;
447 case 'a':
448 /* The `a' is used as a flag only if followed by `s', `S' or
449 `['. */
450 if (*f != 's' && *f != 'S' && *f != '[')
452 --f;
453 break;
455 if (flags & TYPEMOD)
456 /* Signal illegal format element. */
457 conv_error ();
458 /* String conversions (%s, %[) take a `char **'
459 arg and fill it in with a malloc'd pointer. */
460 flags |= MALLOC;
461 break;
464 /* End of the format string? */
465 if (*f == '\0')
466 conv_error ();
468 /* Find the conversion specifier. */
469 fc = *f++;
470 if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
472 /* Eat whitespace. */
473 int save_errno = errno;
474 errno = 0;
476 if (inchar () == EOF && errno == EINTR)
477 input_error ();
478 while (isspace (c));
479 errno = save_errno;
480 ungetc (c, s);
481 skip_space = 0;
484 switch (fc)
486 case '%': /* Must match a literal '%'. */
487 c = inchar ();
488 if (c == EOF)
489 input_error ();
490 if (c != fc)
492 ungetc (c, s);
493 conv_error ();
495 break;
497 case 'n': /* Answer number of assignments done. */
498 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
499 with the 'n' conversion specifier. */
500 if (!(flags & SUPPRESS))
502 /* Don't count the read-ahead. */
503 if (flags & LONGDBL)
504 *ARG (long long int *) = read_in;
505 else if (flags & LONG)
506 *ARG (long int *) = read_in;
507 else if (flags & SHORT)
508 *ARG (short int *) = read_in;
509 else
510 *ARG (int *) = read_in;
512 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
513 /* We have a severe problem here. The ISO C standard
514 contradicts itself in explaining the effect of the %n
515 format in `scanf'. While in ISO C:1990 and the ISO C
516 Amendement 1:1995 the result is described as
518 Execution of a %n directive does not effect the
519 assignment count returned at the completion of
520 execution of the f(w)scanf function.
522 in ISO C Corrigendum 1:1994 the following was added:
524 Subclause 7.9.6.2
525 Add the following fourth example:
527 #include <stdio.h>
528 int d1, d2, n1, n2, i;
529 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
530 the value 123 is assigned to d1 and the value3 to n1.
531 Because %n can never get an input failure the value
532 of 3 is also assigned to n2. The value of d2 is not
533 affected. The value 3 is assigned to i.
535 We go for now with the historically correct code from ISO C,
536 i.e., we don't count the %n assignments. When it ever
537 should proof to be wrong just remove the #ifdef above. */
538 ++done;
539 #endif
541 break;
543 case 'c': /* Match characters. */
544 if ((flags & LONG) == 0)
546 if (!(flags & SUPPRESS))
548 str = ARG (char *);
549 if (str == NULL)
550 conv_error ();
553 c = inchar ();
554 if (c == EOF)
555 input_error ();
557 if (width == -1)
558 width = 1;
560 if (!(flags & SUPPRESS))
563 *str++ = c;
564 while (--width > 0 && inchar () != EOF);
566 else
567 while (--width > 0 && inchar () != EOF);
569 if (!(flags & SUPPRESS))
570 ++done;
572 break;
574 /* FALLTHROUGH */
575 case 'C':
576 /* Get UTF-8 encoded wide character. Here we assume (as in
577 other parts of the libc) that we only have to handle
578 UTF-8. */
580 wint_t val;
581 size_t cnt = 0;
582 int first = 1;
584 if (!(flags & SUPPRESS))
586 wstr = ARG (wchar_t *);
587 if (str == NULL)
588 conv_error ();
593 #define NEXT_WIDE_CHAR(First) \
594 c = inchar (); \
595 if (c == EOF) \
596 /* EOF is only an error for the first character. */ \
597 if (First) \
598 input_error (); \
599 else \
600 break; \
601 val = c; \
602 if (val >= 0x80) \
604 if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
605 encode_error (); \
606 if ((c & 0xe0) == 0xc0) \
608 /* We expect two bytes. */ \
609 cnt = 1; \
610 val &= 0x1f; \
612 else if ((c & 0xf0) == 0xe0) \
614 /* We expect three bytes. */ \
615 cnt = 2; \
616 val &= 0x0f; \
618 else if ((c & 0xf8) == 0xf0) \
620 /* We expect four bytes. */ \
621 cnt = 3; \
622 val &= 0x07; \
624 else if ((c & 0xfc) == 0xf8) \
626 /* We expect five bytes. */ \
627 cnt = 4; \
628 val &= 0x03; \
630 else \
632 /* We expect six bytes. */ \
633 cnt = 5; \
634 val &= 0x01; \
637 do \
639 c = inchar (); \
640 if (c == EOF \
641 || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
642 encode_error (); \
643 val <<= 6; \
644 val |= c & 0x3f; \
646 while (--cnt > 0); \
649 if (!(flags & SUPPRESS)) \
650 *wstr++ = val; \
651 First = 0
653 NEXT_WIDE_CHAR (first);
655 while (--width > 0);
657 if (!(flags & SUPPRESS))
658 ++done;
660 break;
662 case 's': /* Read a string. */
663 if (flags & LONG)
664 /* We have to process a wide character string. */
665 goto wide_char_string;
667 #define STRING_ARG(Str, Type) \
668 if (!(flags & SUPPRESS)) \
670 if (flags & MALLOC) \
672 /* The string is to be stored in a malloc'd buffer. */ \
673 strptr = ARG (char **); \
674 if (strptr == NULL) \
675 conv_error (); \
676 /* Allocate an initial buffer. */ \
677 strsize = 100; \
678 *strptr = malloc (strsize * sizeof (Type)); \
679 Str = (Type *) *strptr; \
681 else \
682 Str = ARG (Type *); \
683 if (Str == NULL) \
684 conv_error (); \
686 STRING_ARG (str, char);
688 c = inchar ();
689 if (c == EOF)
690 input_error ();
694 if (isspace (c))
696 ungetc (c, s);
697 break;
699 #define STRING_ADD_CHAR(Str, c, Type) \
700 if (!(flags & SUPPRESS)) \
702 *Str++ = c; \
703 if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \
705 /* Enlarge the buffer. */ \
706 Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \
707 if (Str == NULL) \
709 /* Can't allocate that much. Last-ditch effort. */\
710 Str = realloc (*strptr, \
711 (strsize + 1) * sizeof (Type)); \
712 if (Str == NULL) \
714 /* We lose. Oh well. \
715 Terminate the string and stop converting, \
716 so at least we don't skip any input. */ \
717 ((Type *) (*strptr))[strsize] = '\0'; \
718 ++done; \
719 conv_error (); \
721 else \
723 *strptr = (char *) Str; \
724 Str = ((Type *) *strptr) + strsize; \
725 ++strsize; \
728 else \
730 *strptr = (char *) Str; \
731 Str = ((Type *) *strptr) + strsize; \
732 strsize *= 2; \
736 STRING_ADD_CHAR (str, c, char);
737 } while ((width <= 0 || --width > 0) && inchar () != EOF);
739 if (!(flags & SUPPRESS))
741 *str = '\0';
742 ++done;
744 break;
746 case 'S':
747 /* Wide character string. */
748 wide_char_string:
750 wint_t val;
751 int first = 1;
752 STRING_ARG (wstr, wchar_t);
756 size_t cnt = 0;
757 NEXT_WIDE_CHAR (first);
759 if (iswspace (val))
761 /* XXX We would have to push back the whole wide char
762 with possibly many bytes. But since scanf does
763 not make a difference for white space characters
764 we can simply push back a simple <SP> which is
765 guaranteed to be in the [:space:] class. */
766 ungetc (' ', s);
767 break;
770 STRING_ADD_CHAR (wstr, val, wchar_t);
771 first = 0;
773 while (width <= 0 || --width > 0);
775 if (!(flags & SUPPRESS))
777 *wstr = L'\0';
778 ++done;
781 break;
783 case 'x': /* Hexadecimal integer. */
784 case 'X': /* Ditto. */
785 base = 16;
786 number_signed = 0;
787 goto number;
789 case 'o': /* Octal integer. */
790 base = 8;
791 number_signed = 0;
792 goto number;
794 case 'u': /* Unsigned decimal integer. */
795 base = 10;
796 number_signed = 0;
797 goto number;
799 case 'd': /* Signed decimal integer. */
800 base = 10;
801 number_signed = 1;
802 goto number;
804 case 'i': /* Generic number. */
805 base = 0;
806 number_signed = 1;
808 number:
809 c = inchar ();
810 if (c == EOF)
811 input_error ();
813 /* Check for a sign. */
814 if (c == '-' || c == '+')
816 ADDW (c);
817 if (width > 0)
818 --width;
819 c = inchar ();
822 /* Look for a leading indication of base. */
823 if (width != 0 && c == '0')
825 if (width > 0)
826 --width;
828 ADDW (c);
829 c = inchar ();
831 if (width != 0 && tolower (c) == 'x')
833 if (base == 0)
834 base = 16;
835 if (base == 16)
837 if (width > 0)
838 --width;
839 c = inchar ();
842 else if (base == 0)
843 base = 8;
846 if (base == 0)
847 base = 10;
849 /* Read the number into workspace. */
850 while (c != EOF && width != 0)
852 if (base == 16 ? !isxdigit (c) :
853 ((!isdigit (c) || c - '0' >= base) &&
854 !((flags & GROUP) && base == 10 && c == thousands)))
855 break;
856 ADDW (c);
857 if (width > 0)
858 --width;
860 c = inchar ();
863 /* The just read character is not part of the number anymore. */
864 ungetc (c, s);
866 if (wpsize == 0 ||
867 (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
868 /* There was no number. */
869 conv_error ();
871 /* Convert the number. */
872 ADDW ('\0');
873 if (flags & LONGDBL)
875 if (number_signed)
876 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
877 else
878 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
880 else
882 if (number_signed)
883 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
884 else
885 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
887 if (wp == tw)
888 conv_error ();
890 if (!(flags & SUPPRESS))
892 if (! number_signed)
894 if (flags & LONGDBL)
895 *ARG (unsigned LONGLONG int *) = num.uq;
896 else if (flags & LONG)
897 *ARG (unsigned long int *) = num.ul;
898 else if (flags & SHORT)
899 *ARG (unsigned short int *)
900 = (unsigned short int) num.ul;
901 else if (flags & CHAR)
902 *ARG (unsigned char *) = (unsigned char) num.ul;
903 else
904 *ARG (unsigned int *) = (unsigned int) num.ul;
906 else
908 if (flags & LONGDBL)
909 *ARG (LONGLONG int *) = num.q;
910 else if (flags & LONG)
911 *ARG (long int *) = num.l;
912 else if (flags & SHORT)
913 *ARG (short int *) = (short int) num.l;
914 else if (flags & CHAR)
915 *ARG (signed char *) = (signed char) num.ul;
916 else
917 *ARG (int *) = (int) num.l;
919 ++done;
921 break;
923 case 'e': /* Floating-point numbers. */
924 case 'E':
925 case 'f':
926 case 'g':
927 case 'G':
928 case 'a':
929 case 'A':
930 c = inchar ();
931 if (c == EOF)
932 input_error ();
934 /* Check for a sign. */
935 if (c == '-' || c == '+')
937 negative = c == '-';
938 if (inchar () == EOF)
939 /* EOF is only an input error before we read any chars. */
940 conv_error ();
941 if (width > 0)
942 --width;
944 else
945 negative = 0;
947 /* Take care for the special arguments "nan" and "inf". */
948 if (tolower (c) == 'n')
950 /* Maybe "nan". */
951 ADDW (c);
952 if (inchar () == EOF || tolower (c) != 'a')
953 input_error ();
954 ADDW (c);
955 if (inchar () == EOF || tolower (c) != 'n')
956 input_error ();
957 ADDW (c);
958 /* It is "nan". */
959 goto scan_float;
961 else if (tolower (c) == 'i')
963 /* Maybe "inf" or "infinity". */
964 ADDW (c);
965 if (inchar () == EOF || tolower (c) != 'n')
966 input_error ();
967 ADDW (c);
968 if (inchar () == EOF || tolower (c) != 'f')
969 input_error ();
970 ADDW (c);
971 /* It is as least "inf". */
972 if (inchar () != EOF)
974 if (tolower (c) == 'i')
976 /* No we have to read the rest as well. */
977 ADDW (c);
978 if (inchar () == EOF || tolower (c) != 'n')
979 input_error ();
980 ADDW (c);
981 if (inchar () == EOF || tolower (c) != 'i')
982 input_error ();
983 ADDW (c);
984 if (inchar () == EOF || tolower (c) != 't')
985 input_error ();
986 ADDW (c);
987 if (inchar () == EOF || tolower (c) != 'y')
988 input_error ();
989 ADDW (c);
991 else
992 /* Never mind. */
993 ungetc (c, s);
995 goto scan_float;
998 is_hexa = 0;
999 exp_char = 'e';
1000 if (c == '0')
1002 ADDW (c);
1003 c = inchar ();
1004 if (tolower (c) == 'x')
1006 /* It is a number in hexadecimal format. */
1007 ADDW (c);
1009 is_hexa = 1;
1010 exp_char = 'p';
1012 /* Grouping is not allowed. */
1013 flags &= ~GROUP;
1014 c = inchar ();
1018 got_dot = got_e = 0;
1021 if (isdigit (c))
1022 ADDW (c);
1023 else if (!got_e && is_hexa && isxdigit (c))
1024 ADDW (c);
1025 else if (got_e && wp[wpsize - 1] == exp_char
1026 && (c == '-' || c == '+'))
1027 ADDW (c);
1028 else if (wpsize > 0 && !got_e && tolower (c) == exp_char)
1030 ADDW (exp_char);
1031 got_e = got_dot = 1;
1033 else if (c == decimal && !got_dot)
1035 ADDW (c);
1036 got_dot = 1;
1038 else if ((flags & GROUP) && c == thousands && !got_dot)
1039 ADDW (c);
1040 else
1042 /* The last read character is not part of the number
1043 anymore. */
1044 ungetc (c, s);
1045 break;
1047 if (width > 0)
1048 --width;
1050 while (width != 0 && inchar () != EOF);
1052 /* Have we read any character? If we try to read a number
1053 in hexadecimal notation and we have read only the `0x'
1054 prefix this is an error. */
1055 if (wpsize == 0 || (is_hexa && wpsize == 2))
1056 conv_error ();
1058 scan_float:
1059 /* Convert the number. */
1060 ADDW ('\0');
1061 if (flags & LONGDBL)
1063 long double d = __strtold_internal (wp, &tw, flags & GROUP);
1064 if (!(flags & SUPPRESS) && tw != wp)
1065 *ARG (long double *) = negative ? -d : d;
1067 else if (flags & LONG)
1069 double d = __strtod_internal (wp, &tw, flags & GROUP);
1070 if (!(flags & SUPPRESS) && tw != wp)
1071 *ARG (double *) = negative ? -d : d;
1073 else
1075 float d = __strtof_internal (wp, &tw, flags & GROUP);
1076 if (!(flags & SUPPRESS) && tw != wp)
1077 *ARG (float *) = negative ? -d : d;
1080 if (tw == wp)
1081 conv_error ();
1083 if (!(flags & SUPPRESS))
1084 ++done;
1085 break;
1087 case '[': /* Character class. */
1088 if (flags & LONG)
1090 STRING_ARG (wstr, wchar_t);
1091 c = '\0'; /* This is to keep gcc quiet. */
1093 else
1095 STRING_ARG (str, char);
1097 c = inchar ();
1098 if (c == EOF)
1099 input_error ();
1102 if (*f == '^')
1104 ++f;
1105 not_in = 1;
1107 else
1108 not_in = 0;
1110 /* Fill WP with byte flags indexed by character.
1111 We will use this flag map for matching input characters. */
1112 if (wpmax < UCHAR_MAX)
1114 wpmax = UCHAR_MAX;
1115 wp = (char *) alloca (wpmax);
1117 memset (wp, 0, UCHAR_MAX);
1119 fc = *f;
1120 if (fc == ']' || fc == '-')
1122 /* If ] or - appears before any char in the set, it is not
1123 the terminator or separator, but the first char in the
1124 set. */
1125 wp[fc] = 1;
1126 ++f;
1129 while ((fc = *f++) != '\0' && fc != ']')
1131 if (fc == '-' && *f != '\0' && *f != ']' &&
1132 (unsigned char) f[-2] <= (unsigned char) *f)
1134 /* Add all characters from the one before the '-'
1135 up to (but not including) the next format char. */
1136 for (fc = f[-2]; fc < *f; ++fc)
1137 wp[fc] = 1;
1139 else
1140 /* Add the character to the flag map. */
1141 wp[fc] = 1;
1143 if (fc == '\0')
1145 if (!(flags & LONG))
1146 ungetc (c, s);
1147 conv_error();
1150 if (flags & LONG)
1152 wint_t val;
1153 int first = 1;
1157 size_t cnt = 0;
1158 NEXT_WIDE_CHAR (first);
1159 if (val <= 255 && wp[val] == not_in)
1161 ungetc (val, s);
1162 break;
1164 STRING_ADD_CHAR (wstr, val, wchar_t);
1165 if (width > 0)
1166 --width;
1167 first = 0;
1169 while (width != 0);
1171 if (first)
1172 conv_error ();
1174 if (!(flags & SUPPRESS))
1176 *wstr = L'\0';
1177 ++done;
1180 else
1182 num.ul = read_in - 1; /* -1 because we already read one char. */
1185 if (wp[c] == not_in)
1187 ungetc (c, s);
1188 break;
1190 STRING_ADD_CHAR (str, c, char);
1191 if (width > 0)
1192 --width;
1194 while (width != 0 && inchar () != EOF);
1196 if (read_in == num.ul)
1197 conv_error ();
1199 if (!(flags & SUPPRESS))
1201 *str = '\0';
1202 ++done;
1205 break;
1207 case 'p': /* Generic pointer. */
1208 base = 16;
1209 /* A PTR must be the same size as a `long int'. */
1210 flags &= ~(SHORT|LONGDBL);
1211 flags |= LONG;
1212 number_signed = 0;
1213 goto number;
1217 /* The last thing we saw int the format string was a white space.
1218 Consume the last white spaces. */
1219 if (skip_space)
1222 c = inchar ();
1223 while (isspace (c));
1224 ungetc (c, s);
1227 /* Unlock stream. */
1228 UNLOCK_STREAM (s);
1230 return done;
1233 #ifdef USE_IN_LIBIO
1235 __vfscanf (FILE *s, const char *format, va_list argptr)
1237 return _IO_vfscanf (s, format, argptr, NULL);
1239 #endif
1241 weak_alias (__vfscanf, vfscanf)