update from main archive 970203
[glibc/history.git] / stdio-common / vfscanf.c
blobf201c467753ed04ae1e92f786dfe8d8c7e1f2f0e
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 <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) (--read_in, _IO_ungetc (c, s))
58 # define inchar() ((c = _IO_getc_unlocked (s)), (void) ++read_in, c)
59 # define encode_error() do { \
60 if (errp != NULL) *errp |= 4; \
61 _IO_funlockfile (s); \
62 __set_errno (EILSEQ); \
63 return done; \
64 } while (0)
65 # define conv_error() do { \
66 if (errp != NULL) *errp |= 2; \
67 _IO_funlockfile (s); \
68 return done; \
69 } while (0)
70 # define input_error() do { \
71 _IO_funlockfile (s); \
72 if (errp != NULL) *errp |= 1; \
73 return done ?: EOF; \
74 } while (0)
75 # define memory_error() do { \
76 _IO_funlockfile (s); \
77 __set_errno (ENOMEM); \
78 return EOF; \
79 } while (0)
80 # define ARGCHECK(s, format) \
81 do \
82 { \
83 /* Check file argument for consistence. */ \
84 CHECK_FILE (s, EOF); \
85 if (s->_flags & _IO_NO_READS) \
86 { \
87 __set_errno (EBADF); \
88 return EOF; \
89 } \
90 else if (format == NULL) \
91 { \
92 MAYBE_SET_EINVAL; \
93 return EOF; \
94 } \
95 } while (0)
96 # define LOCK_STREAM(S) \
97 __libc_cleanup_region_start ((void (*) (void *)) &_IO_funlockfile, (S)); \
98 _IO_flockfile (S)
99 # define UNLOCK_STREAM __libc_cleanup_region_end (1)
100 #else
101 # define ungetc(c, s) (--read_in, ungetc (c, s))
102 # define inchar() ((c = getc (s)), (void) ++read_in, c)
103 # define encode_error() do { \
104 funlockfile (s); \
105 __set_errno (EILSEQ); \
106 return done; \
107 } while (0)
108 # define conv_error() do { \
109 funlockfile (s); \
110 return done; \
111 } while (0)
112 # define input_error() do { \
113 funlockfile (s); \
114 return done ?: EOF; \
115 } while (0)
116 # define memory_error() do { \
117 funlockfile (s); \
118 __set_errno (ENOMEM); \
119 return EOF; \
120 } while (0)
121 # define ARGCHECK(s, format) \
122 do \
124 /* Check file argument for consistence. */ \
125 if (!__validfp (s) || !s->__mode.__read) \
127 __set_errno (EBADF); \
128 return EOF; \
130 else if (format == NULL) \
132 __set_errno (EINVAL); \
133 return EOF; \
135 } while (0)
136 #if 1
137 /* XXX For now !!! */
138 # define flockfile(S) /* nothing */
139 # define funlockfile(S) /* nothing */
140 # define LOCK_STREAM(S)
141 # define UNLOCK_STREAM
142 #else
143 # define LOCK_STREAM(S) \
144 __libc_cleanup_region_start (&__funlockfile, (S)); \
145 __flockfile (S)
146 # define UNLOCK_STREAM __libc_cleanup_region_end (1)
147 #endif
148 #endif
151 /* Read formatted input from S according to the format string
152 FORMAT, using the argument list in ARG.
153 Return the number of assignments made, or -1 for an input error. */
154 #ifdef USE_IN_LIBIO
156 _IO_vfscanf (s, format, argptr, errp)
157 _IO_FILE *s;
158 const char *format;
159 _IO_va_list argptr;
160 int *errp;
161 #else
163 __vfscanf (FILE *s, const char *format, va_list argptr)
164 #endif
166 va_list arg = (va_list) argptr;
168 register const char *f = format;
169 register unsigned char fc; /* Current character of the format. */
170 register size_t done = 0; /* Assignments done. */
171 register size_t read_in = 0; /* Chars read in. */
172 register int c = 0; /* Last char read. */
173 register int width; /* Maximum field width. */
174 register int flags; /* Modifiers for current format element. */
176 /* Status for reading F-P nums. */
177 char got_dot, got_e, negative;
178 /* If a [...] is a [^...]. */
179 char not_in;
180 /* Base for integral numbers. */
181 int base;
182 /* Signedness for integral numbers. */
183 int number_signed;
184 /* Decimal point character. */
185 wchar_t decimal;
186 /* The thousands character of the current locale. */
187 wchar_t thousands;
188 /* Integral holding variables. */
189 union
191 long long int q;
192 unsigned long long int uq;
193 long int l;
194 unsigned long int ul;
195 } num;
196 /* Character-buffer pointer. */
197 char *str = NULL;
198 wchar_t *wstr = NULL;
199 char **strptr = NULL;
200 size_t strsize = 0;
201 /* We must not react on white spaces immediately because they can
202 possibly be matched even if in the input stream no character is
203 available anymore. */
204 int skip_space = 0;
205 /* Workspace. */
206 char *tw; /* Temporary pointer. */
207 char *wp = NULL; /* Workspace. */
208 size_t wpmax = 0; /* Maximal size of workspace. */
209 size_t wpsize; /* Currently used bytes in workspace. */
210 #define ADDW(Ch) \
211 do \
213 if (wpsize == wpmax) \
215 char *old = wp; \
216 wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; \
217 wp = (char *) alloca (wpmax); \
218 if (old != NULL) \
219 memcpy (wp, old, wpsize); \
221 wp[wpsize++] = (Ch); \
223 while (0)
225 ARGCHECK (s, format);
227 /* Figure out the decimal point character. */
228 if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
229 strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
230 decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
231 /* Figure out the thousands separator character. */
232 if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
233 strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
234 thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
236 /* Lock the stream. */
237 LOCK_STREAM (s);
239 /* Run through the format string. */
240 while (*f != '\0')
242 unsigned int argpos;
243 /* Extract the next argument, which is of type TYPE.
244 For a %N$... spec, this is the Nth argument from the beginning;
245 otherwise it is the next argument after the state now in ARG. */
246 #if 0
247 /* XXX Possible optimization. */
248 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
249 ({ va_list arg = (va_list) argptr; \
250 arg = (va_list) ((char *) arg \
251 + (argpos - 1) \
252 * __va_rounded_size (void *)); \
253 va_arg (arg, type); \
255 #else
256 # define ARG(type) (argpos == 0 ? va_arg (arg, type) : \
257 ({ unsigned int pos = argpos; \
258 va_list arg = (va_list) argptr; \
259 while (--pos > 0) \
260 (void) va_arg (arg, void *); \
261 va_arg (arg, type); \
263 #endif
265 if (!isascii (*f))
267 /* Non-ASCII, may be a multibyte. */
268 int len = mblen (f, strlen (f));
269 if (len > 0)
273 c = inchar ();
274 if (c == EOF)
275 input_error ();
276 else if (c != *f++)
278 ungetc (c, s);
279 conv_error ();
282 while (--len > 0);
283 continue;
287 fc = *f++;
288 if (fc != '%')
290 /* Remember to skip spaces. */
291 if (isspace (fc))
293 skip_space = 1;
294 continue;
297 /* Read a character. */
298 c = inchar ();
300 /* Characters other than format specs must just match. */
301 if (c == EOF)
302 input_error ();
304 /* We saw white space char as the last character in the format
305 string. Now it's time to skip all leading white space. */
306 if (skip_space)
308 while (isspace (c))
309 if (inchar () == EOF && errno == EINTR)
310 conv_error ();
311 skip_space = 0;
314 if (c != fc)
316 ungetc (c, s);
317 conv_error ();
320 continue;
323 /* This is the start of the conversion string. */
324 flags = 0;
326 /* Initialize state of modifiers. */
327 argpos = 0;
329 /* Prepare temporary buffer. */
330 wpsize = 0;
332 /* Check for a positional parameter specification. */
333 if (isdigit (*f))
335 argpos = *f++ - '0';
336 while (isdigit (*f))
337 argpos = argpos * 10 + (*f++ - '0');
338 if (*f == '$')
339 ++f;
340 else
342 /* Oops; that was actually the field width. */
343 width = argpos;
344 flags |= WIDTH;
345 argpos = 0;
346 goto got_width;
350 /* Check for the assignment-suppressing and the number grouping flag. */
351 while (*f == '*' || *f == '\'')
352 switch (*f++)
354 case '*':
355 flags |= SUPPRESS;
356 break;
357 case '\'':
358 flags |= GROUP;
359 break;
362 /* We have seen width. */
363 if (isdigit (*f))
364 flags |= WIDTH;
366 /* Find the maximum field width. */
367 width = 0;
368 while (isdigit (*f))
370 width *= 10;
371 width += *f++ - '0';
373 got_width:
374 if (width == 0)
375 width = -1;
377 /* Check for type modifiers. */
378 while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
379 switch (*f++)
381 case 'h':
382 /* int's are short int's. */
383 if (flags & TYPEMOD)
384 /* Signal illegal format element. */
385 conv_error ();
386 flags |= SHORT;
387 break;
388 case 'l':
389 if (flags & (SHORT|LONGDBL))
390 conv_error ();
391 else if (flags & LONG)
393 /* A double `l' is equivalent to an `L'. */
394 flags &= ~LONG;
395 flags |= LONGDBL;
397 else
398 /* int's are long int's. */
399 flags |= LONG;
400 break;
401 case 'q':
402 case 'L':
403 /* double's are long double's, and int's are long long int's. */
404 if (flags & TYPEMOD)
405 /* Signal illegal format element. */
406 conv_error ();
407 flags |= LONGDBL;
408 break;
409 case 'a':
410 if (flags & TYPEMOD)
411 /* Signal illegal format element. */
412 conv_error ();
413 /* String conversions (%s, %[) take a `char **'
414 arg and fill it in with a malloc'd pointer. */
415 flags |= MALLOC;
416 break;
419 /* End of the format string? */
420 if (*f == '\0')
421 conv_error ();
423 /* We must take care for EINTR errors. */
424 if (c == EOF && errno == EINTR)
425 input_error ();
427 /* Find the conversion specifier. */
428 fc = *f++;
429 if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
431 /* Eat whitespace. */
433 if (inchar () == EOF && errno == EINTR)
434 input_error ();
435 while (isspace (c));
436 ungetc (c, s);
437 skip_space = 0;
440 switch (fc)
442 case '%': /* Must match a literal '%'. */
443 c = inchar ();
444 if (c != fc)
446 ungetc (c, s);
447 conv_error ();
449 break;
451 case 'n': /* Answer number of assignments done. */
452 /* Corrigendum 1 to ISO C 1990 describes the allowed flags
453 with the 'n' conversion specifier. */
454 if (!(flags & SUPPRESS))
456 /* Don't count the read-ahead. */
457 if (flags & LONGDBL)
458 *ARG (long long int *) = read_in;
459 else if (flags & LONG)
460 *ARG (long int *) = read_in;
461 else if (flags & SHORT)
462 *ARG (short int *) = read_in;
463 else
464 *ARG (int *) = read_in;
466 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
467 /* We have a severe problem here. The ISO C standard
468 contradicts itself in explaining the effect of the %n
469 format in `scanf'. While in ISO C:1990 and the ISO C
470 Amendement 1:1995 the result is described as
472 Execution of a %n directive does not effect the
473 assignment count returned at the completion of
474 execution of the f(w)scanf function.
476 in ISO C Corrigendum 1:1994 the following was added:
478 Subclause 7.9.6.2
479 Add the following fourth example:
481 #include <stdio.h>
482 int d1, d2, n1, n2, i;
483 i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
484 the value 123 is assigned to d1 and the value3 to n1.
485 Because %n can never get an input failure the value
486 of 3 is also assigned to n2. The value of d2 is not
487 affected. The value 3 is assigned to i.
489 We go for now with the historically correct code fro ISO C,
490 i.e., we don't count the %n assignments. When it ever
491 should proof to be wrong just remove the #ifdef above. */
492 ++done;
493 #endif
495 break;
497 case 'c': /* Match characters. */
498 if ((flags & LONG) == 0)
500 if (!(flags & SUPPRESS))
502 str = ARG (char *);
503 if (str == NULL)
504 conv_error ();
507 c = inchar ();
508 if (c == EOF)
509 input_error ();
511 if (width == -1)
512 width = 1;
514 if (!(flags & SUPPRESS))
517 *str++ = c;
518 while (--width > 0 && inchar () != EOF);
520 else
521 while (--width > 0 && inchar () != EOF);
523 if (width > 0)
524 /* I.e., EOF was read. */
525 --read_in;
527 if (!(flags & SUPPRESS))
528 ++done;
530 break;
532 /* FALLTHROUGH */
533 case 'C':
534 /* Get UTF-8 encoded wide character. Here we assume (as in
535 other parts of the libc) that we only have to handle
536 UTF-8. */
538 wint_t val;
539 size_t cnt = 0;
540 int first = 1;
542 if (!(flags & SUPPRESS))
544 wstr = ARG (wchar_t *);
545 if (str == NULL)
546 conv_error ();
551 #define NEXT_WIDE_CHAR(First) \
552 c = inchar (); \
553 if (c == EOF) \
554 /* EOF is only an error for the first character. */ \
555 if (First) \
556 input_error (); \
557 else \
559 --read_in; \
560 break; \
562 val = c; \
563 if (val >= 0x80) \
565 if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
566 encode_error (); \
567 if ((c & 0xe0) == 0xc0) \
569 /* We expect two bytes. */ \
570 cnt = 1; \
571 val &= 0x1f; \
573 else if ((c & 0xf0) == 0xe0) \
575 /* We expect three bytes. */ \
576 cnt = 2; \
577 val &= 0x0f; \
579 else if ((c & 0xf8) == 0xf0) \
581 /* We expect four bytes. */ \
582 cnt = 3; \
583 val &= 0x07; \
585 else if ((c & 0xfc) == 0xf8) \
587 /* We expect five bytes. */ \
588 cnt = 4; \
589 val &= 0x03; \
591 else \
593 /* We expect six bytes. */ \
594 cnt = 5; \
595 val &= 0x01; \
598 do \
600 c = inchar (); \
601 if (c == EOF \
602 || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \
603 encode_error (); \
604 val <<= 6; \
605 val |= c & 0x3f; \
607 while (--cnt > 0); \
610 if (!(flags & SUPPRESS)) \
611 *wstr++ = val; \
612 first = 0
614 NEXT_WIDE_CHAR (first);
616 while (--width > 0);
618 if (width > 0)
619 /* I.e., EOF was read. */
620 --read_in;
622 if (!(flags & SUPPRESS))
623 ++done;
625 break;
627 case 's': /* Read a string. */
628 if (flags & LONG)
629 /* We have to process a wide character string. */
630 goto wide_char_string;
632 #define STRING_ARG(Str, Type) \
633 if (!(flags & SUPPRESS)) \
635 if (flags & MALLOC) \
637 /* The string is to be stored in a malloc'd buffer. */ \
638 strptr = ARG (char **); \
639 if (strptr == NULL) \
640 conv_error (); \
641 /* Allocate an initial buffer. */ \
642 strsize = 100; \
643 *strptr = malloc (strsize * sizeof (Type)); \
644 Str = (Type *) *strptr; \
646 else \
647 Str = ARG (Type *); \
648 if (Str == NULL) \
649 conv_error (); \
651 STRING_ARG (str, char);
653 c = inchar ();
654 if (c == EOF)
655 input_error ();
659 if (isspace (c))
661 ungetc (c, s);
662 break;
664 #define STRING_ADD_CHAR(Str, c, Type) \
665 if (!(flags & SUPPRESS)) \
667 *Str++ = c; \
668 if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \
670 /* Enlarge the buffer. */ \
671 Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \
672 if (Str == NULL) \
674 /* Can't allocate that much. Last-ditch effort. */\
675 Str = realloc (*strptr, \
676 (strsize + 1) * sizeof (Type)); \
677 if (Str == NULL) \
679 /* We lose. Oh well. \
680 Terminate the string and stop converting, \
681 so at least we don't skip any input. */ \
682 ((Type *) (*strptr))[strsize] = '\0'; \
683 ++done; \
684 conv_error (); \
686 else \
688 *strptr = (char *) Str; \
689 Str = ((Type *) *strptr) + strsize; \
690 ++strsize; \
693 else \
695 *strptr = (char *) Str; \
696 Str = ((Type *) *strptr) + strsize; \
697 strsize *= 2; \
701 STRING_ADD_CHAR (str, c, char);
702 } while ((width <= 0 || --width > 0) && inchar () != EOF);
704 if (c == EOF)
705 --read_in;
707 if (!(flags & SUPPRESS))
709 *str = '\0';
710 ++done;
712 break;
714 case 'S':
715 /* Wide character string. */
716 wide_char_string:
718 wint_t val;
719 int first = 1;
720 STRING_ARG (wstr, wchar_t);
724 size_t cnt = 0;
725 NEXT_WIDE_CHAR (first);
727 if (iswspace (val))
729 /* XXX We would have to push back the whole wide char
730 with possibly many bytes. But since scanf does
731 not make a difference for white space characters
732 we can simply push back a simple <SP> which is
733 guaranteed to be in the [:space:] class. */
734 ungetc (' ', s);
735 break;
738 STRING_ADD_CHAR (wstr, val, wchar_t);
739 first = 0;
741 while (width <= 0 || --width > 0);
743 if (!(flags & SUPPRESS))
745 *wstr = L'\0';
746 ++done;
749 break;
751 case 'x': /* Hexadecimal integer. */
752 case 'X': /* Ditto. */
753 base = 16;
754 number_signed = 0;
755 goto number;
757 case 'o': /* Octal integer. */
758 base = 8;
759 number_signed = 0;
760 goto number;
762 case 'u': /* Unsigned decimal integer. */
763 base = 10;
764 number_signed = 0;
765 goto number;
767 case 'd': /* Signed decimal integer. */
768 base = 10;
769 number_signed = 1;
770 goto number;
772 case 'i': /* Generic number. */
773 base = 0;
774 number_signed = 1;
776 number:
777 c = inchar ();
778 if (c == EOF)
779 input_error ();
781 /* Check for a sign. */
782 if (c == '-' || c == '+')
784 ADDW (c);
785 if (width > 0)
786 --width;
787 c = inchar ();
790 /* Look for a leading indication of base. */
791 if (width != 0 && c == '0')
793 if (width > 0)
794 --width;
796 ADDW (c);
797 c = inchar ();
799 if (width != 0 && tolower (c) == 'x')
801 if (base == 0)
802 base = 16;
803 if (base == 16)
805 if (width > 0)
806 --width;
807 c = inchar ();
810 else if (base == 0)
811 base = 8;
814 if (base == 0)
815 base = 10;
817 /* Read the number into workspace. */
818 while (c != EOF && width != 0)
820 if (base == 16 ? !isxdigit (c) :
821 ((!isdigit (c) || c - '0' >= base) &&
822 !((flags & GROUP) && base == 10 && c == thousands)))
823 break;
824 ADDW (c);
825 if (width > 0)
826 --width;
828 c = inchar ();
831 /* The just read character is not part of the number anymore. */
832 ungetc (c, s);
834 if (wpsize == 0 ||
835 (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
836 /* There was no number. */
837 conv_error ();
839 /* Convert the number. */
840 ADDW ('\0');
841 if (flags & LONGDBL)
843 if (number_signed)
844 num.q = __strtoq_internal (wp, &tw, base, flags & GROUP);
845 else
846 num.uq = __strtouq_internal (wp, &tw, base, flags & GROUP);
848 else
850 if (number_signed)
851 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
852 else
853 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
855 if (wp == tw)
856 conv_error ();
858 if (!(flags & SUPPRESS))
860 if (! number_signed)
862 if (flags & LONGDBL)
863 *ARG (unsigned LONGLONG int *) = num.uq;
864 else if (flags & LONG)
865 *ARG (unsigned long int *) = num.ul;
866 else if (flags & SHORT)
867 *ARG (unsigned short int *)
868 = (unsigned short int) num.ul;
869 else
870 *ARG (unsigned int *) = (unsigned int) num.ul;
872 else
874 if (flags & LONGDBL)
875 *ARG (LONGLONG int *) = num.q;
876 else if (flags & LONG)
877 *ARG (long int *) = num.l;
878 else if (flags & SHORT)
879 *ARG (short int *) = (short int) num.l;
880 else
881 *ARG (int *) = (int) num.l;
883 ++done;
885 break;
887 case 'e': /* Floating-point numbers. */
888 case 'E':
889 case 'f':
890 case 'g':
891 case 'G':
892 c = inchar ();
893 if (c == EOF)
894 input_error ();
896 /* Check for a sign. */
897 if (c == '-' || c == '+')
899 negative = c == '-';
900 if (inchar () == EOF)
901 /* EOF is only an input error before we read any chars. */
902 conv_error ();
903 if (width > 0)
904 --width;
906 else
907 negative = 0;
909 got_dot = got_e = 0;
912 if (isdigit (c))
913 ADDW (c);
914 else if (got_e && wp[wpsize - 1] == 'e'
915 && (c == '-' || c == '+'))
916 ADDW (c);
917 else if (wpsize > 0 && !got_e && tolower (c) == 'e')
919 ADDW ('e');
920 got_e = got_dot = 1;
922 else if (c == decimal && !got_dot)
924 ADDW (c);
925 got_dot = 1;
927 else if ((flags & GROUP) && c == thousands && !got_dot)
928 ADDW (c);
929 else
930 break;
931 if (width > 0)
932 --width;
934 while (inchar () != EOF && width != 0);
936 /* The last read character is not part of the number anymore. */
937 ungetc (c, s);
939 if (wpsize == 0)
940 conv_error ();
942 /* Convert the number. */
943 ADDW ('\0');
944 if (flags & LONGDBL)
946 long double d = __strtold_internal (wp, &tw, flags & GROUP);
947 if (!(flags & SUPPRESS) && tw != wp)
948 *ARG (long double *) = negative ? -d : d;
950 else if (flags & LONG)
952 double d = __strtod_internal (wp, &tw, flags & GROUP);
953 if (!(flags & SUPPRESS) && tw != wp)
954 *ARG (double *) = negative ? -d : d;
956 else
958 float d = __strtof_internal (wp, &tw, flags & GROUP);
959 if (!(flags & SUPPRESS) && tw != wp)
960 *ARG (float *) = negative ? -d : d;
963 if (tw == wp)
964 conv_error ();
966 if (!(flags & SUPPRESS))
967 ++done;
968 break;
970 case '[': /* Character class. */
971 if (flags & LONG)
973 STRING_ARG (wstr, wchar_t);
974 c = '\0'; /* This is to keep gcc quiet. */
976 else
978 STRING_ARG (str, char);
980 c = inchar ();
981 if (c == EOF)
982 input_error ();
985 if (*f == '^')
987 ++f;
988 not_in = 1;
990 else
991 not_in = 0;
993 /* Fill WP with byte flags indexed by character.
994 We will use this flag map for matching input characters. */
995 if (wpmax < UCHAR_MAX)
997 wpmax = UCHAR_MAX;
998 wp = (char *) alloca (wpmax);
1000 memset (wp, 0, UCHAR_MAX);
1002 fc = *f;
1003 if (fc == ']' || fc == '-')
1005 /* If ] or - appears before any char in the set, it is not
1006 the terminator or separator, but the first char in the
1007 set. */
1008 wp[fc] = 1;
1009 ++f;
1012 while ((fc = *f++) != '\0' && fc != ']')
1014 if (fc == '-' && *f != '\0' && *f != ']' &&
1015 (unsigned char) f[-2] <= (unsigned char) *f)
1017 /* Add all characters from the one before the '-'
1018 up to (but not including) the next format char. */
1019 for (fc = f[-2]; fc < *f; ++fc)
1020 wp[fc] = 1;
1022 else
1023 /* Add the character to the flag map. */
1024 wp[fc] = 1;
1026 if (fc == '\0')
1028 if (!(flags & LONG))
1029 ungetc (c, s);
1030 conv_error();
1033 if (flags & LONG)
1035 wint_t val;
1036 int first = 1;
1040 size_t cnt = 0;
1041 NEXT_WIDE_CHAR (first);
1042 if (val > 255 || wp[val] == not_in)
1044 /* XXX We have a problem here. We read a wide
1045 character and this possibly took several
1046 bytes. But we can only push back one single
1047 character. To be sure we don't create wrong
1048 input we push it back only in case it is
1049 representable within one byte. */
1050 if (val < 0x80)
1051 ungetc (val, s);
1052 break;
1054 STRING_ADD_CHAR (wstr, val, wchar_t);
1055 if (width > 0)
1056 --width;
1057 first = 0;
1059 while (width != 0);
1061 if (first)
1062 conv_error ();
1064 if (!(flags & SUPPRESS))
1066 *wstr = L'\0';
1067 ++done;
1070 else
1072 num.ul = read_in - 1; /* -1 because we already read one char. */
1075 if (wp[c] == not_in)
1077 ungetc (c, s);
1078 break;
1080 STRING_ADD_CHAR (str, c, char);
1081 if (width > 0)
1082 --width;
1084 while (width != 0 && inchar () != EOF);
1086 if (read_in == num.ul)
1087 conv_error ();
1089 if (!(flags & SUPPRESS))
1091 *str = '\0';
1092 ++done;
1095 break;
1097 case 'p': /* Generic pointer. */
1098 base = 16;
1099 /* A PTR must be the same size as a `long int'. */
1100 flags &= ~(SHORT|LONGDBL);
1101 flags |= LONG;
1102 number_signed = 0;
1103 goto number;
1107 /* The last thing we saw int the format string was a white space.
1108 Consume the last white spaces. */
1109 if (skip_space)
1112 c = inchar ();
1113 while (isspace (c));
1114 ungetc (c, s);
1117 /* Unlock stream. */
1118 UNLOCK_STREAM;
1120 return done;
1123 #ifdef USE_IN_LIBIO
1125 __vfscanf (FILE *s, const char *format, va_list argptr)
1127 return _IO_vfscanf (s, format, argptr, NULL);
1129 #endif
1131 weak_alias (__vfscanf, vfscanf)