OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [machine/] [powerpc/] [vfscanf.c] - Blame information for rev 158

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.