source: trunk/libs/newlib/src/newlib/libc/machine/powerpc/vfscanf.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 26.5 KB
Line 
1/*
2FUNCTION
3<<vscanf>>, <<vfscanf>>, <<vsscanf>>---format argument list
4
5INDEX
6        vscanf
7INDEX
8        vfscanf
9INDEX
10        vsscanf
11
12SYNOPSIS
13        #include <stdio.h>
14        #include <stdarg.h>
15        int vscanf(const char *restrict <[fmt]>, va_list <[list]>);
16        int vfscanf(FILE *restrict <[fp]>, const char *restrict <[fmt]>, va_list <[list]>);
17        int vsscanf(const char *restrict <[str]>, const char *restrict <[fmt]>, va_list <[list]>);
18
19        int _vscanf_r(void *<[reent]>, const char *restrict <[fmt]>,
20                       va_list <[list]>);
21        int _vfscanf_r(void *<[reent]>, FILE *restrict <[fp]>, const char *restrict <[fmt]>,
22                       va_list <[list]>);
23        int _vsscanf_r(void *<[reent]>, const char *restrict <[str]>, const char *restrict <[fmt]>,
24                       va_list <[list]>);
25
26DESCRIPTION
27<<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants
28of <<scanf>>, <<fscanf>>, and <<sscanf>>.  They differ only in
29allowing their caller to pass the variable argument list as a
30<<va_list>> object (initialized by <<va_start>>) rather than
31directly accepting a variable number of arguments.
32
33RETURNS
34The return values are consistent with the corresponding functions:
35<<vscanf>> returns the number of input fields successfully scanned,
36converted, and stored; the return value does not include scanned
37fields which were not stored. 
38
39If <<vscanf>> attempts to read at end-of-file, the return value
40is <<EOF>>.
41
42If no fields were stored, the return value is <<0>>.
43
44The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
45reentrant versions which take an additional first parameter which points to the
46reentrancy structure.
47
48PORTABILITY
49These are GNU extensions.
50
51Supporting OS subroutines required:
52*/
53
54/*-
55 * Copyright (c) 1990 The Regents of the University of California.
56 * All rights reserved.
57 *
58 * Redistribution and use in source and binary forms are permitted
59 * provided that the above copyright notice and this paragraph are
60 * duplicated in all such forms and that any documentation,
61 * advertising materials, and other materials related to such
62 * distribution and use acknowledge that the software was developed
63 * by the University of California, Berkeley.  The name of the
64 * University may not be used to endorse or promote products derived
65 * from this software without specific prior written permission.
66 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
67 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
68 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
69 */
70
71#include <_ansi.h>
72#include <reent.h>
73#include <newlib.h>
74#include <ctype.h>
75#include <stdio.h>
76#include <stdlib.h>
77#include <limits.h>
78#include <wchar.h>
79#include <string.h>
80#include <stdarg.h>
81#include "local.h"
82
83#ifndef NO_FLOATING_POINT
84#define FLOATING_POINT
85#endif
86
87#ifdef FLOATING_POINT
88#include <float.h>
89
90/* Currently a test is made to see if long double processing is warranted.
91   This could be changed in the future should the _ldtoa_r code be
92   preferred over _dtoa_r.  */
93#define _NO_LONGDBL
94#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
95#undef _NO_LONGDBL
96#endif
97
98#define _NO_LONGLONG
99#if defined _WANT_IO_LONG_LONG && defined __GNUC__
100# undef _NO_LONGLONG
101#endif
102
103#include "floatio.h"
104#define BUF     (MAXEXP+MAXFRACT+3)     /* 3 = sign + decimal point + NUL */
105/* An upper bound for how long a long prints in decimal.  4 / 13 approximates
106   log (2).  Add one char for roundoff compensation and one for the sign.  */
107#define MAX_LONG_LEN ((CHAR_BIT * sizeof (long)  - 1) * 4 / 13 + 2)
108#else
109#define BUF     40
110#endif
111
112/*
113 * Flags used during conversion.
114 */
115
116#define LONG            0x01    /* l: long or double */
117#define LONGDBL         0x02    /* L: long double or long long */
118#define SHORT           0x04    /* h: short */
119#define SUPPRESS        0x10    /* suppress assignment */
120#define POINTER         0x20    /* weird %p pointer (`fake hex') */
121#define NOSKIP          0x40    /* do not skip blanks */
122
123/*
124 * The following are used in numeric conversions only:
125 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
126 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
127 */
128
129#define SIGNOK          0x80    /* +/- is (still) legal */
130#define NDIGITS         0x100   /* no digits detected */
131
132#define DPTOK           0x200   /* (float) decimal point is still legal */
133#define EXPOK           0x400   /* (float) exponent (e+3, etc) still legal */
134
135#define PFXOK           0x200   /* 0x prefix is (still) legal */
136#define NZDIGITS        0x400   /* no zero digits detected */
137#define NNZDIGITS       0x800   /* no non-zero digits detected */
138
139#define VECTOR          0x2000  /* v: vector */
140#define FIXEDPOINT      0x4000  /* r/R: fixed-point */
141#define SIGNED          0x8000  /* r: signed fixed-point */
142
143/*
144 * Conversion types.
145 */
146
147#define CT_CHAR         0       /* %c conversion */
148#define CT_CCL          1       /* %[...] conversion */
149#define CT_STRING       2       /* %s conversion */
150#define CT_INT          3       /* integer, i.e., strtol or strtoul */
151#define CT_FLOAT        4       /* floating, i.e., strtod */
152
153#if 0
154#define u_char unsigned char
155#endif
156#define u_char char
157#define u_long unsigned long
158
159#ifndef _NO_LONGLONG
160typedef unsigned long long u_long_long;
161#endif
162
163typedef union
164{
165  char c[16] __attribute__ ((__aligned__ (16)));
166  short h[8];
167  long l[4];
168  int i[4];
169  float f[4];
170} vec_union;
171
172/*
173 * vfscanf
174 */
175
176#define BufferEmpty (fp->_r <= 0 && __srefill(fp))
177
178#ifndef _REENT_ONLY
179
180int
181vfscanf (register FILE *__restrict fp,
182    const char *__restrict fmt,
183    va_list ap)
184{
185  CHECK_INIT(_REENT, fp);
186  return __svfscanf_r (_REENT, fp, fmt, ap);
187}
188
189int
190__svfscanf (fp, fmt0, ap)
191     register FILE *fp;
192     char const *fmt0;
193     va_list ap;
194{
195  return __svfscanf_r (_REENT, fp, fmt0, ap);
196}
197
198#endif /* !_REENT_ONLY */
199
200int
201_vfscanf_r (struct _reent *data,
202    register FILE *__restrict fp,
203    const char *__restrict fmt,
204    va_list ap)
205{
206  return __svfscanf_r (data, fp, fmt, ap);
207}
208
209
210int
211__svfscanf_r (rptr, fp, fmt0, ap)
212     struct _reent *rptr;
213     register FILE *fp;
214     char const *fmt0;
215     va_list ap;
216{
217  register u_char *fmt = (u_char *) fmt0;
218  register int c;               /* character from format, or conversion */
219  register int type;            /* conversion type */
220  register size_t width;        /* field width, or 0 */
221  register char *p;             /* points into all kinds of strings */
222  register int n;               /* handy integer */
223  register int flags;           /* flags as defined above */
224  register char *p0;            /* saves original value of p when necessary */
225  int orig_flags;               /* saved flags used when processing vector */
226  int int_width;                /* tmp area to store width when processing int */
227  int nassigned;                /* number of fields assigned */
228  int nread;                    /* number of characters consumed from fp */
229  int base = 0;                 /* base argument to strtol/strtoul */
230  int nbytes = 1;               /* number of bytes read from fmt string */
231  wchar_t wc;                   /* wchar to use to read format string */
232  char vec_sep;                 /* vector separator char */
233  char last_space_char;         /* last white-space char eaten - needed for vec support */
234  int vec_read_count;           /* number of vector items to read separately */
235  int looped;                   /* has vector processing looped */
236  u_long (*ccfn) () = 0;        /* conversion function (strtol/strtoul) */
237  char ccltab[256];             /* character class table for %[...] */
238  char buf[BUF];                /* buffer for numeric conversions */
239  vec_union vec_buf;
240  char *lptr;                   /* literal pointer */
241#ifdef _MB_CAPABLE
242  mbstate_t state;                /* value to keep track of multibyte state */
243#endif
244
245  char *ch_dest;
246  short *sp;
247  int *ip;
248  float *flp;
249  _LONG_DOUBLE *ldp;
250  double *dp;
251  long *lp;
252#ifndef _NO_LONGLONG
253  long long *llp;
254#else
255        u_long _uquad;
256#endif
257
258  /* `basefix' is used to avoid `if' tests in the integer scanner */
259  static const short basefix[17] =
260    {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
261
262  nassigned = 0;
263  nread = 0;
264  for (;;)
265    {
266#ifndef _MB_CAPABLE
267      wc = *fmt;
268#else
269      memset (&state, '\0', sizeof (state));
270      nbytes = _mbtowc_r (rptr, &wc, fmt, MB_CUR_MAX, &state);
271#endif
272      fmt += nbytes;
273      if (wc == 0)
274        return nassigned;
275      if (nbytes == 1 && isspace (wc))
276        {
277          for (;;)
278            {
279              if (BufferEmpty)
280                return nassigned;
281              if (!isspace (*fp->_p))
282                break;
283              nread++, fp->_r--, fp->_p++;
284            }
285          continue;
286        }
287      if (wc != '%')
288        goto literal;
289      width = 0;
290      flags = 0;
291      vec_sep = ' ';
292      vec_read_count = 0;
293      looped = 0;
294
295      /*
296       * switch on the format.  continue if done; break once format
297       * type is derived.
298       */
299
300    again:
301      c = *fmt++;
302
303      switch (c)
304        {
305        case '%':
306        literal:
307          lptr = fmt - nbytes;
308          for (n = 0; n < nbytes; ++n)
309            {
310              if (BufferEmpty)
311                goto input_failure;
312              if (*fp->_p != *lptr)
313                goto match_failure;
314              fp->_r--, fp->_p++;
315              nread++;
316              ++lptr;
317            }
318          continue;
319
320        case '*':
321          flags |= SUPPRESS;
322          goto again;
323        case ',':
324        case ';':
325        case ':':
326        case '_':
327          if (flags == SUPPRESS || flags == 0)
328            vec_sep = c;
329          goto again;
330        case 'l':
331          if (flags & SHORT)
332            continue; /* invalid format, don't process any further */
333          if (flags & LONG)
334            {
335              flags &= ~LONG;
336              flags &= ~VECTOR;
337              flags |= LONGDBL;
338            }
339          else
340            {
341              flags |= LONG;
342              if (flags & VECTOR)
343                vec_read_count = 4;
344            }
345          goto again;
346        case 'L':
347          flags |= LONGDBL;
348          flags &= ~VECTOR;
349          goto again;
350        case 'h':
351          flags |= SHORT;
352          if (flags & LONG)
353            continue;  /* invalid format, don't process any further */
354          if (flags & VECTOR)
355            vec_read_count = 8;
356          goto again;
357#ifdef __ALTIVEC__
358        case 'v':
359          flags |= VECTOR;
360          vec_read_count = (flags & SHORT) ? 8 : ((flags & LONG) ? 4 : 16);
361          goto again;
362#endif
363        case '0':
364        case '1':
365        case '2':
366        case '3':
367        case '4':
368        case '5':
369        case '6':
370        case '7':
371        case '8':
372        case '9':
373          width = width * 10 + c - '0';
374          goto again;
375
376          /*
377           * Conversions. Those marked `compat' are for
378           * 4.[123]BSD compatibility.
379           *
380           * (According to ANSI, E and X formats are supposed to
381           * the same as e and x.  Sorry about that.)
382           */
383
384        case 'D':               /* compat */
385          flags |= LONG;
386          /* FALLTHROUGH */
387        case 'd':
388          type = CT_INT;
389          ccfn = (u_long (*)())_strtol_r;
390          base = 10;
391          break;
392
393        case 'i':
394          type = CT_INT;
395          ccfn = (u_long (*)())_strtol_r;
396          base = 0;
397          break;
398
399        case 'O':               /* compat */
400          flags |= LONG;
401          /* FALLTHROUGH */
402        case 'o':
403          type = CT_INT;
404          ccfn = _strtoul_r;
405          base = 8;
406          break;
407
408        case 'u':
409          type = CT_INT;
410          ccfn = _strtoul_r;
411          base = 10;
412          break;
413
414        case 'X':               /* compat   XXX */
415        case 'x':
416          flags |= PFXOK;       /* enable 0x prefixing */
417          type = CT_INT;
418          ccfn = _strtoul_r;
419          base = 16;
420          break;
421
422#ifdef FLOATING_POINT
423        case 'E':               /* compat   XXX */
424        case 'G':               /* compat   XXX */
425/* ANSI says that E,G and X behave the same way as e,g,x */
426          /* FALLTHROUGH */
427        case 'e':
428        case 'f':
429        case 'g':
430          type = CT_FLOAT;
431          if (flags & VECTOR)
432            vec_read_count = 4;
433          break;
434       
435# ifdef __SPE__
436          /* treat fixed-point like %f floating point */
437        case 'r':
438          flags |= SIGNED;
439          /* fallthrough */
440        case 'R':
441          flags |= FIXEDPOINT;
442          type = CT_FLOAT;
443          break;
444# endif
445#endif
446
447        case 's':
448          flags &= ~VECTOR;
449          type = CT_STRING;
450          break;
451
452        case '[':
453          fmt = __sccl (ccltab, fmt);
454          flags |= NOSKIP;
455          flags &= ~VECTOR;
456          type = CT_CCL;
457          break;
458
459        case 'c':
460          flags |= NOSKIP;
461          type = CT_CHAR;
462          if (flags & VECTOR)
463            {
464              /* not allowed to have h or l with c specifier */
465              if (flags & (LONG | SHORT))
466                continue;  /* invalid format don't process any further */
467              width = 0;
468              vec_read_count = 16;
469            }
470          break;
471
472        case 'p':               /* pointer format is like hex */
473          flags |= POINTER | PFXOK;
474          type = CT_INT;
475          ccfn = _strtoul_r;
476          base = 16;
477          break;
478
479        case 'n':
480          if (flags & SUPPRESS) /* ??? */
481            continue;
482          flags &= ~VECTOR;
483          if (flags & SHORT)
484            {
485              sp = va_arg (ap, short *);
486              *sp = nread;
487            }
488          else if (flags & LONG)
489            {
490              lp = va_arg (ap, long *);
491              *lp = nread;
492            }
493#ifndef _NO_LONGLONG
494          else if (flags & LONGDBL)
495            {
496              llp = va_arg (ap, long long*);
497              *llp = nread;
498            }
499#endif
500          else
501            {
502              ip = va_arg (ap, int *);
503              *ip = nread;
504            }
505          continue;
506
507          /*
508           * Disgusting backwards compatibility hacks.  XXX
509           */
510        case '\0':              /* compat */
511          return EOF;
512
513        default:                /* compat */
514          if (isupper (c))
515            flags |= LONG;
516          type = CT_INT;
517          ccfn = (u_long (*)())_strtol_r;
518          base = 10;
519          break;
520        }
521
522    process:
523      /*
524       * We have a conversion that requires input.
525       */
526      if (BufferEmpty)
527        goto input_failure;
528
529      /*
530       * Consume leading white space, except for formats that
531       * suppress this.
532       */
533      last_space_char = '\0';
534
535      if ((flags & NOSKIP) == 0)
536        {
537          while (isspace (*fp->_p))
538            {
539              last_space_char = *fp->_p;
540              nread++;
541              if (--fp->_r > 0)
542                fp->_p++;
543              else
544#ifndef CYGNUS_NEC
545              if (__srefill (fp))
546#endif
547                goto input_failure;
548            }
549          /*
550           * Note that there is at least one character in the
551           * buffer, so conversions that do not set NOSKIP ca
552           * no longer result in an input failure.
553           */
554        }
555
556      /* for vector formats process separator characters after first loop */
557      if (looped && (flags & VECTOR))
558        {
559          flags = orig_flags; 
560          /* all formats other than default char have a separator char */
561          if (vec_sep != ' ' || type != CT_CHAR)
562            {
563              if (vec_sep == ' ' && last_space_char != ' ' ||
564                  vec_sep != ' ' && *fp->_p != vec_sep)
565                goto match_failure;
566              if (vec_sep != ' ')
567                {
568                  nread++;
569                  if (--fp->_r > 0)
570                    fp->_p++;
571                  else
572#ifndef CYGNUS_NEC
573                    if (__srefill (fp))
574#endif
575                      goto input_failure;
576                }
577            }
578          /* after eating the separator char, we must eat any white-space
579             after the separator char that precedes the data to convert */
580          if ((flags & NOSKIP) == 0)
581            {
582              while (isspace (*fp->_p))
583                {
584                  last_space_char = *fp->_p;
585                  nread++;
586                  if (--fp->_r > 0)
587                    fp->_p++;
588                  else
589#ifndef CYGNUS_NEC
590                    if (__srefill (fp))
591#endif
592                      goto input_failure;
593                }
594            }
595
596        }
597      else /* save to counter-act changes made to flags when processing */
598        orig_flags = flags;
599
600      /*
601       * Do the conversion.
602       */
603      switch (type)
604        {
605
606        case CT_CHAR:
607          /* scan arbitrary characters (sets NOSKIP) */
608          if (width == 0)
609            width = 1;
610          if (flags & SUPPRESS)
611            {
612              size_t sum = 0;
613
614              for (;;)
615                {
616                  if ((n = fp->_r) < (int)width)
617                    {
618                      sum += n;
619                      width -= n;
620                      fp->_p += n;
621#ifndef CYGNUS_NEC
622                      if (__srefill (fp))
623                        {
624#endif
625                          if (sum == 0)
626                            goto input_failure;
627                          break;
628#ifndef CYGNUS_NEC
629                        }
630#endif
631                    }
632                  else
633                    {
634                      sum += width;
635                      fp->_r -= width;
636                      fp->_p += width;
637                      break;
638                    }
639                }
640              nread += sum;
641            }
642          else
643            {
644              int n = width;
645              if (!looped)
646                {
647                  if (flags & VECTOR)
648                    ch_dest = vec_buf.c;
649                  else
650                    ch_dest = va_arg (ap, char *);
651                }
652#ifdef CYGNUS_NEC
653              /* Kludge city for the moment */
654              if (fp->_r == 0)
655                goto input_failure;
656
657              while (n && fp->_r)
658                {
659                  *ch_dest++ = *(fp->_p++);
660                  n--;
661                  fp->_r--;
662                  nread++;
663                }
664#else
665              size_t r = fread (ch_dest, 1, width, fp);
666
667              if (r == 0)
668                goto input_failure;
669              nread += r;
670              ch_dest += r;
671#endif
672              if (!(flags & VECTOR))
673                nassigned++;
674            }
675          break;
676
677        case CT_CCL:
678          /* scan a (nonempty) character class (sets NOSKIP) */
679          if (width == 0)
680            width = ~0;         /* `infinity' */
681          /* take only those things in the class */
682          if (flags & SUPPRESS)
683            {
684              n = 0;
685              while (ccltab[*fp->_p])
686                {
687                  n++, fp->_r--, fp->_p++;
688                  if (--width == 0)
689                    break;
690                  if (BufferEmpty)
691                    {
692                      if (n == 0)
693                        goto input_failure;
694                      break;
695                    }
696                }
697              if (n == 0)
698                goto match_failure;
699            }
700          else
701            {
702              p0 = p = va_arg (ap, char *);
703              while (ccltab[*fp->_p])
704                {
705                  fp->_r--;
706                  *p++ = *fp->_p++;
707                  if (--width == 0)
708                    break;
709                  if (BufferEmpty)
710                    {
711                      if (p == p0)
712                        goto input_failure;
713                      break;
714                    }
715                }
716              n = p - p0;
717              if (n == 0)
718                goto match_failure;
719              *p = 0;
720              nassigned++;
721            }
722          nread += n;
723          break;
724
725        case CT_STRING:
726          /* like CCL, but zero-length string OK, & no NOSKIP */
727          if (width == 0)
728            width = ~0;
729          if (flags & SUPPRESS)
730            {
731              n = 0;
732              while (!isspace (*fp->_p))
733                {
734                  n++, fp->_r--, fp->_p++;
735                  if (--width == 0)
736                    break;
737                  if (BufferEmpty)
738                    break;
739                }
740              nread += n;
741            }
742          else
743            {
744              p0 = p = va_arg (ap, char *);
745              while (!isspace (*fp->_p))
746                {
747                  fp->_r--;
748                  *p++ = *fp->_p++;
749                  if (--width == 0)
750                    break;
751                  if (BufferEmpty)
752                    break;
753                }
754              *p = 0;
755              nread += p - p0;
756              nassigned++;
757            }
758          continue;
759
760        case CT_INT:
761          {
762          unsigned int_width_left = 0;
763          int skips = 0;
764          int_width = width;
765#ifdef hardway
766          if (int_width == 0 || int_width > sizeof (buf) - 1)
767#else
768          /* size_t is unsigned, hence this optimisation */
769          if (int_width - 1 > sizeof (buf) - 2)
770#endif
771            {
772              int_width_left = width - (sizeof (buf) - 1);
773              int_width = sizeof (buf) - 1;
774            }
775          flags |= SIGNOK | NDIGITS | NZDIGITS | NNZDIGITS;
776          for (p = buf; int_width; int_width--)
777            {
778              c = *fp->_p;
779              /*
780               * Switch on the character; `goto ok' if we
781               * accept it as a part of number.
782               */
783              switch (c)
784                {
785                  /*
786                   * The digit 0 is always legal, but is special.
787                   * For %i conversions, if no digits (zero or nonzero)
788                   * have been scanned (only signs), we will have base==0.
789                   * In that case, we should set it to 8 and enable 0x
790                   * prefixing. Also, if we have not scanned zero digits
791                   * before this, do not turn off prefixing (someone else
792                   * will turn it off if we have scanned any nonzero digits).
793                   */
794                case '0':
795                  if (! (flags & NNZDIGITS))
796                    goto ok;
797                  if (base == 0)
798                    {
799                      base = 8;
800                      flags |= PFXOK;
801                    }
802                  if (flags & NZDIGITS)
803                    {
804                      flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
805                      goto ok;
806                    }
807                  flags &= ~(SIGNOK | PFXOK | NDIGITS);
808                  if (int_width_left)
809                    {
810                      int_width_left--;
811                      int_width++;
812                    }
813                  ++skips;
814                  goto skip;
815
816                  /* 1 through 7 always legal */
817                case '1':
818                case '2':
819                case '3':
820                case '4':
821                case '5':
822                case '6':
823                case '7':
824                  base = basefix[base];
825                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
826                  goto ok;
827
828                  /* digits 8 and 9 ok iff decimal or hex */
829                case '8':
830                case '9':
831                  base = basefix[base];
832                  if (base <= 8)
833                    break;      /* not legal here */
834                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
835                  goto ok;
836
837                  /* letters ok iff hex */
838                case 'A':
839                case 'B':
840                case 'C':
841                case 'D':
842                case 'E':
843                case 'F':
844                case 'a':
845                case 'b':
846                case 'c':
847                case 'd':
848                case 'e':
849                case 'f':
850                  /* no need to fix base here */
851                  if (base <= 10)
852                    break;      /* not legal here */
853                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
854                  goto ok;
855
856                  /* sign ok only as first character */
857                case '+':
858                case '-':
859                  if (flags & SIGNOK)
860                    {
861                      flags &= ~SIGNOK;
862                      goto ok;
863                    }
864                  break;
865
866                  /* x ok iff flag still set & 2nd char */
867                case 'x':
868                case 'X':
869                  if (flags & PFXOK && p == buf + 1)
870                    {
871                      base = 16;/* if %i */
872                      flags &= ~PFXOK;
873                      /* We must reset the NZDIGITS and NDIGITS
874                         flags that would have been unset by seeing
875                         the zero that preceded the X or x.  */
876                      flags |= NZDIGITS | NDIGITS;
877                      goto ok;
878                    }
879                  break;
880                }
881
882              /*
883               * If we got here, c is not a legal character
884               * for a number.  Stop accumulating digits.
885               */
886              break;
887            ok:
888              /*
889               * c is legal: store it and look at the next.
890               */
891              *p++ = c;
892            skip:
893              if (--fp->_r > 0)
894                fp->_p++;
895              else
896#ifndef CYGNUS_NEC
897              if (__srefill (fp))
898#endif
899                break;          /* EOF */
900            }
901          /*
902           * If we had only a sign, it is no good; push back the sign.
903           * If the number ends in `x', it was [sign] '0' 'x', so push back
904           * the x and treat it as [sign] '0'.
905           */
906          if (flags & NDIGITS)
907            {
908              if (p > buf)
909                (void) ungetc (*(u_char *)-- p, fp);
910              goto match_failure;
911            }
912          c = ((u_char *) p)[-1];
913          if (c == 'x' || c == 'X')
914            {
915              --p;
916              /*(void)*/ ungetc (c, fp);
917            }
918          if ((flags & SUPPRESS) == 0)
919            {
920              u_long res;
921
922              *p = 0;
923              res = (*ccfn) (rptr, buf, (char **) NULL, base);
924              if ((flags & POINTER) && !(flags & VECTOR))
925                *(va_arg (ap, void **)) = (void *) (unsigned _POINTER_INT) res;
926              else if (flags & SHORT)
927                {
928                  if (!(flags & VECTOR))
929                    sp = va_arg (ap, short *);
930                  else if (!looped)
931                    sp = vec_buf.h;
932                  *sp++ = res;
933                }
934              else if (flags & LONG)
935                {
936                  if (!(flags & VECTOR))
937                    lp = va_arg (ap, long *);
938                  else if (!looped)
939                    lp = vec_buf.l;
940                  *lp++ = res;
941                }
942#ifndef _NO_LONGLONG
943              else if (flags & LONGDBL)
944                {
945                  u_long_long resll;
946                  if (ccfn == _strtoul_r)
947                    resll = _strtoull_r (rptr, buf, (char **) NULL, base);
948                  else
949                    resll = _strtoll_r (rptr, buf, (char **) NULL, base);
950                  llp = va_arg (ap, long long*);
951                  *llp = resll;
952                }
953#endif
954              else
955                {
956                  if (!(flags & VECTOR))
957                    {
958                      ip = va_arg (ap, int *);
959                      *ip++ = res;
960                    }
961                  else
962                    {
963                      if (!looped)
964                        ch_dest = vec_buf.c;
965                      *ch_dest++ = (char)res;
966                    }
967                }
968              if (!(flags & VECTOR))
969                nassigned++;
970            }
971          nread += p - buf + skips;
972          break;
973          }
974
975#ifdef FLOATING_POINT
976        case CT_FLOAT:
977        {
978          /* scan a floating point number as if by strtod */
979          /* This code used to assume that the number of digits is reasonable.
980             However, ANSI / ISO C makes no such stipulation; we have to get
981             exact results even when there is an unreasonable amount of
982             leading zeroes.  */
983          long leading_zeroes = 0;
984          long zeroes, exp_adjust;
985          char *exp_start = NULL;
986          unsigned fl_width = width;
987          unsigned width_left = 0;
988#ifdef hardway
989          if (fl_width == 0 || fl_width > sizeof (buf) - 1)
990#else
991          /* size_t is unsigned, hence this optimisation */
992          if (fl_width - 1 > sizeof (buf) - 2)
993#endif
994            {
995              width_left = fl_width - (sizeof (buf) - 1);
996              fl_width = sizeof (buf) - 1;
997            }
998          flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
999          zeroes = 0;
1000          exp_adjust = 0;
1001          for (p = buf; fl_width; )
1002            {
1003              c = *fp->_p;
1004              /*
1005               * This code mimicks the integer conversion
1006               * code, but is much simpler.
1007               */
1008              switch (c)
1009                {
1010
1011                case '0':
1012                  if (flags & NDIGITS)
1013                    {
1014                      flags &= ~SIGNOK;
1015                      zeroes++;
1016                      if (width_left)
1017                        {
1018                          width_left--;
1019                          fl_width++;
1020                        }
1021                      goto fskip;
1022                    }
1023                  /* Fall through.  */
1024                case '1':
1025                case '2':
1026                case '3':
1027                case '4':
1028                case '5':
1029                case '6':
1030                case '7':
1031                case '8':
1032                case '9':
1033                  flags &= ~(SIGNOK | NDIGITS);
1034                  goto fok;
1035
1036                case '+':
1037                case '-':
1038                  if (flags & SIGNOK)
1039                    {
1040                      flags &= ~SIGNOK;
1041                      goto fok;
1042                    }
1043                  break;
1044                case '.':
1045                  if (flags & DPTOK)
1046                    {
1047                      flags &= ~(SIGNOK | DPTOK);
1048                      leading_zeroes = zeroes;
1049                      goto fok;
1050                    }
1051                  break;
1052                case 'e':
1053                case 'E':
1054                  /* no exponent without some digits */
1055                  if ((flags & (NDIGITS | EXPOK)) == EXPOK
1056                      || ((flags & EXPOK) && zeroes))
1057                    {
1058                      if (! (flags & DPTOK))
1059                        {
1060                          exp_adjust = zeroes - leading_zeroes;
1061                          exp_start = p;
1062                        }
1063                      flags =
1064                        (flags & ~(EXPOK | DPTOK)) |
1065                        SIGNOK | NDIGITS;
1066                      zeroes = 0;
1067                      goto fok;
1068                    }
1069                  break;
1070                }
1071              break;
1072            fok:
1073              *p++ = c;
1074            fskip:
1075              fl_width--;
1076              ++nread;
1077              if (--fp->_r > 0)
1078                fp->_p++;
1079              else
1080#ifndef CYGNUS_NEC
1081              if (__srefill (fp))
1082#endif
1083                break;          /* EOF */
1084            }
1085          if (zeroes)
1086            flags &= ~NDIGITS;
1087          /*
1088           * If no digits, might be missing exponent digits
1089           * (just give back the exponent) or might be missing
1090           * regular digits, but had sign and/or decimal point.
1091           */
1092          if (flags & NDIGITS)
1093            {
1094              if (flags & EXPOK)
1095                {
1096                  /* no digits at all */
1097                  while (p > buf)
1098                    {
1099                      ungetc (*(u_char *)-- p, fp);
1100                      --nread;
1101                    }
1102                  goto match_failure;
1103                }
1104              /* just a bad exponent (e and maybe sign) */
1105              c = *(u_char *)-- p;
1106              --nread;
1107              if (c != 'e' && c != 'E')
1108                {
1109                  (void) ungetc (c, fp);        /* sign */
1110                  c = *(u_char *)-- p;
1111                  --nread;
1112                }
1113              (void) ungetc (c, fp);
1114            }
1115          if ((flags & SUPPRESS) == 0)
1116            {
1117#ifdef _NO_LONGDBL
1118              double res;
1119#else  /* !_NO_LONG_DBL */
1120              long double res;
1121#endif /* !_NO_LONG_DBL */
1122              long new_exp = 0;
1123
1124              *p = 0;
1125              if ((flags & (DPTOK | EXPOK)) == EXPOK)
1126                {
1127                  exp_adjust = zeroes - leading_zeroes;
1128                  new_exp = -exp_adjust;
1129                  exp_start = p;
1130                }
1131              else if (exp_adjust)
1132                new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust;
1133              if (exp_adjust)
1134                {
1135
1136                  /* If there might not be enough space for the new exponent,
1137                     truncate some trailing digits to make room.  */
1138                  if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)
1139                    exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
1140                 sprintf (exp_start, "e%ld", new_exp);
1141                }
1142#ifdef __SPE__
1143              if (flags & FIXEDPOINT)
1144                {
1145                  __uint64_t ufix64;
1146                  if (flags & SIGNED)
1147                    ufix64 = (__uint64_t)_strtosfix64_r (rptr, buf, NULL);
1148                  else
1149                    ufix64 = _strtoufix64_r (rptr, buf, NULL);
1150                  if (flags & SHORT)
1151                    {
1152                      __uint16_t *sp = va_arg (ap, __uint16_t *);
1153                      *sp = (__uint16_t)(ufix64 >> 48);
1154                    }
1155                  else if (flags & LONG)
1156                    {
1157                      __uint64_t *llp = va_arg (ap, __uint64_t *);
1158                      *llp = ufix64;
1159                    }
1160                  else
1161                    {
1162                      __uint32_t *lp = va_arg (ap, __uint32_t *);
1163                      *lp = (__uint32_t)(ufix64 >> 32);
1164                    }
1165                  nassigned++;
1166                  break;
1167                }
1168             
1169#endif /* __SPE__ */
1170#ifdef _NO_LONGDBL
1171              res = _strtod_r (rptr, buf, NULL);
1172#else  /* !_NO_LONGDBL */
1173              res = _strtold_r (rptr, buf, NULL);
1174#endif /* !_NO_LONGDBL */
1175              if (flags & LONG)
1176                {
1177                  dp = va_arg (ap, double *);
1178                  *dp = res;
1179                }
1180              else if (flags & LONGDBL)
1181                {
1182                  ldp = va_arg (ap, _LONG_DOUBLE *);
1183                  *ldp = res;
1184                }
1185              else
1186                {
1187                  if (!(flags & VECTOR))
1188                    flp = va_arg (ap, float *);
1189                  else if (!looped)
1190                    flp = vec_buf.f;
1191                  *flp++ = res;
1192                }
1193              if (!(flags & VECTOR))
1194                nassigned++;
1195            }
1196          break;
1197        }
1198#endif /* FLOATING_POINT */
1199        }
1200      if (vec_read_count-- > 1)
1201        {
1202          looped = 1;
1203          goto process;
1204        }
1205      if (flags & VECTOR)
1206        {
1207          int i;
1208          unsigned long *vp = va_arg (ap, unsigned long *);
1209          for (i = 0; i < 4; ++i)
1210            *vp++ = vec_buf.l[i];
1211          nassigned++;
1212        }
1213    }
1214input_failure:
1215  return nassigned ? nassigned : -1;
1216match_failure:
1217  return nassigned;
1218}
1219
Note: See TracBrowser for help on using the repository browser.