Update.
[glibc.git] / stdio-common / vfscanf.c
blobf9bbb6929e12fa3f5222e097407066d03c4dfb3f
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 /* Workspace. */
220 char *tw; /* Temporary pointer. */
221 char *wp = NULL; /* Workspace. */
222 size_t wpmax = 0; /* Maximal size of workspace. */
223 size_t wpsize; /* Currently used bytes in workspace. */
224 #define ADDW(Ch) \
225 do \
227 if (wpsize == wpmax) \
229 char *old = wp; \
230 wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \
231 wp = (char *) alloca (wpmax); \
232 if (old != NULL) \
233 memcpy (wp, old, wpsize); \
235 wp[wpsize++] = (Ch); \
237 while (0)
239 #ifdef __va_copy
240 __va_copy (arg, argptr);
241 #else
242 arg = (va_list) argptr;
243 #endif
245 ARGCHECK (s, format);
247 /* Figure out the decimal point character. */
248 if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
249 strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
250 decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
251 /* Figure out the thousands separator character. */
252 if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
253 strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
254 thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
256 /* Lock the stream. */
257 LOCK_STREAM (s);
259 /* Run through the format string. */
260 while (*f != '\0')
262 unsigned int argpos;
263 /* Extract the next argument, which is of type TYPE.
264 For a %N$... spec, this is the Nth argument from the beginning;
265 otherwise it is the next argument after the state now in ARG. */
266 #ifdef __va_copy
267 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
268 ({ unsigned int pos = argpos; \
269 va_list arg; \
270 __va_copy (arg, argptr); \
271 while (--pos > 0) \
272 (void) va_arg (arg, void *); \
273 va_arg (arg, type); \
275 #else
276 # if 0
277 /* XXX Possible optimization. */
278 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
279 ({ va_list arg = (va_list) argptr; \
280 arg = (va_list) ((char *) arg \
281 + (argpos - 1) \
282 * __va_rounded_size (void *)); \
283 va_arg (arg, type); \
285 # else
286 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
287 ({ unsigned int pos = argpos; \
288 va_list arg = (va_list) argptr; \
289 while (--pos > 0) \
290 (void) va_arg (arg, void *); \
291 va_arg (arg, type); \
293 # endif
294 #endif
296 if (!isascii (*f))
298 /* Non-ASCII, may be a multibyte. */
299 int len = mblen (f, strlen (f));
300 if (len > 0)
304 c = inchar ();
305 if (c == EOF)
306 input_error ();
307 else if (c != *f++)
309 ungetc (c, s);
310 conv_error ();
313 while (--len > 0);
314 continue;
318 fc = *f++;
319 if (fc != '%')
321 /* Remember to skip spaces. */
322 if (isspace (fc))
324 skip_space = 1;
325 continue;
328 /* Read a character. */
329 c = inchar ();
331 /* Characters other than format specs must just match. */
332 if (c == EOF)
333 input_error ();
335 /* We saw white space char as the last character in the format
336 string. Now it's time to skip all leading white space. */
337 if (skip_space)
339 while (isspace (c))
340 if (inchar () == EOF && errno == EINTR)
341 conv_error ();
342 skip_space = 0;
345 if (c != fc)
347 ungetc (c, s);
348 conv_error ();
351 continue;
354 /* This is the start of the conversion string. */
355 flags = 0;
357 /* Initialize state of modifiers. */
358 argpos = 0;
360 /* Prepare temporary buffer. */
361 wpsize = 0;
363 /* Check for a positional parameter specification. */
364 if (isdigit (*f))
366 argpos = *f++ - '0';
367 while (isdigit (*f))
368 argpos = argpos * 10 + (*f++ - '0');
369 if (*f == '$')
370 ++f;
371 else
373 /* Oops; that was actually the field width. */
374 width = argpos;
375 flags |= WIDTH;
376 argpos = 0;
377 goto got_width;
381 /* Check for the assignment-suppressing and the number grouping flag. */
382 while (*f == '*' || *f == '\'')
383 switch (*f++)
385 case '*':
386 flags |= SUPPRESS;
387 break;
388 case '\'':
389 flags |= GROUP;
390 break;
393 /* We have seen width. */
394 if (isdigit (*f))
395 flags |= WIDTH;
397 /* Find the maximum field width. */
398 width = 0;
399 while (isdigit (*f))
401 width *= 10;
402 width += *f++ - '0';
404 got_width:
405 if (width == 0)
406 width = -1;
408 /* Check for type modifiers. */
409 switch (*f++)
411 case 'h':
412 /* ints are short ints or chars. */
413 if (*f == 'h')
415 ++f;
416 flags |= CHAR;
418 else
419 flags |= SHORT;
420 break;
421 case 'l':
422 if (*f == 'l')
424 /* A double `l' is equivalent to an `L'. */
425 ++f;
426 flags |= LONGDBL;
428 else
429 /* ints are long ints. */
430 flags |= LONG;
431 break;
432 case 'q':
433 case 'L':
434 /* doubles are long doubles, and ints are long long ints. */
435 flags |= LONGDBL;
436 break;
437 case 'a':
438 /* The `a' is used as a flag only if followed by `s', `S' or
439 `['. */
440 if (*f != 's' && *f != 'S' && *f != '[')
442 --f;
443 break;
445 /* String conversions (%s, %[) take a `char **'
446 arg and fill it in with a malloc'd pointer. */
447 flags |= MALLOC;
448 break;
449 case 'z':
450 if (sizeof (size_t) > sizeof (unsigned long int))
451 flags |= LONGDBL;
452 else if (sizeof (size_t) > sizeof (unsigned int))
453 flags |= LONG;
454 break;
455 case 'j':
456 if (sizeof (uintmax_t) > sizeof (unsigned long int))
457 flags |= LONGDBL;
458 else if (sizeof (uintmax_t) > sizeof (unsigned int))
459 flags |= LONG;
460 break;
461 case 't':
462 if (sizeof (ptrdiff_t) > sizeof (long int))
463 flags |= LONGDBL;
464 else if (sizeof (ptrdiff_t) > sizeof (int))
465 flags |= LONG;
466 break;
467 default:
468 /* Not a recognized modifier. Backup. */
469 --f;
470 break;
473 /* End of the format string? */
474 if (*f == '\0')
475 conv_error ();
477 /* Find the conversion specifier. */
478 fc = *f++;
479 if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
481 /* Eat whitespace. */
482 int save_errno = errno;
483 errno = 0;
485 if (inchar () == EOF && errno == EINTR)
486 input_error ();
487 while (isspace (c));
488 errno = save_errno;
489 ungetc (c, s);
490 skip_space = 0;
493 switch (fc)
495 case '%': /* Must match a literal '%'. */
496 c = inchar ();
497 if (c == EOF)
498 input_error ();
499 if (c != fc)
501 ungetc (c, s);
502 conv_error ();
504 break;
506 case 'n': /* Answer number of assignments done. */
507 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
508 with the 'n' conversion specifier. */
509 if (!(flags & SUPPRESS))
511 /* Don't count the read-ahead. */
512 if (flags & LONGDBL)
513 *ARG (long long int *) = read_in;
514 else if (flags & LONG)
515 *ARG (long int *) = read_in;
516 else if (flags & SHORT)
517 *ARG (short int *) = read_in;
518 else
519 *ARG (int *) = read_in;
521 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
522 /* We have a severe problem here. The ISO C standard
523 contradicts itself in explaining the effect of the %n
524 format in `scanf'. While in ISO C:1990 and the ISO C
525 Amendement 1:1995 the result is described as
527 Execution of a %n directive does not effect the
528 assignment count returned at the completion of
529 execution of the f(w)scanf function.
531 in ISO C Corrigendum 1:1994 the following was added:
533 Subclause 7.9.6.2
534 Add the following fourth example:
536 #include <stdio.h>
537 int d1, d2, n1, n2, i;
538 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
539 the value 123 is assigned to d1 and the value3 to n1.
540 Because %n can never get an input failure the value
541 of 3 is also assigned to n2. The value of d2 is not
542 affected. The value 3 is assigned to i.
544 We go for now with the historically correct code from ISO C,
545 i.e., we don't count the %n assignments. When it ever
546 should proof to be wrong just remove the #ifdef above. */
547 ++done;
548 #endif
550 break;
552 case 'c': /* Match characters. */
553 if ((flags & LONG) == 0)
555 if (!(flags & SUPPRESS))
557 str = ARG (char *);
558 if (str == NULL)
559 conv_error ();
562 c = inchar ();
563 if (c == EOF)
564 input_error ();
566 if (width == -1)
567 width = 1;
569 if (!(flags & SUPPRESS))
572 *str++ = c;
573 while (--width > 0 && inchar () != EOF);
575 else
576 while (--width > 0 && inchar () != EOF);
578 if (!(flags & SUPPRESS))
579 ++done;
581 break;
583 /* FALLTHROUGH */
584 case 'C':
585 /* Get UTF-8 encoded wide character. Here we assume (as in
586 other parts of the libc) that we only have to handle
587 UTF-8. */
589 wint_t val;
590 size_t cnt = 0;
591 int first = 1;
593 if (!(flags & SUPPRESS))
595 wstr = ARG (wchar_t *);
596 if (str == NULL)
597 conv_error ();
602 #define NEXT_WIDE_CHAR(First) \
603 c = inchar (); \
604 if (c == EOF) \
606 /* EOF is only an error for the first character. */ \
607 if (First) \
608 input_error (); \
609 else \
610 break; \
612 val = c; \
613 if (val >= 0x80) \
615 if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
616 encode_error (); \
617 if ((c & 0xe0) == 0xc0) \
619 /* We expect two bytes. */ \
620 cnt = 1; \
621 val &= 0x1f; \
623 else if ((c & 0xf0) == 0xe0) \
625 /* We expect three bytes. */ \
626 cnt = 2; \
627 val &= 0x0f; \
629 else if ((c & 0xf8) == 0xf0) \
631 /* We expect four bytes. */ \
632 cnt = 3; \
633 val &= 0x07; \
635 else if ((c & 0xfc) == 0xf8) \
637 /* We expect five bytes. */ \
638 cnt = 4; \
639 val &= 0x03; \
641 else \
643 /* We expect six bytes. */ \
644 cnt = 5; \
645 val &= 0x01; \
648 do \
650 c = inchar (); \
651 if (c == EOF \
652 || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
653 encode_error (); \
654 val <<= 6; \
655 val |= c & 0x3f; \
657 while (--cnt > 0); \
660 if (!(flags & SUPPRESS)) \
661 *wstr++ = val; \
662 First = 0
664 NEXT_WIDE_CHAR (first);
666 while (--width > 0);
668 if (!(flags & SUPPRESS))
669 ++done;
671 break;
673 case 's': /* Read a string. */
674 if (flags & LONG)
675 /* We have to process a wide character string. */
676 goto wide_char_string;
678 #define STRING_ARG(Str, Type) \
679 if (!(flags & SUPPRESS)) \
681 if (flags & MALLOC) \
683 /* The string is to be stored in a malloc'd buffer. */ \
684 strptr = ARG (char **); \
685 if (strptr == NULL) \
686 conv_error (); \
687 /* Allocate an initial buffer. */ \
688 strsize = 100; \
689 *strptr = malloc (strsize * sizeof (Type)); \
690 Str = (Type *) *strptr; \
692 else \
693 Str = ARG (Type *); \
694 if (Str == NULL) \
695 conv_error (); \
697 STRING_ARG (str, char);
699 c = inchar ();
700 if (c == EOF)
701 input_error ();
705 if (isspace (c))
707 ungetc (c, s);
708 break;
710 #define STRING_ADD_CHAR(Str, c, Type) \
711 if (!(flags & SUPPRESS)) \
713 *Str++ = c; \
714 if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \
716 /* Enlarge the buffer. */ \
717 Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \
718 if (Str == NULL) \
720 /* Can't allocate that much. Last-ditch effort. */\
721 Str = realloc (*strptr, \
722 (strsize + 1) * sizeof (Type)); \
723 if (Str == NULL) \
725 /* We lose. Oh well. \
726 Terminate the string and stop converting, \
727 so at least we don't skip any input. */ \
728 ((Type *) (*strptr))[strsize] = '\0'; \
729 ++done; \
730 conv_error (); \
732 else \
734 *strptr = (char *) Str; \
735 Str = ((Type *) *strptr) + strsize; \
736 ++strsize; \
739 else \
741 *strptr = (char *) Str; \
742 Str = ((Type *) *strptr) + strsize; \
743 strsize *= 2; \
747 STRING_ADD_CHAR (str, c, char);
748 } while ((width <= 0 || --width > 0) && inchar () != EOF);
750 if (!(flags & SUPPRESS))
752 *str = '\0';
753 ++done;
755 break;
757 case 'S':
758 /* Wide character string. */
759 wide_char_string:
761 wint_t val;
762 int first = 1;
763 STRING_ARG (wstr, wchar_t);
767 size_t cnt = 0;
768 NEXT_WIDE_CHAR (first);
770 if (iswspace (val))
772 /* XXX We would have to push back the whole wide char
773 with possibly many bytes. But since scanf does
774 not make a difference for white space characters
775 we can simply push back a simple <SP> which is
776 guaranteed to be in the [:space:] class. */
777 ungetc (' ', s);
778 break;
781 STRING_ADD_CHAR (wstr, val, wchar_t);
782 first = 0;
784 while (width <= 0 || --width > 0);
786 if (!(flags & SUPPRESS))
788 *wstr = L'\0';
789 ++done;
792 break;
794 case 'x': /* Hexadecimal integer. */
795 case 'X': /* Ditto. */
796 base = 16;
797 number_signed = 0;
798 goto number;
800 case 'o': /* Octal integer. */
801 base = 8;
802 number_signed = 0;
803 goto number;
805 case 'u': /* Unsigned decimal integer. */
806 base = 10;
807 number_signed = 0;
808 goto number;
810 case 'd': /* Signed decimal integer. */
811 base = 10;
812 number_signed = 1;
813 goto number;
815 case 'i': /* Generic number. */
816 base = 0;
817 number_signed = 1;
819 number:
820 c = inchar ();
821 if (c == EOF)
822 input_error ();
824 /* Check for a sign. */
825 if (c == '-' || c == '+')
827 ADDW (c);
828 if (width > 0)
829 --width;
830 c = inchar ();
833 /* Look for a leading indication of base. */
834 if (width != 0 && c == '0')
836 if (width > 0)
837 --width;
839 ADDW (c);
840 c = inchar ();
842 if (width != 0 && tolower (c) == 'x')
844 if (base == 0)
845 base = 16;
846 if (base == 16)
848 if (width > 0)
849 --width;
850 c = inchar ();
853 else if (base == 0)
854 base = 8;
857 if (base == 0)
858 base = 10;
860 /* Read the number into workspace. */
861 while (c != EOF && width != 0)
863 if (base == 16 ? !isxdigit (c) :
864 ((!isdigit (c) || c - '0' >= base) &&
865 !((flags & GROUP) && base == 10 && c == thousands)))
866 break;
867 ADDW (c);
868 if (width > 0)
869 --width;
871 c = inchar ();
874 /* The just read character is not part of the number anymore. */
875 ungetc (c, s);
877 if (wpsize == 0 ||
878 (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
879 /* There was no number. */
880 conv_error ();
882 /* Convert the number. */
883 ADDW ('\0');
884 if (flags & LONGDBL)
886 if (number_signed)
887 num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
888 else
889 num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
891 else
893 if (number_signed)
894 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
895 else
896 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
898 if (wp == tw)
899 conv_error ();
901 if (!(flags & SUPPRESS))
903 if (! number_signed)
905 if (flags & LONGDBL)
906 *ARG (unsigned LONGLONG int *) = num.uq;
907 else if (flags & LONG)
908 *ARG (unsigned long int *) = num.ul;
909 else if (flags & SHORT)
910 *ARG (unsigned short int *)
911 = (unsigned short int) num.ul;
912 else if (flags & CHAR)
913 *ARG (unsigned char *) = (unsigned char) num.ul;
914 else
915 *ARG (unsigned int *) = (unsigned int) num.ul;
917 else
919 if (flags & LONGDBL)
920 *ARG (LONGLONG int *) = num.q;
921 else if (flags & LONG)
922 *ARG (long int *) = num.l;
923 else if (flags & SHORT)
924 *ARG (short int *) = (short int) num.l;
925 else if (flags & CHAR)
926 *ARG (signed char *) = (signed char) num.ul;
927 else
928 *ARG (int *) = (int) num.l;
930 ++done;
932 break;
934 case 'e': /* Floating-point numbers. */
935 case 'E':
936 case 'f':
937 case 'g':
938 case 'G':
939 case 'a':
940 case 'A':
941 c = inchar ();
942 if (c == EOF)
943 input_error ();
945 /* Check for a sign. */
946 if (c == '-' || c == '+')
948 negative = c == '-';
949 if (inchar () == EOF)
950 /* EOF is only an input error before we read any chars. */
951 conv_error ();
952 if (width > 0)
953 --width;
955 else
956 negative = 0;
958 /* Take care for the special arguments "nan" and "inf". */
959 if (tolower (c) == 'n')
961 /* Maybe "nan". */
962 ADDW (c);
963 if (inchar () == EOF || tolower (c) != 'a')
964 input_error ();
965 ADDW (c);
966 if (inchar () == EOF || tolower (c) != 'n')
967 input_error ();
968 ADDW (c);
969 /* It is "nan". */
970 goto scan_float;
972 else if (tolower (c) == 'i')
974 /* Maybe "inf" or "infinity". */
975 ADDW (c);
976 if (inchar () == EOF || tolower (c) != 'n')
977 input_error ();
978 ADDW (c);
979 if (inchar () == EOF || tolower (c) != 'f')
980 input_error ();
981 ADDW (c);
982 /* It is as least "inf". */
983 if (inchar () != EOF)
985 if (tolower (c) == 'i')
987 /* No we have to read the rest as well. */
988 ADDW (c);
989 if (inchar () == EOF || tolower (c) != 'n')
990 input_error ();
991 ADDW (c);
992 if (inchar () == EOF || tolower (c) != 'i')
993 input_error ();
994 ADDW (c);
995 if (inchar () == EOF || tolower (c) != 't')
996 input_error ();
997 ADDW (c);
998 if (inchar () == EOF || tolower (c) != 'y')
999 input_error ();
1000 ADDW (c);
1002 else
1003 /* Never mind. */
1004 ungetc (c, s);
1006 goto scan_float;
1009 is_hexa = 0;
1010 exp_char = 'e';
1011 if (c == '0')
1013 ADDW (c);
1014 c = inchar ();
1015 if (tolower (c) == 'x')
1017 /* It is a number in hexadecimal format. */
1018 ADDW (c);
1020 is_hexa = 1;
1021 exp_char = 'p';
1023 /* Grouping is not allowed. */
1024 flags &= ~GROUP;
1025 c = inchar ();
1029 got_dot = got_e = 0;
1032 if (isdigit (c))
1033 ADDW (c);
1034 else if (!got_e && is_hexa && isxdigit (c))
1035 ADDW (c);
1036 else if (got_e && wp[wpsize - 1] == exp_char
1037 && (c == '-' || c == '+'))
1038 ADDW (c);
1039 else if (wpsize > 0 && !got_e && tolower (c) == exp_char)
1041 ADDW (exp_char);
1042 got_e = got_dot = 1;
1044 else if (c == decimal && !got_dot)
1046 ADDW (c);
1047 got_dot = 1;
1049 else if ((flags & GROUP) && c == thousands && !got_dot)
1050 ADDW (c);
1051 else
1053 /* The last read character is not part of the number
1054 anymore. */
1055 ungetc (c, s);
1056 break;
1058 if (width > 0)
1059 --width;
1061 while (width != 0 && inchar () != EOF);
1063 /* Have we read any character? If we try to read a number
1064 in hexadecimal notation and we have read only the `0x'
1065 prefix this is an error. */
1066 if (wpsize == 0 || (is_hexa && wpsize == 2))
1067 conv_error ();
1069 scan_float:
1070 /* Convert the number. */
1071 ADDW ('\0');
1072 if (flags & LONGDBL)
1074 long double d = __strtold_internal (wp, &tw, flags & GROUP);
1075 if (!(flags & SUPPRESS) && tw != wp)
1076 *ARG (long double *) = negative ? -d : d;
1078 else if (flags & LONG)
1080 double d = __strtod_internal (wp, &tw, flags & GROUP);
1081 if (!(flags & SUPPRESS) && tw != wp)
1082 *ARG (double *) = negative ? -d : d;
1084 else
1086 float d = __strtof_internal (wp, &tw, flags & GROUP);
1087 if (!(flags & SUPPRESS) && tw != wp)
1088 *ARG (float *) = negative ? -d : d;
1091 if (tw == wp)
1092 conv_error ();
1094 if (!(flags & SUPPRESS))
1095 ++done;
1096 break;
1098 case '[': /* Character class. */
1099 if (flags & LONG)
1101 STRING_ARG (wstr, wchar_t);
1102 c = '\0'; /* This is to keep gcc quiet. */
1104 else
1106 STRING_ARG (str, char);
1108 c = inchar ();
1109 if (c == EOF)
1110 input_error ();
1113 if (*f == '^')
1115 ++f;
1116 not_in = 1;
1118 else
1119 not_in = 0;
1121 /* Fill WP with byte flags indexed by character.
1122 We will use this flag map for matching input characters. */
1123 if (wpmax < UCHAR_MAX)
1125 wpmax = UCHAR_MAX;
1126 wp = (char *) alloca (wpmax);
1128 memset (wp, 0, UCHAR_MAX);
1130 fc = *f;
1131 if (fc == ']' || fc == '-')
1133 /* If ] or - appears before any char in the set, it is not
1134 the terminator or separator, but the first char in the
1135 set. */
1136 wp[fc] = 1;
1137 ++f;
1140 while ((fc = *f++) != '\0' && fc != ']')
1142 if (fc == '-' && *f != '\0' && *f != ']' &&
1143 (unsigned char) f[-2] <= (unsigned char) *f)
1145 /* Add all characters from the one before the '-'
1146 up to (but not including) the next format char. */
1147 for (fc = f[-2]; fc < *f; ++fc)
1148 wp[fc] = 1;
1150 else
1151 /* Add the character to the flag map. */
1152 wp[fc] = 1;
1154 if (fc == '\0')
1156 if (!(flags & LONG))
1157 ungetc (c, s);
1158 conv_error();
1161 if (flags & LONG)
1163 wint_t val;
1164 int first = 1;
1168 size_t cnt = 0;
1169 NEXT_WIDE_CHAR (first);
1170 if (val <= 255 && wp[val] == not_in)
1172 ungetc (val, s);
1173 break;
1175 STRING_ADD_CHAR (wstr, val, wchar_t);
1176 if (width > 0)
1177 --width;
1178 first = 0;
1180 while (width != 0);
1182 if (first)
1183 conv_error ();
1185 if (!(flags & SUPPRESS))
1187 *wstr = L'\0';
1188 ++done;
1191 else
1193 num.ul = read_in - 1; /* -1 because we already read one char. */
1196 if (wp[c] == not_in)
1198 ungetc (c, s);
1199 break;
1201 STRING_ADD_CHAR (str, c, char);
1202 if (width > 0)
1203 --width;
1205 while (width != 0 && inchar () != EOF);
1207 if (read_in == num.ul)
1208 conv_error ();
1210 if (!(flags & SUPPRESS))
1212 *str = '\0';
1213 ++done;
1216 break;
1218 case 'p': /* Generic pointer. */
1219 base = 16;
1220 /* A PTR must be the same size as a `long int'. */
1221 flags &= ~(SHORT|LONGDBL);
1222 flags |= LONG;
1223 number_signed = 0;
1224 goto number;
1228 /* The last thing we saw int the format string was a white space.
1229 Consume the last white spaces. */
1230 if (skip_space)
1233 c = inchar ();
1234 while (isspace (c));
1235 ungetc (c, s);
1238 /* Unlock stream. */
1239 UNLOCK_STREAM (s);
1241 return done;
1244 #ifdef USE_IN_LIBIO
1246 __vfscanf (FILE *s, const char *format, va_list argptr)
1248 return _IO_vfscanf (s, format, argptr, NULL);
1250 #endif
1252 weak_alias (__vfscanf, vfscanf)