update for HEAD-2003091401
[reactos.git] / lib / msvcrt / stdio / vfscanf.c
1 /* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
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.
8
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.
13
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.  */
18
19 //#include <stdarg.h>
20 #include <msvcrt/stdarg.h> // robd
21 #include <msvcrt/crttypes.h> // robd
22
23 #include <msvcrt/errno.h>
24 #include <limits.h>
25 #include <msvcrt/ctype.h>
26 #include <msvcrt/stdio.h>
27 #include <msvcrt/stdlib.h>
28 #include <msvcrt/string.h>
29 #include <msvcrt/wchar.h>
30 #include <msvcrt/malloc.h>
31 #include <msvcrt/mbstring.h>
32 #include <msvcrt/internal/file.h>
33 #include <msvcrt/internal/stdio.h>
34
35 /* The internal entry points for `strtoX' take an extra flag argument
36    saying whether or not to parse locale-dependent number grouping.  */
37
38 double __strtod_internal  (const char *__nptr,char **__endptr, int __group);
39 float __strtof_internal (const char *__nptr, char **__endptr,int __group);
40 long double __strtold_internal  (const char *__nptr,char **__endptr, int __group);
41 long int __strtol_internal (const char *__nptr, char **__endptr,        int __base, int __group);
42 unsigned long int __strtoul_internal  (const char *__nptr,  char **__endptr, int __base, int __group);
43
44
45 #include <msvcrt/crttypes.h> // robd
46 //#ifdef        __GNUC__
47 //#define       HAVE_LONGLONG
48 //#define       LONGLONG        LONGLONG
49 //#else
50 //#define       LONGLONG        long
51 //#endif
52
53 /* Those are flags in the conversion format. */
54 # define LONG           0x001   /* l: long or double */
55 # define LONGDBL        0x002   /* L: LONGLONG or long double */
56 # define SHORT          0x004   /* h: short */
57 # define SUPPRESS       0x008   /* *: suppress assignment */
58 # define POINTER        0x010   /* weird %p pointer (`fake hex') */
59 # define NOSKIP         0x020   /* do not skip blanks */
60 # define WIDTH          0x040   /* width was given */
61 # define GROUP          0x080   /* ': group numbers */
62 # define MALLOC         0x100   /* a: malloc strings */
63
64 # define TYPEMOD        (LONG|LONGDBL|SHORT)
65
66
67 # define UNGETC(c, s)   ((void) (((wint_t)c) != ((wint_t)EOF) && --read_in), ungetc (c, s))
68 # define inchar()       ((c = getc (s)), (void) (c != EOF && ++read_in), c)
69 # define encode_error() do {                                                  \
70                           funlockfile (s);                                    \
71                           __set_errno (EILSEQ);                               \
72                           return done;                                        \
73                         } while (0)
74 # define conv_error()   do {                                                  \
75                           funlockfile (s);                                    \
76                           return done;                                        \
77                         } while (0)
78 # define input_error()  do {                                                  \
79                           funlockfile (s);                                    \
80                           return done ? 0 : EOF;                              \
81                         } while (0)
82 # define memory_error() do {                                                  \
83                           funlockfile (s);                                    \
84                           __set_errno (ENOMEM);                               \
85                           return EOF;                                         \
86                         } while (0)
87 # define ARGCHECK(s, format)                                                  \
88   do                                                                          \
89     {                                                                         \
90       /* Check file argument for consistence.  */                             \
91       if (!__validfp (s) || !s->__mode.__read)                                \
92         {                                                                     \
93           __set_errno (EBADF);                                                \
94           return EOF;                                                         \
95         }                                                                     \
96       else if (format == NULL)                                                \
97         {                                                                     \
98           __set_errno (EINVAL);                                               \
99           return EOF;                                                         \
100         }                                                                     \
101     } while (0)
102
103 # define flockfile(S) /* nothing */
104 # define funlockfile(S) /* nothing */
105
106 # define ADDW(Ch)                                                             \
107 do{                                                                           \
108   if (wpsize == wpmax)                                                        \
109     {                                                                         \
110       char *old = wp;                                                         \
111       wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax;                  \
112       wp = (char *) malloc (wpmax);                                           \
113       if (old != NULL)                                                        \
114         {                                                                     \
115           memcpy (wp, old, wpsize);                                           \
116           free(old);                                                          \
117         }                                                                     \
118     }                                                                         \
119   wp[wpsize++] = (Ch);                                                        \
120 }while(0)
121
122
123 int __vfscanf (FILE *s, const char *format, va_list argptr)
124 {
125   va_list arg;
126   register const char *f = format;
127   register unsigned char fc;    /* Current character of the format.  */
128   register size_t done = 0;     /* Assignments done.  */
129   register size_t read_in = 0;  /* Chars read in.  */
130   register int c = 0;           /* Last char read.  */
131   register int width;           /* Maximum field width.  */
132   register int flags;           /* Modifiers for current format element.  */
133
134   /* Status for reading F-P nums.  */
135   char got_dot, got_e, negative;
136   /* If a [...] is a [^...].  */
137   char not_in;
138   /* Base for integral numbers.  */
139   int base;
140   /* Signedness for integral numbers.  */
141   int number_signed;
142   /* Decimal point character.  */
143   wchar_t decimal = '.';
144   /* The thousands character of the current locale.  */
145   wchar_t thousands = ',';
146   /* Integral holding variables.  */
147   union
148     {
149       LONGLONG q;
150       ULONGLONG uq;
151       long int l;
152       unsigned long int ul;
153     } num;
154   /* Character-buffer pointer.  */
155   char *str = NULL;
156   wchar_t *wstr = NULL;
157   char **strptr = NULL;
158   size_t strsize = 0;
159   /* We must not react on white spaces immediately because they can
160      possibly be matched even if in the input stream no character is
161      available anymore.  */
162   int skip_space = 0;
163   /* Workspace.  */
164   char *wp = NULL;              /* Workspace.  */
165   size_t wpmax = 0;             /* Maximal size of workspace.  */
166   size_t wpsize = 0;            /* Currently used bytes in workspace.  */
167   char *tw;                     /* Temporary pointer.  */
168
169 #ifdef __va_copy
170   __va_copy (arg, argptr);
171 #else
172   arg = (va_list) argptr;
173 #endif
174
175
176
177   /* Run through the format string.  */
178   while (*f != '\0')
179     {
180       unsigned int argpos;
181       /* Extract the next argument, which is of type TYPE.
182          For a %N$... spec, this is the Nth argument from the beginning;
183          otherwise it is the next argument after the state now in ARG.  */
184 #define ARG(type)       va_arg(argptr,type)
185
186       if (!isascii (*f))
187         {
188           /* Non-ASCII, may be a multibyte.  */
189          // int len = mblen (f, strlen (f));
190         int len =1;
191           if (len > 0)
192             {
193               do
194                 {
195                   c = inchar ();
196                   if (c == EOF)
197                     input_error ();
198                   else if (c != *f++)
199                     {
200                       UNGETC (c, s);
201                       conv_error ();
202                     }
203                 }
204               while (--len > 0);
205               continue;
206             }
207         }
208
209       fc = *f++;
210       if (fc != '%')
211         {
212           /* Remember to skip spaces.  */
213           if (isspace (fc))
214             {
215               skip_space = 1;
216               continue;
217             }
218
219           /* Read a character.  */
220           c = inchar ();
221
222           /* Characters other than format specs must just match.  */
223           if (c == EOF)
224             input_error ();
225
226           /* We saw white space char as the last character in the format
227              string.  Now it's time to skip all leading white space.  */
228           if (skip_space)
229             {
230               while (isspace (c))
231                 if (inchar () == EOF && *_errno() == EINTR)
232                   conv_error ();
233               skip_space = 0;
234             }
235
236           if (c != fc)
237             {
238               UNGETC (c, s);
239               conv_error ();
240             }
241
242           continue;
243         }
244
245       /* This is the start of the conversion string. */
246       flags = 0;
247
248       /* Initialize state of modifiers.  */
249       argpos = 0;
250
251       /* Prepare temporary buffer.  */
252       wpsize = 0;
253
254       /* Check for a positional parameter specification.  */
255       if (isdigit (*f))
256         {
257           argpos = *f++ - '0';
258           while (isdigit (*f))
259             argpos = argpos * 10 + (*f++ - '0');
260           if (*f == '$')
261             ++f;
262           else
263             {
264               /* Oops; that was actually the field width.  */
265               width = argpos;
266               flags |= WIDTH;
267               argpos = 0;
268               goto got_width;
269             }
270         }
271
272       /* Check for the assignment-suppressing and the number grouping flag.  */
273       while (*f == '*' || *f == '\'')
274         switch (*f++)
275           {
276           case '*':
277             flags |= SUPPRESS;
278             break;
279           case '\'':
280             flags |= GROUP;
281             break;
282           }
283
284       /* We have seen width. */
285       if (isdigit (*f))
286         flags |= WIDTH;
287
288       /* Find the maximum field width.  */
289       width = 0;
290       while (isdigit (*f))
291         {
292           width *= 10;
293           width += *f++ - '0';
294         }
295     got_width:
296       if (width == 0)
297         width = -1;
298
299       /* Check for type modifiers.  */
300       while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q')
301         switch (*f++)
302           {
303           case 'h':
304             /* int's are short int's.  */
305             if (flags & TYPEMOD)
306               /* Signal illegal format element.  */
307               conv_error ();
308             flags |= SHORT;
309             break;
310           case 'l':
311             if (flags & (SHORT|LONGDBL))
312               conv_error ();
313             else if (flags & LONG)
314               {
315                 /* A double `l' is equivalent to an `L'.  */
316                 flags &= ~LONG;
317                 flags |= LONGDBL;
318               }
319             else
320               /* int's are long int's.  */
321               flags |= LONG;
322             break;
323           case 'q':
324           case 'L':
325             /* double's are long double's, and int's are LONGLONG int's.  */
326             if (flags & TYPEMOD)
327               /* Signal illegal format element.  */
328               conv_error ();
329             flags |= LONGDBL;
330             break;
331           case 'a':
332             if (flags & TYPEMOD)
333               /* Signal illegal format element.  */
334               conv_error ();
335             /* String conversions (%s, %[) take a `char **'
336                arg and fill it in with a malloc'd pointer.  */
337             flags |= MALLOC;
338             break;
339           }
340
341       /* End of the format string?  */
342       if (*f == '\0')
343         conv_error ();
344
345       /* We must take care for EINTR errors.  */
346       if (c == EOF && *_errno() == EINTR)
347         input_error ();
348
349       /* Find the conversion specifier.  */
350       fc = *f++;
351       if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n'))
352         {
353           /* Eat whitespace.  */
354           do
355             if (inchar () == EOF && *_errno() == EINTR)
356               input_error ();
357           while (isspace (c));
358           UNGETC (c, s);
359           skip_space = 0;
360         }
361
362       switch (fc)
363         {
364         case '%':       /* Must match a literal '%'.  */
365           c = inchar ();
366           if (c != fc)
367             {
368               UNGETC (c, s);
369               conv_error ();
370             }
371           break;
372
373         case 'n':       /* Answer number of assignments done.  */
374           /* Corrigendum 1 to ISO C 1990 describes the allowed flags
375              with the 'n' conversion specifier.  */
376           if (!(flags & SUPPRESS))
377             {
378               /* Don't count the read-ahead.  */
379               if (flags & LONGDBL)
380                 *ARG (long int *) = read_in;
381               else if (flags & LONG)
382                 *ARG (long int *) = read_in;
383               else if (flags & SHORT)
384                 *ARG (short int *) = read_in;
385               else
386                 *ARG (int *) = read_in;
387
388 #ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1
389               /* We have a severe problem here.  The ISO C standard
390                  contradicts itself in explaining the effect of the %n
391                  format in `scanf'.  While in ISO C:1990 and the ISO C
392                  Amendement 1:1995 the result is described as
393
394                    Execution of a %n directive does not effect the
395                    assignment count returned at the completion of
396                    execution of the f(w)scanf function.
397
398                  in ISO C Corrigendum 1:1994 the following was added:
399
400                    Subclause 7.9.6.2
401                    Add the following fourth example:
402                      In:
403                        #include <stdio.h>
404                        int d1, d2, n1, n2, i;
405                        i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
406                      the value 123 is assigned to d1 and the value3 to n1.
407                      Because %n can never get an input failure the value
408                      of 3 is also assigned to n2.  The value of d2 is not
409                      affected.  The value 3 is assigned to i.
410
411                  We go for now with the historically correct code fro ISO C,
412                  i.e., we don't count the %n assignments.  When it ever
413                  should proof to be wrong just remove the #ifdef above.  */
414               ++done;
415 #endif
416             }
417           break;
418
419         case 'c':       /* Match characters.  */
420           if ((flags & LONG) == 0)
421             {
422               if (!(flags & SUPPRESS))
423                 {
424                   str = ARG (char *);
425                   if (str == NULL)
426                     conv_error ();
427                 }
428
429               c = inchar ();
430               if (c == EOF)
431                 input_error ();
432
433               if (width == -1)
434                 width = 1;
435
436               if (!(flags & SUPPRESS))
437                 {
438                   do
439                     *str++ = c;
440                   while (--width > 0 && inchar () != EOF);
441                 }
442               else
443                 while (--width > 0 && inchar () != EOF);
444
445               if (width > 0)
446                 /* I.e., EOF was read.  */
447                 --read_in;
448
449               if (!(flags & SUPPRESS))
450                 ++done;
451
452               break;
453             }
454           /* FALLTHROUGH */
455         case 'C':
456           /* Get UTF-8 encoded wide character.  Here we assume (as in
457              other parts of the libc) that we only have to handle
458              UTF-8.  */
459           {
460             wint_t val;
461             size_t cnt = 0;
462             int first = 1;
463
464             if (!(flags & SUPPRESS))
465               {
466                 wstr = ARG (wchar_t *);
467                 if (str == NULL)
468                   conv_error ();
469               }
470
471             do
472               {
473 #define NEXT_WIDE_CHAR(First)                                                 \
474                 c = inchar ();                                                \
475                 if (c == EOF)   {                                             \
476                   /* EOF is only an error for the first character.  */        \
477                   if (First) {                                                \
478                     input_error ();                                           \
479                   }                                                           \
480                   else                                                        \
481                     {                                                         \
482                       --read_in;                                              \
483                       break;                                                  \
484                     }                                                   \
485                 }                                                     \
486                 val = c;                                                      \
487                 if (val >= 0x80)                                              \
488                   {                                                           \
489                     if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe)             \
490                       encode_error ();                                        \
491                     if ((c & 0xe0) == 0xc0)                                   \
492                       {                                                       \
493                         /* We expect two bytes.  */                           \
494                         cnt = 1;                                              \
495                         val &= 0x1f;                                          \
496                       }                                                       \
497                     else if ((c & 0xf0) == 0xe0)                              \
498                       {                                                       \
499                         /* We expect three bytes.  */                         \
500                         cnt = 2;                                              \
501                         val &= 0x0f;                                          \
502                       }                                                       \
503                     else if ((c & 0xf8) == 0xf0)                              \
504                       {                                                       \
505                         /* We expect four bytes.  */                          \
506                         cnt = 3;                                              \
507                         val &= 0x07;                                          \
508                       }                                                       \
509                     else if ((c & 0xfc) == 0xf8)                              \
510                       {                                                       \
511                         /* We expect five bytes.  */                          \
512                         cnt = 4;                                              \
513                         val &= 0x03;                                          \
514                       }                                                       \
515                     else                                                      \
516                       {                                                       \
517                         /* We expect six bytes.  */                           \
518                         cnt = 5;                                              \
519                         val &= 0x01;                                          \
520                       }                                                       \
521                                                                               \
522                     do                                                        \
523                       {                                                       \
524                         c = inchar ();                                        \
525                         if (c == EOF                                          \
526                             || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe)      \
527                           encode_error ();                                    \
528                         val <<= 6;                                            \
529                         val |= c & 0x3f;                                      \
530                       }                                                       \
531                     while (--cnt > 0);                                        \
532                   }                                                           \
533                                                                               \
534                 if (!(flags & SUPPRESS))                                      \
535                   *wstr++ = val;                                              \
536                 first = 0
537
538                 NEXT_WIDE_CHAR (first);
539               }
540             while (--width > 0);
541
542             if (width > 0)
543               /* I.e., EOF was read.  */
544               --read_in;
545
546             if (!(flags & SUPPRESS))
547               ++done;
548           }
549           break;
550
551         case 's':               /* Read a string.  */
552           if (flags & LONG)
553             /* We have to process a wide character string.  */
554             goto wide_char_string;
555
556 #define STRING_ARG(Str, Type)                                                 \
557           if (!(flags & SUPPRESS))                                            \
558             {                                                                 \
559               if (flags & MALLOC)                                             \
560                 {                                                             \
561                   /* The string is to be stored in a malloc'd buffer.  */     \
562                   strptr = ARG (char **);                                     \
563                   if (strptr == NULL)                                         \
564                     conv_error ();                                            \
565                   /* Allocate an initial buffer.  */                          \
566                   strsize = 100;                                              \
567                   *strptr = malloc (strsize * sizeof (Type));                 \
568                   Str = (Type *) *strptr;                                     \
569                 }                                                             \
570               else                                                            \
571                 Str = ARG (Type *);                                           \
572               if (Str == NULL)                                                \
573                 conv_error ();                                                \
574             }
575           STRING_ARG (str, char);
576
577           c = inchar ();
578           if (c == EOF)
579             input_error ();
580
581           do
582             {
583               if (isspace (c))
584                 {
585                   UNGETC (c, s);
586                   break;
587                 }
588 #define STRING_ADD_CHAR(Str, c, Type)                                         \
589               if (!(flags & SUPPRESS))                                        \
590                 {                                                             \
591                   *Str++ = c;                                                 \
592                   if ((flags & MALLOC) && (char *) Str == *strptr + strsize)  \
593                     {                                                         \
594                       /* Enlarge the buffer.  */                              \
595                       Str = realloc (*strptr, strsize * 2 * sizeof (Type));   \
596                       if (Str == NULL)                                        \
597                         {                                                     \
598                           /* Can't allocate that much.  Last-ditch effort.  */\
599                           Str = realloc (*strptr,                             \
600                                          (strsize + 1) * sizeof (Type));      \
601                           if (Str == NULL)                                    \
602                             {                                                 \
603                               /* We lose.  Oh well.                           \
604                                  Terminate the string and stop converting,    \
605                                  so at least we don't skip any input.  */     \
606                               ((Type *) (*strptr))[strsize] = '\0';           \
607                               ++done;                                         \
608                               conv_error ();                                  \
609                             }                                                 \
610                           else                                                \
611                             {                                                 \
612                               *strptr = (char *) Str;                         \
613                               Str = ((Type *) *strptr) + strsize;             \
614                               ++strsize;                                      \
615                             }                                                 \
616                         }                                                     \
617                       else                                                    \
618                         {                                                     \
619                           *strptr = (char *) Str;                             \
620                           Str = ((Type *) *strptr) + strsize;                 \
621                           strsize *= 2;                                       \
622                         }                                                     \
623                     }                                                         \
624                 }
625               STRING_ADD_CHAR (str, c, char);
626             } while ((width <= 0 || --width > 0) && inchar () != EOF);
627
628           if (!(flags & SUPPRESS))
629             {
630               *str = '\0';
631               ++done;
632             }
633           break;
634
635         case 'S':
636           /* Wide character string.  */
637         wide_char_string:
638           {
639             wint_t val;
640             int first = 1;
641             STRING_ARG (wstr, wchar_t);
642
643             do
644               {
645                 size_t cnt = 0;
646                 NEXT_WIDE_CHAR (first);
647
648                 if (iswspace (val))
649                   {
650                     /* XXX We would have to push back the whole wide char
651                        with possibly many bytes.  But since scanf does
652                        not make a difference for white space characters
653                        we can simply push back a simple <SP> which is
654                        guaranteed to be in the [:space:] class.  */
655                     UNGETC (' ', s);
656                     break;
657                   }
658
659                 STRING_ADD_CHAR (wstr, val, wchar_t);
660                 first = 0;
661               }
662             while (width <= 0 || --width > 0);
663
664             if (!(flags & SUPPRESS))
665               {
666                 *wstr = L'\0';
667                 ++done;
668               }
669           }
670           break;
671
672         case 'x':       /* Hexadecimal integer.  */
673         case 'X':       /* Ditto.  */
674           base = 16;
675           number_signed = 0;
676           goto number;
677
678         case 'o':       /* Octal integer.  */
679           base = 8;
680           number_signed = 0;
681           goto number;
682
683         case 'u':       /* Unsigned decimal integer.  */
684           base = 10;
685           number_signed = 0;
686           goto number;
687
688         case 'd':       /* Signed decimal integer.  */
689           base = 10;
690           number_signed = 1;
691           goto number;
692
693         case 'i':       /* Generic number.  */
694           base = 0;
695           number_signed = 1;
696
697         number:
698           c = inchar ();
699           if (c == EOF)
700             input_error ();
701
702           /* Check for a sign.  */
703           if (c == '-' || c == '+')
704             {
705               ADDW (c);
706               if (width > 0)
707                 --width;
708               c = inchar ();
709             }
710
711           /* Look for a leading indication of base.  */
712           if (width != 0 && c == '0')
713             {
714               if (width > 0)
715                 --width;
716
717               ADDW (c);
718               c = inchar ();
719
720               if (width != 0 && tolower (c) == 'x')
721                 {
722                   if (base == 0)
723                     base = 16;
724                   if (base == 16)
725                     {
726                       if (width > 0)
727                         --width;
728                       c = inchar ();
729                     }
730                 }
731               else if (base == 0)
732                 base = 8;
733             }
734
735           if (base == 0)
736             base = 10;
737
738           /* Read the number into workspace.  */
739           while (c != EOF && width != 0)
740             {
741               if (base == 16 ? !isxdigit (c) :
742                   ((!isdigit (c) || c - '0' >= base) &&
743                    !((flags & GROUP) && base == 10 && c == thousands)))
744                 break;
745               ADDW (c);
746               if (width > 0)
747                 --width;
748
749               c = inchar ();
750             }
751
752           /* The just read character is not part of the number anymore.  */
753           UNGETC (c, s);
754
755           if (wpsize == 0 ||
756               (wpsize == 1 && (wp[0] == '+' || wp[0] == '-')))
757             /* There was no number.  */
758             conv_error ();
759
760           /* Convert the number.  */
761           ADDW ('\0');
762           if (flags & LONGDBL)
763             {
764 //            if (number_signed)
765 //              num.q = __strtoq_internal (wp, &tw, base, flags & GROUP);
766 //            else
767 //              num.uq = __strtouq_internal (wp, &tw, base, flags & GROUP);
768             }
769           else
770             {
771               if (number_signed)
772                 num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
773               else
774                 num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
775             }
776           if (wp == tw)
777             conv_error ();
778
779           if (!(flags & SUPPRESS))
780           {
781             if (! number_signed)
782                 {
783                         if (flags & LONGDBL) {
784                                 *ARG (ULONGLONG*) = num.uq;
785                         }
786                         else if (flags & LONG)
787                                 *ARG (unsigned long int*) = num.ul;
788                         else if (flags & SHORT)
789                                 *ARG (unsigned short int*) = (unsigned short int) num.ul;
790                         else
791                                 *ARG (unsigned int*) = (unsigned int) num.ul;
792                 }
793             else
794                 {
795                         if (flags & LONGDBL) {
796                             *ARG (LONGLONG*) = num.q;
797                         }
798                         else if (flags & LONG)
799                                 *ARG (long int *) = num.l;
800                         else if (flags & SHORT)
801                                 *ARG (short int *) = (short int) num.l;
802                         else
803                                 *ARG (int *) = (int) num.l;
804                 }
805             ++done;
806           }
807           break;
808
809         case 'e':       /* Floating-point numbers.  */
810         case 'E':
811         case 'f':
812         case 'g':
813         case 'G':
814           c = inchar ();
815           if (c == EOF)
816             input_error ();
817
818           /* Check for a sign.  */
819           if (c == '-' || c == '+')
820             {
821               negative = c == '-';
822               if (inchar () == EOF)
823                 /* EOF is only an input error before we read any chars.  */
824                 conv_error ();
825               if (width > 0)
826                 --width;
827             }
828           else
829             negative = 0;
830
831           got_dot = got_e = 0;
832           do
833             {
834               if (isdigit (c))
835                 ADDW (c);
836               else if (got_e && wp[wpsize - 1] == 'e'
837                        && (c == '-' || c == '+'))
838                 ADDW (c);
839               else if (wpsize > 0 && !got_e && tolower (c) == 'e')
840                 {
841                   ADDW ('e');
842                   got_e = got_dot = 1;
843                 }
844               else if (c == decimal && !got_dot)
845                 {
846                   ADDW (c);
847                   got_dot = 1;
848                 }
849               else if ((flags & GROUP) && c == thousands && !got_dot)
850                 ADDW (c);
851               else
852                 {
853                   /* The last read character is not part of the number
854                      anymore.  */
855                   UNGETC (c, s);
856                   break;
857                 }
858               if (width > 0)
859                 --width;
860             }
861           while (width != 0 && inchar () != EOF);
862
863           if (wpsize == 0)
864             conv_error ();
865
866           /* Convert the number.  */
867           ADDW ('\0');
868           if (flags & LONGDBL)
869             {
870               long double d = __strtold_internal (wp, &tw, flags & GROUP);
871               if (!(flags & SUPPRESS) && tw != wp)
872                 *ARG (long double *) = negative ? -d : d;
873             }
874           else if (flags & LONG)
875             {
876               double d = __strtod_internal (wp, &tw, flags & GROUP);
877               if (!(flags & SUPPRESS) && tw != wp)
878                 *ARG (double *) = negative ? -d : d;
879             }
880           else
881             {
882               float d = __strtof_internal (wp, &tw, flags & GROUP);
883               if (!(flags & SUPPRESS) && tw != wp)
884                 *ARG (float *) = negative ? -d : d;
885             }
886
887           if (tw == wp)
888             conv_error ();
889
890           if (!(flags & SUPPRESS))
891             ++done;
892           break;
893
894         case '[':       /* Character class.  */
895           if (flags & LONG)
896             {
897               STRING_ARG (wstr, wchar_t);
898               c = '\0';         /* This is to keep gcc quiet.  */
899             }
900           else
901             {
902               STRING_ARG (str, char);
903
904               c = inchar ();
905               if (c == EOF)
906                 input_error ();
907             }
908
909           if (*f == '^')
910             {
911               ++f;
912               not_in = 1;
913             }
914           else
915             not_in = 0;
916
917           /* Fill WP with byte flags indexed by character.
918              We will use this flag map for matching input characters.  */
919           if (wpmax < UCHAR_MAX)
920             {
921               wpmax = UCHAR_MAX;
922               wp = (char *) alloca (wpmax);
923             }
924           memset (wp, 0, UCHAR_MAX);
925
926           fc = *f;
927           if (fc == ']' || fc == '-')
928             {
929               /* If ] or - appears before any char in the set, it is not
930                  the terminator or separator, but the first char in the
931                  set.  */
932               wp[fc] = 1;
933               ++f;
934             }
935
936           while ((fc = *f++) != '\0' && fc != ']')
937             {
938               if (fc == '-' && *f != '\0' && *f != ']' &&
939                   (unsigned char) f[-2] <= (unsigned char) *f)
940                 {
941                   /* Add all characters from the one before the '-'
942                      up to (but not including) the next format char.  */
943                   for (fc = f[-2]; fc < *f; ++fc)
944                     wp[fc] = 1;
945                 }
946               else
947                 /* Add the character to the flag map.  */
948                 wp[fc] = 1;
949             }
950           if (fc == '\0')
951             {
952               if (!(flags & LONG))
953                 UNGETC (c, s);
954               conv_error();
955             }
956
957           if (flags & LONG)
958             {
959               wint_t val;
960               int first = 1;
961
962               do
963                 {
964                   size_t cnt = 0;
965                   NEXT_WIDE_CHAR (first);
966                   if (val > 255 || wp[val] == not_in)
967                     {
968                       /* XXX We have a problem here.  We read a wide
969                          character and this possibly took several
970                          bytes.  But we can only push back one single
971                          character.  To be sure we don't create wrong
972                          input we push it back only in case it is
973                          representable within one byte.  */
974                       if (val < 0x80)
975                         UNGETC (val, s);
976                       break;
977                     }
978                   STRING_ADD_CHAR (wstr, val, wchar_t);
979                   if (width > 0)
980                     --width;
981                   first = 0;
982                 }
983               while (width != 0);
984
985               if (first)
986                 conv_error ();
987
988               if (!(flags & SUPPRESS))
989                 {
990                   *wstr = L'\0';
991                   ++done;
992                 }
993             }
994           else
995             {
996               num.ul = read_in - 1; /* -1 because we already read one char.  */
997               do
998                 {
999                   if (wp[c] == not_in)
1000                     {
1001                       UNGETC (c, s);
1002                       break;
1003                     }
1004                   STRING_ADD_CHAR (str, c, char);
1005                   if (width > 0)
1006                     --width;
1007                 }
1008               while (width != 0 && inchar () != EOF);
1009
1010               if (read_in == num.ul)
1011                 conv_error ();
1012
1013               if (!(flags & SUPPRESS))
1014                 {
1015                   *str = '\0';
1016                   ++done;
1017                 }
1018             }
1019           break;
1020
1021         case 'p':       /* Generic pointer.  */
1022           base = 16;
1023           /* A PTR must be the same size as a `long int'.  */
1024           flags &= ~(SHORT|LONGDBL);
1025           flags |= LONG;
1026           number_signed = 0;
1027           goto number;
1028         }
1029     }
1030
1031   /* The last thing we saw int the format string was a white space.
1032      Consume the last white spaces.  */
1033   if (skip_space)
1034     {
1035       do
1036         c = inchar ();
1037       while (isspace (c));
1038       UNGETC (c, s);
1039     }
1040
1041
1042   return done;
1043 }
1044
1045
1046
1047 int
1048 xfscanf(FILE *f, const char *fmt, ...)
1049 {
1050   int r;
1051   va_list a=0;
1052   va_start(a, fmt);
1053   r = __vfscanf(f, fmt, a);
1054   va_end(a);
1055   return r;
1056 }
1057
1058
1059 double __strtod_internal  (const char *__nptr,char **__endptr, int __group)
1060 {
1061         return strtod(__nptr,__endptr);
1062 }
1063 float __strtof_internal (const char *__nptr, char **__endptr,int __group)
1064 {
1065         return (float)strtod(__nptr,__endptr);
1066 }
1067 static double powten[] =
1068 {
1069   1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L,
1070 #ifdef __GNUC__
1071   1e512L, 1e512L*1e512L, 1e2048L, 1e4096L
1072 #else
1073       1e256L, 1e256L, 1e256L, 1e256L
1074 #endif
1075 };
1076
1077 long double __strtold_internal  (const char *s,char **sret, int __group)
1078 {
1079         
1080   long double r;                /* result */
1081   int e, ne;                    /* exponent */
1082   int sign;                     /* +- 1.0 */
1083   int esign;
1084   int flags=0;
1085   int l2powm1;
1086
1087   r = 0.0L;
1088   sign = 1;
1089   e = ne = 0;
1090   esign = 1;
1091
1092   while(*s && isspace(*s))
1093     s++;
1094
1095   if (*s == '+')
1096     s++;
1097   else if (*s == '-')
1098   {
1099     sign = -1;
1100     s++;
1101   }
1102
1103   while ((*s >= '0') && (*s <= '9'))
1104   {
1105     flags |= 1;
1106     r *= 10.0L;
1107     r += *s - '0';
1108     s++;
1109   }
1110
1111   if (*s == '.')
1112   {
1113     s++;
1114     while ((*s >= '0') && (*s <= '9'))
1115     {
1116       flags |= 2;
1117       r *= 10.0L;
1118       r += *s - '0';
1119       s++;
1120       ne++;
1121     }
1122   }
1123   if (flags == 0)
1124   {
1125     if (sret)
1126       *sret = (char *)s;
1127     return 0.0L;
1128   }
1129
1130   if ((*s == 'e') || (*s == 'E'))
1131   {
1132     s++;
1133     if (*s == '+')
1134       s++;
1135     else if (*s == '-')
1136     {
1137       s++;
1138       esign = -1;
1139     }
1140     while ((*s >= '0') && (*s <= '9'))
1141     {
1142       e *= 10;
1143       e += *s - '0';
1144       s++;
1145     }
1146   }
1147   if (esign < 0)
1148   {
1149     esign = -esign;
1150     e = -e;
1151   }
1152   e = e - ne;
1153   if (e < -4096)
1154   {
1155     /* possibly subnormal number, 10^e would overflow */
1156     r *= 1.0e-2048L;
1157     e += 2048;
1158   }
1159   if (e < 0)
1160   {
1161     e = -e;
1162     esign = -esign;
1163   }
1164   if (e >= 8192)
1165     e = 8191;
1166   if (e)
1167   {
1168     double d = 1.0L;
1169     l2powm1 = 0;
1170     while (e)
1171     {
1172       if (e & 1)
1173         d *= powten[l2powm1];
1174       e >>= 1;
1175       l2powm1++;
1176     }
1177     if (esign > 0)
1178       r *= d;
1179     else
1180       r /= d;
1181   }
1182   if (sret)
1183     *sret = (char *)s;
1184   return r * sign;
1185
1186   return 0;
1187 }
1188 long int __strtol_internal (const char *__nptr, char **__endptr,        int __base, int __group)
1189 {
1190         return strtol(__nptr,__endptr, __base);
1191 }
1192 unsigned long int __strtoul_internal  (const char *__nptr,  char **__endptr, int __base, int __group)
1193 {
1194         return strtoul(__nptr,__endptr, __base);
1195 }
1196
1197
1198
1199
1200
1201
1202
1203
1204