Upgrade GMP from 4.3.2 to 5.0.2 on the vendor branch
[dragonfly.git] / contrib / gmp / scanf / doscan.c
1 /* __gmp_doscan -- formatted input internals.
2
3    THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY.  THEY'RE ALMOST
4    CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
5    FUTURE GNU MP RELEASES.
6
7 Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
8
9 This file is part of the GNU MP Library.
10
11 The GNU MP Library is free software; you can redistribute it and/or modify
12 it under the terms of the GNU Lesser General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
15
16 The GNU MP Library is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
19 License for more details.
20
21 You should have received a copy of the GNU Lesser General Public License
22 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
23
24 #define _GNU_SOURCE    /* for DECIMAL_POINT in langinfo.h */
25
26 #include "config.h"
27
28 #if HAVE_STDARG
29 #include <stdarg.h>
30 #else
31 #include <varargs.h>
32 #endif
33
34 #include <ctype.h>
35 #include <stddef.h>    /* for ptrdiff_t */
36 #include <stdio.h>
37 #include <stdlib.h>    /* for strtol */
38 #include <string.h>
39
40 #if HAVE_LANGINFO_H
41 #include <langinfo.h>  /* for nl_langinfo */
42 #endif
43
44 #if HAVE_LOCALE_H
45 #include <locale.h>    /* for localeconv */
46 #endif
47
48 #if HAVE_INTTYPES_H
49 # include <inttypes.h> /* for intmax_t */
50 #else
51 # if HAVE_STDINT_H
52 #  include <stdint.h>
53 # endif
54 #endif
55
56 #if HAVE_SYS_TYPES_H
57 #include <sys/types.h> /* for quad_t */
58 #endif
59
60 #include "gmp.h"
61 #include "gmp-impl.h"
62
63
64 /* Change this to "#define TRACE(x) x" for some traces. */
65 #define TRACE(x)
66
67
68 /* General:
69
70        It's necessary to parse up the format string to recognise the GMP
71        extra types F, Q and Z.  Other types and conversions are passed
72        across to the standard sscanf or fscanf via funs->scan, for ease of
73        implementation.  This is essential in the case of something like glibc
74        %p where the pointer format isn't actually documented.
75
76        Because funs->scan doesn't get the whole input it can't put the right
77        values in for %n, so that's handled in __gmp_doscan.  Neither sscanf
78        nor fscanf directly indicate how many characters were read, so an
79        extra %n is appended to each run for that.  For fscanf this merely
80        supports our %n output, but for sscanf it lets funs->step move us
81        along the input string.
82
83        Whitespace and literal matches in the format string, including %%,
84        are handled directly within __gmp_doscan.  This is reasonably
85        efficient, and avoids some suspicious behaviour observed in various
86        system libc's.  GLIBC 2.2.4 for instance returns 0 on
87
88            sscanf(" ", " x")
89        or
90            sscanf(" ", " x%d",&n)
91
92        whereas we think they should return EOF, since end-of-string is
93        reached when a match of "x" is required.
94
95        For standard % conversions, funs->scan is called once for each
96        conversion.  If we had vfscanf and vsscanf and could rely on their
97        fixed text matching behaviour then we could call them with multiple
98        consecutive standard conversions.  But plain fscanf and sscanf work
99        fine, and parsing one field at a time shouldn't be too much of a
100        slowdown.
101
102    gmpscan:
103
104        gmpscan reads a gmp type.  It's only used from one place, but is a
105        separate subroutine to avoid a big chunk of complicated code in the
106        middle of __gmp_doscan.  Within gmpscan a couple of loopbacks make it
107        possible to share code for parsing integers, rationals and floats.
108
109        In gmpscan normally one char of lookahead is maintained, but when width
110        is reached that stops, on the principle that an fgetc/ungetc of a char
111        past where we're told to stop would be undesirable.  "chars" is how many
112        characters have been read so far, including the current c.  When
113        chars==width and another character is desired then a jump is done to the
114        "convert" stage.  c is invalid and mustn't be unget'ed in this case;
115        chars is set to width+1 to indicate that.
116
117        gmpscan normally returns the number of characters read.  -1 means an
118        invalid field, -2 means EOF reached before any matching characters
119        were read.
120
121        For hex floats, the mantissa part is passed to mpf_set_str, then the
122        exponent is applied with mpf_mul_exp or mpf_div_2exp.  This is easier
123        than teaching mpf_set_str about an exponent factor (ie. 2) differing
124        from the mantissa radix point factor (ie. 16).  mpf_mul_exp and
125        mpf_div_2exp will preserve the application requested precision, so
126        nothing in that respect is lost by making this a two-step process.
127
128    Matching and errors:
129
130        C99 7.19.6.2 paras 9 and 10 say an input item is read as the longest
131        string which is a match for the appropriate type, or a prefix of a
132        match.  With that done, if it's only a prefix then the result is a
133        matching failure, ie. invalid input.
134
135        This rule seems fairly clear, but doesn't seem to be universally
136        applied in system C libraries.  Even GLIBC doesn't seem to get it
137        right, insofar as it seems to accept some apparently invalid forms.
138        Eg. glibc 2.3.1 accepts "0x" for a "%i", where a reading of the
139        standard would suggest a non-empty sequence of digits should be
140        required after an "0x".
141
142        A footnote to 7.19.6.2 para 17 notes how this input item reading can
143        mean inputs acceptable to strtol are not acceptable to fscanf.  We
144        think this confirms our reading of "0x" as invalid.
145
146        Clearly gmp_sscanf could backtrack to a longest input which was a
147        valid match for a given item, but this is not done, since C99 says
148        sscanf is identical to fscanf, so we make gmp_sscanf identical to
149        gmp_fscanf.
150
151    Types:
152
153        C99 says "ll" is for long long, and "L" is for long double floats.
154        Unfortunately in GMP 4.1.1 we documented the two as equivalent.  This
155        doesn't affect us directly, since both are passed through to plain
156        scanf.  It seems wisest not to try to enforce the C99 rule.  This is
157        consistent with what we said before, though whether it actually
158        worked was always up to the C library.
159
160    Alternatives:
161
162        Consideration was given to using separate code for gmp_fscanf and
163        gmp_sscanf.  The sscanf case could zip across a string doing literal
164        matches or recognising digits in gmpscan, rather than making a
165        function call fun->get per character.  The fscanf could use getc
166        rather than fgetc too, which might help those systems where getc is a
167        macro or otherwise inlined.  But none of this scanning and converting
168        will be particularly fast, so the two are done together to keep it a
169        little simpler for now.
170
171        Various multibyte string issues are not addressed, for a start C99
172        scanf says the format string is multibyte.  Since we pass %c, %s and
173        %[ to the system scanf, they might do multibyte reads already, but
174        it's another matter whether or not that can be used, since our digit
175        and whitespace parsing is only unibyte.  The plan is to quietly
176        ignore multibyte locales for now.  This is not as bad as it sounds,
177        since GMP is presumably used mostly on numbers, which can be
178        perfectly adequately treated in plain ASCII.
179
180 */
181
182
183 struct gmp_doscan_params_t {
184   int   base;
185   int   ignore;
186   char  type;
187   int   width;
188 };
189
190
191 #define GET(c)                  \
192   do {                          \
193     ASSERT (chars <= width);    \
194     chars++;                    \
195     if (chars > width)          \
196       goto convert;             \
197     (c) = (*funs->get) (data);  \
198   } while (0)
199
200 /* store into "s", extending if necessary */
201 #define STORE(c)                                                        \
202   do {                                                                  \
203     ASSERT (s_upto <= s_alloc);                                         \
204     if (s_upto >= s_alloc)                                              \
205       {                                                                 \
206         size_t  s_alloc_new = s_alloc + S_ALLOC_STEP;                   \
207         s = __GMP_REALLOCATE_FUNC_TYPE (s, s_alloc, s_alloc_new, char); \
208         s_alloc = s_alloc_new;                                          \
209       }                                                                 \
210     s[s_upto++] = c;                                                    \
211   } while (0)
212
213 #define S_ALLOC_STEP  512
214
215 static int
216 gmpscan (const struct gmp_doscan_funs_t *funs, void *data,
217          const struct gmp_doscan_params_t *p, void *dst)
218 {
219   int     chars, c, base, first, width, seen_point, seen_digit, hexfloat;
220   size_t  s_upto, s_alloc, hexexp;
221   char    *s;
222   int     invalid = 0;
223
224   TRACE (printf ("gmpscan\n"));
225
226   ASSERT (p->type == 'F' || p->type == 'Q' || p->type == 'Z');
227
228   c = (*funs->get) (data);
229   if (c == EOF)
230     return -2;
231
232   chars = 1;
233   first = 1;
234   seen_point = 0;
235   width = (p->width == 0 ? INT_MAX-1 : p->width);
236   base = p->base;
237   s_alloc = S_ALLOC_STEP;
238   s = __GMP_ALLOCATE_FUNC_TYPE (s_alloc, char);
239   s_upto = 0;
240   hexfloat = 0;
241   hexexp = 0;
242
243  another:
244   seen_digit = 0;
245   if (c == '-')
246     {
247       STORE (c);
248       goto get_for_sign;
249     }
250   else if (c == '+')
251     {
252       /* don't store '+', it's not accepted by mpz_set_str etc */
253     get_for_sign:
254       GET (c);
255     }
256
257   if (base == 0)
258     {
259       base = 10;                  /* decimal if no base indicator */
260       if (c == '0')
261         {
262           seen_digit = 1;         /* 0 alone is a valid number */
263           if (p->type != 'F')
264             base = 8;             /* leading 0 is octal, for non-floats */
265           STORE (c);
266           GET (c);
267           if (c == 'x' || c == 'X')
268             {
269               base = 16;
270               seen_digit = 0;     /* must have digits after an 0x */
271               if (p->type == 'F') /* don't pass 'x' to mpf_set_str_point */
272                 hexfloat = 1;
273               else
274                 STORE (c);
275               GET (c);
276             }
277         }
278     }
279
280  digits:
281   for (;;)
282     {
283       if (base == 16)
284         {
285           if (! isxdigit (c))
286             break;
287         }
288       else
289         {
290           if (! isdigit (c))
291             break;
292           if (base == 8 && (c == '8' || c == '9'))
293             break;
294         }
295
296       seen_digit = 1;
297       STORE (c);
298       GET (c);
299     }
300
301   if (first)
302     {
303       /* decimal point */
304       if (p->type == 'F' && ! seen_point)
305         {
306           /* For a multi-character decimal point, if the first character is
307              present then all of it must be, otherwise the input is
308              considered invalid.  */
309           const char  *point = GMP_DECIMAL_POINT;
310           int         pc = (unsigned char) *point++;
311           if (c == pc)
312             {
313               for (;;)
314                 {
315                   STORE (c);
316                   GET (c);
317                   pc = (unsigned char) *point++;
318                   if (pc == '\0')
319                     break;
320                   if (c != pc)
321                     goto set_invalid;
322                 }
323               seen_point = 1;
324               goto digits;
325             }
326         }
327
328       /* exponent */
329       if (p->type == 'F')
330         {
331           if (hexfloat && (c == 'p' || c == 'P'))
332             {
333               hexexp = s_upto; /* exponent location */
334               base = 10;       /* exponent in decimal */
335               goto exponent;
336             }
337           else if (! hexfloat && (c == 'e' || c == 'E'))
338             {
339             exponent:
340               /* must have at least one digit in the mantissa, just an exponent
341                  is not good enough */
342               if (! seen_digit)
343                 goto set_invalid;
344
345             do_second:
346               first = 0;
347               STORE (c);
348               GET (c);
349               goto another;
350             }
351         }
352
353       /* denominator */
354       if (p->type == 'Q' && c == '/')
355         {
356           /* must have at least one digit in the numerator */
357           if (! seen_digit)
358             goto set_invalid;
359
360           /* now look for at least one digit in the denominator */
361           seen_digit = 0;
362
363           /* allow the base to be redetermined for "%i" */
364           base = p->base;
365           goto do_second;
366         }
367     }
368
369  convert:
370   if (! seen_digit)
371     {
372     set_invalid:
373       invalid = 1;
374       goto done;
375     }
376
377   if (! p->ignore)
378     {
379       STORE ('\0');
380       TRACE (printf ("  convert \"%s\"\n", s));
381
382       /* We ought to have parsed out a valid string above, so just test
383          mpz_set_str etc with an ASSERT.  */
384       switch (p->type) {
385       case 'F':
386         {
387           mpf_ptr  f = (mpf_ptr) dst;
388           if (hexexp != 0)
389             s[hexexp] = '\0';
390           ASSERT_NOCARRY (mpf_set_str (f, s, hexfloat ? 16 : 10));
391           if (hexexp != 0)
392             {
393               char *dummy;
394               long  exp;
395               exp = strtol (s + hexexp + 1, &dummy, 10);
396               if (exp >= 0)
397                 mpf_mul_2exp (f, f, (unsigned long) exp);
398               else
399                 mpf_div_2exp (f, f, - (unsigned long) exp);
400             }
401         }
402         break;
403       case 'Q':
404         ASSERT_NOCARRY (mpq_set_str ((mpq_ptr) dst, s, p->base));
405         break;
406       case 'Z':
407         ASSERT_NOCARRY (mpz_set_str ((mpz_ptr) dst, s, p->base));
408         break;
409       default:
410         ASSERT (0);
411         /*FALLTHRU*/
412         break;
413       }
414     }
415
416  done:
417   ASSERT (chars <= width+1);
418   if (chars != width+1)
419     {
420       (*funs->unget) (c, data);
421       TRACE (printf ("  ungetc %d, to give %d chars\n", c, chars-1));
422     }
423   chars--;
424
425   (*__gmp_free_func) (s, s_alloc);
426
427   if (invalid)
428     {
429       TRACE (printf ("  invalid\n"));
430       return -1;
431     }
432
433   TRACE (printf ("  return %d chars (cf width %d)\n", chars, width));
434   return chars;
435 }
436
437
438 /* Read and discard whitespace, if any.  Return number of chars skipped.
439    Whitespace skipping never provokes the EOF return from __gmp_doscan, so
440    it's not necessary to watch for EOF from funs->get, */
441 static int
442 skip_white (const struct gmp_doscan_funs_t *funs, void *data)
443 {
444   int  c;
445   int  ret = 0;
446
447   do
448     {
449       c = (funs->get) (data);
450       ret++;
451     }
452   while (isspace (c));
453
454   (funs->unget) (c, data);
455   ret--;
456
457   TRACE (printf ("  skip white %d\n", ret));
458   return ret;
459 }
460
461
462 int
463 __gmp_doscan (const struct gmp_doscan_funs_t *funs, void *data,
464               const char *orig_fmt, va_list orig_ap)
465 {
466   struct gmp_doscan_params_t  param;
467   va_list     ap;
468   char        *alloc_fmt;
469   const char  *fmt, *this_fmt, *end_fmt;
470   size_t      orig_fmt_len, alloc_fmt_size, len;
471   int         new_fields, new_chars;
472   char        fchar;
473   int         fields = 0;
474   int         chars = 0;
475
476   TRACE (printf ("__gmp_doscan \"%s\"\n", orig_fmt);
477          if (funs->scan == (gmp_doscan_scan_t) sscanf)
478            printf ("  s=\"%s\"\n", * (const char **) data));
479
480   /* Don't modify orig_ap, if va_list is actually an array and hence call by
481      reference.  It could be argued that it'd be more efficient to leave
482      callers to make a copy if they care, but doing so here is going to be a
483      very small part of the total work, and we may as well keep applications
484      out of trouble.  */
485   va_copy (ap, orig_ap);
486
487   /* Parts of the format string are going to be copied so that a " %n" can
488      be appended.  alloc_fmt is some space for that.  orig_fmt_len+4 will be
489      needed if fmt consists of a single "%" specifier, but otherwise is an
490      overestimate.  We're not going to be very fast here, so use
491      __gmp_allocate_func rather than TMP_ALLOC.  */
492   orig_fmt_len = strlen (orig_fmt);
493   alloc_fmt_size = orig_fmt_len + 4;
494   alloc_fmt = __GMP_ALLOCATE_FUNC_TYPE (alloc_fmt_size, char);
495
496   fmt = orig_fmt;
497   end_fmt = orig_fmt + orig_fmt_len;
498
499   for (;;)
500     {
501     next:
502       fchar = *fmt++;
503
504       if (fchar == '\0')
505         break;
506
507       if (isspace (fchar))
508         {
509           chars += skip_white (funs, data);
510           continue;
511         }
512
513       if (fchar != '%')
514         {
515           int  c;
516         literal:
517           c = (funs->get) (data);
518           if (c != fchar)
519             {
520               (funs->unget) (c, data);
521               if (c == EOF)
522                 {
523                 eof_no_match:
524                   if (fields == 0)
525                     fields = EOF;
526                 }
527               goto done;
528             }
529           chars++;
530           continue;
531         }
532
533       param.type = '\0';
534       param.base = 0;    /* for e,f,g,i */
535       param.ignore = 0;
536       param.width = 0;
537
538       this_fmt = fmt-1;
539       TRACE (printf ("  this_fmt \"%s\"\n", this_fmt));
540
541       for (;;)
542         {
543           ASSERT (fmt <= end_fmt);
544
545           fchar = *fmt++;
546           switch (fchar) {
547
548           case '\0':  /* unterminated % sequence */
549             ASSERT (0);
550             goto done;
551
552           case '%':   /* literal % */
553             goto literal;
554
555           case '[':   /* character range */
556             fchar = *fmt++;
557             if (fchar == '^')
558               fchar = *fmt++;
559             /* ']' allowed as the first char (possibly after '^') */
560             if (fchar == ']')
561               fchar = *fmt++;
562             for (;;)
563               {
564                 ASSERT (fmt <= end_fmt);
565                 if (fchar == '\0')
566                   {
567                     /* unterminated % sequence */
568                     ASSERT (0);
569                     goto done;
570                   }
571                 if (fchar == ']')
572                   break;
573                 fchar = *fmt++;
574               }
575             /*FALLTHRU*/
576           case 'c':   /* characters */
577           case 's':   /* string of non-whitespace */
578           case 'p':   /* pointer */
579           libc_type:
580             len = fmt - this_fmt;
581             memcpy (alloc_fmt, this_fmt, len);
582             alloc_fmt[len++] = '%';
583             alloc_fmt[len++] = 'n';
584             alloc_fmt[len] = '\0';
585
586             TRACE (printf ("  scan \"%s\"\n", alloc_fmt);
587                    if (funs->scan == (gmp_doscan_scan_t) sscanf)
588                      printf ("  s=\"%s\"\n", * (const char **) data));
589
590             new_chars = -1;
591             if (param.ignore)
592               {
593                 new_fields = (*funs->scan) (data, alloc_fmt, &new_chars, NULL);
594                 ASSERT (new_fields == 0 || new_fields == EOF);
595               }
596             else
597               {
598                 void *arg = va_arg (ap, void *);
599                 new_fields = (*funs->scan) (data, alloc_fmt, arg, &new_chars);
600                 ASSERT (new_fields==0 || new_fields==1 || new_fields==EOF);
601
602                 if (new_fields == 0)
603                   goto done;  /* invalid input */
604
605                 if (new_fields == 1)
606                   ASSERT (new_chars != -1);
607               }
608             TRACE (printf ("  new_fields %d   new_chars %d\n",
609                            new_fields, new_chars));
610
611             if (new_fields == -1)
612               goto eof_no_match;  /* EOF before anything matched */
613
614             /* Under param.ignore, when new_fields==0 we don't know if
615                it's a successful match or an invalid field.  new_chars
616                won't have been assigned if it was an invalid field.  */
617             if (new_chars == -1)
618               goto done;  /* invalid input */
619
620             chars += new_chars;
621             (*funs->step) (data, new_chars);
622
623           increment_fields:
624             if (! param.ignore)
625               fields++;
626             goto next;
627
628           case 'd':   /* decimal */
629           case 'u':   /* decimal */
630             param.base = 10;
631             goto numeric;
632
633           case 'e':   /* float */
634           case 'E':   /* float */
635           case 'f':   /* float */
636           case 'g':   /* float */
637           case 'G':   /* float */
638           case 'i':   /* integer with base marker */
639           numeric:
640             if (param.type != 'F' && param.type != 'Q' && param.type != 'Z')
641               goto libc_type;
642
643             chars += skip_white (funs, data);
644
645             new_chars = gmpscan (funs, data, &param,
646                                  param.ignore ? NULL : va_arg (ap, void*));
647             if (new_chars == -2)
648               goto eof_no_match;
649             if (new_chars == -1)
650               goto done;
651
652             ASSERT (new_chars >= 0);
653             chars += new_chars;
654             goto increment_fields;
655
656           case 'a':   /* glibc allocate string */
657           case '\'':  /* glibc digit groupings */
658             break;
659
660           case 'F':   /* mpf_t */
661           case 'j':   /* intmax_t */
662           case 'L':   /* long long */
663           case 'q':   /* quad_t */
664           case 'Q':   /* mpq_t */
665           case 't':   /* ptrdiff_t */
666           case 'z':   /* size_t */
667           case 'Z':   /* mpz_t */
668           set_type:
669             param.type = fchar;
670             break;
671
672           case 'h':   /* short or char */
673             if (param.type != 'h')
674               goto set_type;
675             param.type = 'H';   /* internal code for "hh" */
676             break;
677
678             goto numeric;
679
680           case 'l':   /* long, long long, double or long double */
681             if (param.type != 'l')
682               goto set_type;
683             param.type = 'L';   /* "ll" means "L" */
684             break;
685
686           case 'n':
687             if (! param.ignore)
688               {
689                 void  *p;
690                 p = va_arg (ap, void *);
691                 TRACE (printf ("  store %%n to %p\n", p));
692                 switch (param.type) {
693                 case '\0': * (int       *) p = chars; break;
694                 case 'F':  mpf_set_si ((mpf_ptr) p, (long) chars); break;
695                 case 'H':  * (char      *) p = chars; break;
696                 case 'h':  * (short     *) p = chars; break;
697 #if HAVE_INTMAX_T
698                 case 'j':  * (intmax_t  *) p = chars; break;
699 #else
700                 case 'j':  ASSERT_FAIL (intmax_t not available); break;
701 #endif
702                 case 'l':  * (long      *) p = chars; break;
703 #if HAVE_QUAD_T && HAVE_LONG_LONG
704                 case 'q':
705                   ASSERT_ALWAYS (sizeof (quad_t) == sizeof (long long));
706                   /*FALLTHRU*/
707 #else
708                 case 'q':  ASSERT_FAIL (quad_t not available); break;
709 #endif
710 #if HAVE_LONG_LONG
711                 case 'L':  * (long long *) p = chars; break;
712 #else
713                 case 'L':  ASSERT_FAIL (long long not available); break;
714 #endif
715                 case 'Q':  mpq_set_si ((mpq_ptr) p, (long) chars, 1L); break;
716 #if HAVE_PTRDIFF_T
717                 case 't':  * (ptrdiff_t *) p = chars; break;
718 #else
719                 case 't':  ASSERT_FAIL (ptrdiff_t not available); break;
720 #endif
721                 case 'z':  * (size_t    *) p = chars; break;
722                 case 'Z':  mpz_set_si ((mpz_ptr) p, (long) chars); break;
723                 default: ASSERT (0); break;
724                 }
725               }
726             goto next;
727
728           case 'o':
729             param.base = 8;
730             goto numeric;
731
732           case 'x':
733           case 'X':
734             param.base = 16;
735             goto numeric;
736
737           case '0': case '1': case '2': case '3': case '4':
738           case '5': case '6': case '7': case '8': case '9':
739             param.width = 0;
740             do {
741               param.width = param.width * 10 + (fchar-'0');
742               fchar = *fmt++;
743             } while (isdigit (fchar));
744             fmt--; /* unget the non-digit */
745             break;
746
747           case '*':
748             param.ignore = 1;
749             break;
750
751           default:
752             /* something invalid in a % sequence */
753             ASSERT (0);
754             goto next;
755           }
756         }
757     }
758
759  done:
760   (*__gmp_free_func) (alloc_fmt, alloc_fmt_size);
761   return fields;
762 }