OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc1/] [newlib/] [libc/] [machine/] [powerpc/] [vfscanf.c] - Blame information for rev 345

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 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
/*
212
 * vfscanf
213
 */
214
 
215
#define BufferEmpty (fp->_r <= 0 && __srefill(fp))
216
 
217
#ifndef _REENT_ONLY
218
 
219
int
220
_DEFUN (vfscanf, (fp, fmt, ap),
221
    register FILE *fp _AND
222
    _CONST char *fmt _AND
223
    va_list ap)
224
{
225
  CHECK_INIT(_REENT, fp);
226
  return __svfscanf_r (_REENT, fp, fmt, ap);
227
}
228
 
229
int
230
__svfscanf (fp, fmt0, ap)
231
     register FILE *fp;
232
     char _CONST *fmt0;
233
     va_list ap;
234
{
235
  return __svfscanf_r (_REENT, fp, fmt0, ap);
236
}
237
 
238
#endif /* !_REENT_ONLY */
239
 
240
int
241
_DEFUN (_vfscanf_r, (data, fp, fmt, ap),
242
    struct _reent *data _AND
243
    register FILE *fp _AND
244
    _CONST char *fmt _AND
245
    va_list ap)
246
{
247
  return __svfscanf_r (data, fp, fmt, ap);
248
}
249
 
250
 
251
int
252
__svfscanf_r (rptr, fp, fmt0, ap)
253
     struct _reent *rptr;
254
     register FILE *fp;
255
     char _CONST *fmt0;
256
     va_list ap;
257
{
258
  register u_char *fmt = (u_char *) fmt0;
259
  register int c;               /* character from format, or conversion */
260
  register int type;            /* conversion type */
261
  register size_t width;        /* field width, or 0 */
262
  register char *p;             /* points into all kinds of strings */
263
  register int n;               /* handy integer */
264
  register int flags;           /* flags as defined above */
265
  register char *p0;            /* saves original value of p when necessary */
266
  int orig_flags;               /* saved flags used when processing vector */
267
  int int_width;                /* tmp area to store width when processing int */
268
  int nassigned;                /* number of fields assigned */
269
  int nread;                    /* number of characters consumed from fp */
270
  int base = 0;                  /* base argument to strtol/strtoul */
271
  int nbytes = 1;               /* number of bytes read from fmt string */
272
  wchar_t wc;                   /* wchar to use to read format string */
273
  char vec_sep;                 /* vector separator char */
274
  char last_space_char;         /* last white-space char eaten - needed for vec support */
275
  int vec_read_count;           /* number of vector items to read separately */
276
  int looped;                   /* has vector processing looped */
277
  u_long (*ccfn) () = 0; /* conversion function (strtol/strtoul) */
278
  char ccltab[256];             /* character class table for %[...] */
279
  char buf[BUF];                /* buffer for numeric conversions */
280
  vec_union vec_buf;
281
  char *lptr;                   /* literal pointer */
282
#ifdef _MB_CAPABLE
283
  mbstate_t state;                /* value to keep track of multibyte state */
284
#endif
285
 
286
  char *ch_dest;
287
  short *sp;
288
  int *ip;
289
  float *flp;
290
  _LONG_DOUBLE *ldp;
291
  double *dp;
292
  long *lp;
293
#ifndef _NO_LONGLONG
294
  long long *llp;
295
#else
296
        u_long _uquad;
297
#endif
298
 
299
  /* `basefix' is used to avoid `if' tests in the integer scanner */
300
  static _CONST short basefix[17] =
301
    {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
302
 
303
  nassigned = 0;
304
  nread = 0;
305
  for (;;)
306
    {
307
#ifndef _MB_CAPABLE
308
      wc = *fmt;
309
#else
310
      memset (&state, '\0', sizeof (state));
311
      nbytes = _mbtowc_r (rptr, &wc, fmt, MB_CUR_MAX, &state);
312
#endif
313
      fmt += nbytes;
314
      if (wc == 0)
315
        return nassigned;
316
      if (nbytes == 1 && isspace (wc))
317
        {
318
          for (;;)
319
            {
320
              if (BufferEmpty)
321
                return nassigned;
322
              if (!isspace (*fp->_p))
323
                break;
324
              nread++, fp->_r--, fp->_p++;
325
            }
326
          continue;
327
        }
328
      if (wc != '%')
329
        goto literal;
330
      width = 0;
331
      flags = 0;
332
      vec_sep = ' ';
333
      vec_read_count = 0;
334
      looped = 0;
335
 
336
      /*
337
       * switch on the format.  continue if done; break once format
338
       * type is derived.
339
       */
340
 
341
    again:
342
      c = *fmt++;
343
 
344
      switch (c)
345
        {
346
        case '%':
347
        literal:
348
          lptr = fmt - nbytes;
349
          for (n = 0; n < nbytes; ++n)
350
            {
351
              if (BufferEmpty)
352
                goto input_failure;
353
              if (*fp->_p != *lptr)
354
                goto match_failure;
355
              fp->_r--, fp->_p++;
356
              nread++;
357
              ++lptr;
358
            }
359
          continue;
360
 
361
        case '*':
362
          flags |= SUPPRESS;
363
          goto again;
364
        case ',':
365
        case ';':
366
        case ':':
367
        case '_':
368
          if (flags == SUPPRESS || flags == 0)
369
            vec_sep = c;
370
          goto again;
371
        case 'l':
372
          if (flags & SHORT)
373
            continue; /* invalid format, don't process any further */
374
          if (flags & LONG)
375
            {
376
              flags &= ~LONG;
377
              flags &= ~VECTOR;
378
              flags |= LONGDBL;
379
            }
380
          else
381
            {
382
              flags |= LONG;
383
              if (flags & VECTOR)
384
                vec_read_count = 4;
385
            }
386
          goto again;
387
        case 'L':
388
          flags |= LONGDBL;
389
          flags &= ~VECTOR;
390
          goto again;
391
        case 'h':
392
          flags |= SHORT;
393
          if (flags & LONG)
394
            continue;  /* invalid format, don't process any further */
395
          if (flags & VECTOR)
396
            vec_read_count = 8;
397
          goto again;
398
#ifdef __ALTIVEC__
399
        case 'v':
400
          flags |= VECTOR;
401
          vec_read_count = (flags & SHORT) ? 8 : ((flags & LONG) ? 4 : 16);
402
          goto again;
403
#endif
404
        case '0':
405
        case '1':
406
        case '2':
407
        case '3':
408
        case '4':
409
        case '5':
410
        case '6':
411
        case '7':
412
        case '8':
413
        case '9':
414
          width = width * 10 + c - '0';
415
          goto again;
416
 
417
          /*
418
           * Conversions. Those marked `compat' are for
419
           * 4.[123]BSD compatibility.
420
           *
421
           * (According to ANSI, E and X formats are supposed to
422
           * the same as e and x.  Sorry about that.)
423
           */
424
 
425
        case 'D':               /* compat */
426
          flags |= LONG;
427
          /* FALLTHROUGH */
428
        case 'd':
429
          type = CT_INT;
430
          ccfn = (u_long (*)())_strtol_r;
431
          base = 10;
432
          break;
433
 
434
        case 'i':
435
          type = CT_INT;
436
          ccfn = (u_long (*)())_strtol_r;
437
          base = 0;
438
          break;
439
 
440
        case 'O':               /* compat */
441
          flags |= LONG;
442
          /* FALLTHROUGH */
443
        case 'o':
444
          type = CT_INT;
445
          ccfn = _strtoul_r;
446
          base = 8;
447
          break;
448
 
449
        case 'u':
450
          type = CT_INT;
451
          ccfn = _strtoul_r;
452
          base = 10;
453
          break;
454
 
455
        case 'X':               /* compat   XXX */
456
        case 'x':
457
          flags |= PFXOK;       /* enable 0x prefixing */
458
          type = CT_INT;
459
          ccfn = _strtoul_r;
460
          base = 16;
461
          break;
462
 
463
#ifdef FLOATING_POINT
464
        case 'E':               /* compat   XXX */
465
        case 'G':               /* compat   XXX */
466
/* ANSI says that E,G and X behave the same way as e,g,x */
467
          /* FALLTHROUGH */
468
        case 'e':
469
        case 'f':
470
        case 'g':
471
          type = CT_FLOAT;
472
          if (flags & VECTOR)
473
            vec_read_count = 4;
474
          break;
475
 
476
# ifdef __SPE__
477
          /* treat fixed-point like %f floating point */
478
        case 'r':
479
          flags |= SIGNED;
480
          /* fallthrough */
481
        case 'R':
482
          flags |= FIXEDPOINT;
483
          type = CT_FLOAT;
484
          break;
485
# endif
486
#endif
487
 
488
        case 's':
489
          flags &= ~VECTOR;
490
          type = CT_STRING;
491
          break;
492
 
493
        case '[':
494
          fmt = __sccl (ccltab, fmt);
495
          flags |= NOSKIP;
496
          flags &= ~VECTOR;
497
          type = CT_CCL;
498
          break;
499
 
500
        case 'c':
501
          flags |= NOSKIP;
502
          type = CT_CHAR;
503
          if (flags & VECTOR)
504
            {
505
              /* not allowed to have h or l with c specifier */
506
              if (flags & (LONG | SHORT))
507
                continue;  /* invalid format don't process any further */
508
              width = 0;
509
              vec_read_count = 16;
510
            }
511
          break;
512
 
513
        case 'p':               /* pointer format is like hex */
514
          flags |= POINTER | PFXOK;
515
          type = CT_INT;
516
          ccfn = _strtoul_r;
517
          base = 16;
518
          break;
519
 
520
        case 'n':
521
          if (flags & SUPPRESS) /* ??? */
522
            continue;
523
          flags &= ~VECTOR;
524
          if (flags & SHORT)
525
            {
526
              sp = va_arg (ap, short *);
527
              *sp = nread;
528
            }
529
          else if (flags & LONG)
530
            {
531
              lp = va_arg (ap, long *);
532
              *lp = nread;
533
            }
534
#ifndef _NO_LONGLONG
535
          else if (flags & LONGDBL)
536
            {
537
              llp = va_arg (ap, long long*);
538
              *llp = nread;
539
            }
540
#endif
541
          else
542
            {
543
              ip = va_arg (ap, int *);
544
              *ip = nread;
545
            }
546
          continue;
547
 
548
          /*
549
           * Disgusting backwards compatibility hacks.  XXX
550
           */
551
        case '\0':              /* compat */
552
          return EOF;
553
 
554
        default:                /* compat */
555
          if (isupper (c))
556
            flags |= LONG;
557
          type = CT_INT;
558
          ccfn = (u_long (*)())_strtol_r;
559
          base = 10;
560
          break;
561
        }
562
 
563
    process:
564
      /*
565
       * We have a conversion that requires input.
566
       */
567
      if (BufferEmpty)
568
        goto input_failure;
569
 
570
      /*
571
       * Consume leading white space, except for formats that
572
       * suppress this.
573
       */
574
      last_space_char = '\0';
575
 
576
      if ((flags & NOSKIP) == 0)
577
        {
578
          while (isspace (*fp->_p))
579
            {
580
              last_space_char = *fp->_p;
581
              nread++;
582
              if (--fp->_r > 0)
583
                fp->_p++;
584
              else
585
#ifndef CYGNUS_NEC
586
              if (__srefill (fp))
587
#endif
588
                goto input_failure;
589
            }
590
          /*
591
           * Note that there is at least one character in the
592
           * buffer, so conversions that do not set NOSKIP ca
593
           * no longer result in an input failure.
594
           */
595
        }
596
 
597
      /* for vector formats process separator characters after first loop */
598
      if (looped && (flags & VECTOR))
599
        {
600
          flags = orig_flags;
601
          /* all formats other than default char have a separator char */
602
          if (vec_sep != ' ' || type != CT_CHAR)
603
            {
604
              if (vec_sep == ' ' && last_space_char != ' ' ||
605
                  vec_sep != ' ' && *fp->_p != vec_sep)
606
                goto match_failure;
607
              if (vec_sep != ' ')
608
                {
609
                  nread++;
610
                  if (--fp->_r > 0)
611
                    fp->_p++;
612
                  else
613
#ifndef CYGNUS_NEC
614
                    if (__srefill (fp))
615
#endif
616
                      goto input_failure;
617
                }
618
            }
619
          /* after eating the separator char, we must eat any white-space
620
             after the separator char that precedes the data to convert */
621
          if ((flags & NOSKIP) == 0)
622
            {
623
              while (isspace (*fp->_p))
624
                {
625
                  last_space_char = *fp->_p;
626
                  nread++;
627
                  if (--fp->_r > 0)
628
                    fp->_p++;
629
                  else
630
#ifndef CYGNUS_NEC
631
                    if (__srefill (fp))
632
#endif
633
                      goto input_failure;
634
                }
635
            }
636
 
637
        }
638
      else /* save to counter-act changes made to flags when processing */
639
        orig_flags = flags;
640
 
641
      /*
642
       * Do the conversion.
643
       */
644
      switch (type)
645
        {
646
 
647
        case CT_CHAR:
648
          /* scan arbitrary characters (sets NOSKIP) */
649
          if (width == 0)
650
            width = 1;
651
          if (flags & SUPPRESS)
652
            {
653
              size_t sum = 0;
654
 
655
              for (;;)
656
                {
657
                  if ((n = fp->_r) < (int)width)
658
                    {
659
                      sum += n;
660
                      width -= n;
661
                      fp->_p += n;
662
#ifndef CYGNUS_NEC
663
                      if (__srefill (fp))
664
                        {
665
#endif
666
                          if (sum == 0)
667
                            goto input_failure;
668
                          break;
669
#ifndef CYGNUS_NEC
670
                        }
671
#endif
672
                    }
673
                  else
674
                    {
675
                      sum += width;
676
                      fp->_r -= width;
677
                      fp->_p += width;
678
                      break;
679
                    }
680
                }
681
              nread += sum;
682
            }
683
          else
684
            {
685
              int n = width;
686
              if (!looped)
687
                {
688
                  if (flags & VECTOR)
689
                    ch_dest = vec_buf.c;
690
                  else
691
                    ch_dest = va_arg (ap, char *);
692
                }
693
#ifdef CYGNUS_NEC
694
              /* Kludge city for the moment */
695
              if (fp->_r == 0)
696
                goto input_failure;
697
 
698
              while (n && fp->_r)
699
                {
700
                  *ch_dest++ = *(fp->_p++);
701
                  n--;
702
                  fp->_r--;
703
                  nread++;
704
                }
705
#else
706
              size_t r = fread (ch_dest, 1, width, fp);
707
 
708
              if (r == 0)
709
                goto input_failure;
710
              nread += r;
711
              ch_dest += r;
712
#endif
713
              if (!(flags & VECTOR))
714
                nassigned++;
715
            }
716
          break;
717
 
718
        case CT_CCL:
719
          /* scan a (nonempty) character class (sets NOSKIP) */
720
          if (width == 0)
721
            width = ~0;          /* `infinity' */
722
          /* take only those things in the class */
723
          if (flags & SUPPRESS)
724
            {
725
              n = 0;
726
              while (ccltab[*fp->_p])
727
                {
728
                  n++, fp->_r--, fp->_p++;
729
                  if (--width == 0)
730
                    break;
731
                  if (BufferEmpty)
732
                    {
733
                      if (n == 0)
734
                        goto input_failure;
735
                      break;
736
                    }
737
                }
738
              if (n == 0)
739
                goto match_failure;
740
            }
741
          else
742
            {
743
              p0 = p = va_arg (ap, char *);
744
              while (ccltab[*fp->_p])
745
                {
746
                  fp->_r--;
747
                  *p++ = *fp->_p++;
748
                  if (--width == 0)
749
                    break;
750
                  if (BufferEmpty)
751
                    {
752
                      if (p == p0)
753
                        goto input_failure;
754
                      break;
755
                    }
756
                }
757
              n = p - p0;
758
              if (n == 0)
759
                goto match_failure;
760
              *p = 0;
761
              nassigned++;
762
            }
763
          nread += n;
764
          break;
765
 
766
        case CT_STRING:
767
          /* like CCL, but zero-length string OK, & no NOSKIP */
768
          if (width == 0)
769
            width = ~0;
770
          if (flags & SUPPRESS)
771
            {
772
              n = 0;
773
              while (!isspace (*fp->_p))
774
                {
775
                  n++, fp->_r--, fp->_p++;
776
                  if (--width == 0)
777
                    break;
778
                  if (BufferEmpty)
779
                    break;
780
                }
781
              nread += n;
782
            }
783
          else
784
            {
785
              p0 = p = va_arg (ap, char *);
786
              while (!isspace (*fp->_p))
787
                {
788
                  fp->_r--;
789
                  *p++ = *fp->_p++;
790
                  if (--width == 0)
791
                    break;
792
                  if (BufferEmpty)
793
                    break;
794
                }
795
              *p = 0;
796
              nread += p - p0;
797
              nassigned++;
798
            }
799
          continue;
800
 
801
        case CT_INT:
802
          {
803
          unsigned int_width_left = 0;
804
          int skips = 0;
805
          int_width = width;
806
#ifdef hardway
807
          if (int_width == 0 || int_width > sizeof (buf) - 1)
808
#else
809
          /* size_t is unsigned, hence this optimisation */
810
          if (int_width - 1 > sizeof (buf) - 2)
811
#endif
812
            {
813
              int_width_left = width - (sizeof (buf) - 1);
814
              int_width = sizeof (buf) - 1;
815
            }
816
          flags |= SIGNOK | NDIGITS | NZDIGITS | NNZDIGITS;
817
          for (p = buf; int_width; int_width--)
818
            {
819
              c = *fp->_p;
820
              /*
821
               * Switch on the character; `goto ok' if we
822
               * accept it as a part of number.
823
               */
824
              switch (c)
825
                {
826
                  /*
827
                   * The digit 0 is always legal, but is special.
828
                   * For %i conversions, if no digits (zero or nonzero)
829
                   * have been scanned (only signs), we will have base==0.
830
                   * In that case, we should set it to 8 and enable 0x
831
                   * prefixing. Also, if we have not scanned zero digits
832
                   * before this, do not turn off prefixing (someone else
833
                   * will turn it off if we have scanned any nonzero digits).
834
                   */
835
                case '0':
836
                  if (! (flags & NNZDIGITS))
837
                    goto ok;
838
                  if (base == 0)
839
                    {
840
                      base = 8;
841
                      flags |= PFXOK;
842
                    }
843
                  if (flags & NZDIGITS)
844
                    {
845
                      flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
846
                      goto ok;
847
                    }
848
                  flags &= ~(SIGNOK | PFXOK | NDIGITS);
849
                  if (int_width_left)
850
                    {
851
                      int_width_left--;
852
                      int_width++;
853
                    }
854
                  ++skips;
855
                  goto skip;
856
 
857
                  /* 1 through 7 always legal */
858
                case '1':
859
                case '2':
860
                case '3':
861
                case '4':
862
                case '5':
863
                case '6':
864
                case '7':
865
                  base = basefix[base];
866
                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
867
                  goto ok;
868
 
869
                  /* digits 8 and 9 ok iff decimal or hex */
870
                case '8':
871
                case '9':
872
                  base = basefix[base];
873
                  if (base <= 8)
874
                    break;      /* not legal here */
875
                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
876
                  goto ok;
877
 
878
                  /* letters ok iff hex */
879
                case 'A':
880
                case 'B':
881
                case 'C':
882
                case 'D':
883
                case 'E':
884
                case 'F':
885
                case 'a':
886
                case 'b':
887
                case 'c':
888
                case 'd':
889
                case 'e':
890
                case 'f':
891
                  /* no need to fix base here */
892
                  if (base <= 10)
893
                    break;      /* not legal here */
894
                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
895
                  goto ok;
896
 
897
                  /* sign ok only as first character */
898
                case '+':
899
                case '-':
900
                  if (flags & SIGNOK)
901
                    {
902
                      flags &= ~SIGNOK;
903
                      goto ok;
904
                    }
905
                  break;
906
 
907
                  /* x ok iff flag still set & 2nd char */
908
                case 'x':
909
                case 'X':
910
                  if (flags & PFXOK && p == buf + 1)
911
                    {
912
                      base = 16;/* if %i */
913
                      flags &= ~PFXOK;
914
                      /* We must reset the NZDIGITS and NDIGITS
915
                         flags that would have been unset by seeing
916
                         the zero that preceded the X or x.  */
917
                      flags |= NZDIGITS | NDIGITS;
918
                      goto ok;
919
                    }
920
                  break;
921
                }
922
 
923
              /*
924
               * If we got here, c is not a legal character
925
               * for a number.  Stop accumulating digits.
926
               */
927
              break;
928
            ok:
929
              /*
930
               * c is legal: store it and look at the next.
931
               */
932
              *p++ = c;
933
            skip:
934
              if (--fp->_r > 0)
935
                fp->_p++;
936
              else
937
#ifndef CYGNUS_NEC
938
              if (__srefill (fp))
939
#endif
940
                break;          /* EOF */
941
            }
942
          /*
943
           * If we had only a sign, it is no good; push back the sign.
944
           * If the number ends in `x', it was [sign] '0' 'x', so push back
945
           * the x and treat it as [sign] '0'.
946
           */
947
          if (flags & NDIGITS)
948
            {
949
              if (p > buf)
950
                _CAST_VOID ungetc (*(u_char *)-- p, fp);
951
              goto match_failure;
952
            }
953
          c = ((u_char *) p)[-1];
954
          if (c == 'x' || c == 'X')
955
            {
956
              --p;
957
              /*(void)*/ ungetc (c, fp);
958
            }
959
          if ((flags & SUPPRESS) == 0)
960
            {
961
              u_long res;
962
 
963
              *p = 0;
964
              res = (*ccfn) (rptr, buf, (char **) NULL, base);
965
              if ((flags & POINTER) && !(flags & VECTOR))
966
                *(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res;
967
              else if (flags & SHORT)
968
                {
969
                  if (!(flags & VECTOR))
970
                    sp = va_arg (ap, short *);
971
                  else if (!looped)
972
                    sp = vec_buf.h;
973
                  *sp++ = res;
974
                }
975
              else if (flags & LONG)
976
                {
977
                  if (!(flags & VECTOR))
978
                    lp = va_arg (ap, long *);
979
                  else if (!looped)
980
                    lp = vec_buf.l;
981
                  *lp++ = res;
982
                }
983
#ifndef _NO_LONGLONG
984
              else if (flags & LONGDBL)
985
                {
986
                  u_long_long resll;
987
                  if (ccfn == _strtoul_r)
988
                    resll = _strtoull_r (rptr, buf, (char **) NULL, base);
989
                  else
990
                    resll = _strtoll_r (rptr, buf, (char **) NULL, base);
991
                  llp = va_arg (ap, long long*);
992
                  *llp = resll;
993
                }
994
#endif
995
              else
996
                {
997
                  if (!(flags & VECTOR))
998
                    {
999
                      ip = va_arg (ap, int *);
1000
                      *ip++ = res;
1001
                    }
1002
                  else
1003
                    {
1004
                      if (!looped)
1005
                        ch_dest = vec_buf.c;
1006
                      *ch_dest++ = (char)res;
1007
                    }
1008
                }
1009
              if (!(flags & VECTOR))
1010
                nassigned++;
1011
            }
1012
          nread += p - buf + skips;
1013
          break;
1014
          }
1015
 
1016
#ifdef FLOATING_POINT
1017
        case CT_FLOAT:
1018
        {
1019
          /* scan a floating point number as if by strtod */
1020
          /* This code used to assume that the number of digits is reasonable.
1021
             However, ANSI / ISO C makes no such stipulation; we have to get
1022
             exact results even when there is an unreasonable amount of
1023
             leading zeroes.  */
1024
          long leading_zeroes = 0;
1025
          long zeroes, exp_adjust;
1026
          char *exp_start = NULL;
1027
          unsigned fl_width = width;
1028
          unsigned width_left = 0;
1029
#ifdef hardway
1030
          if (fl_width == 0 || fl_width > sizeof (buf) - 1)
1031
#else
1032
          /* size_t is unsigned, hence this optimisation */
1033
          if (fl_width - 1 > sizeof (buf) - 2)
1034
#endif
1035
            {
1036
              width_left = fl_width - (sizeof (buf) - 1);
1037
              fl_width = sizeof (buf) - 1;
1038
            }
1039
          flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
1040
          zeroes = 0;
1041
          exp_adjust = 0;
1042
          for (p = buf; fl_width; )
1043
            {
1044
              c = *fp->_p;
1045
              /*
1046
               * This code mimicks the integer conversion
1047
               * code, but is much simpler.
1048
               */
1049
              switch (c)
1050
                {
1051
 
1052
                case '0':
1053
                  if (flags & NDIGITS)
1054
                    {
1055
                      flags &= ~SIGNOK;
1056
                      zeroes++;
1057
                      if (width_left)
1058
                        {
1059
                          width_left--;
1060
                          fl_width++;
1061
                        }
1062
                      goto fskip;
1063
                    }
1064
                  /* Fall through.  */
1065
                case '1':
1066
                case '2':
1067
                case '3':
1068
                case '4':
1069
                case '5':
1070
                case '6':
1071
                case '7':
1072
                case '8':
1073
                case '9':
1074
                  flags &= ~(SIGNOK | NDIGITS);
1075
                  goto fok;
1076
 
1077
                case '+':
1078
                case '-':
1079
                  if (flags & SIGNOK)
1080
                    {
1081
                      flags &= ~SIGNOK;
1082
                      goto fok;
1083
                    }
1084
                  break;
1085
                case '.':
1086
                  if (flags & DPTOK)
1087
                    {
1088
                      flags &= ~(SIGNOK | DPTOK);
1089
                      leading_zeroes = zeroes;
1090
                      goto fok;
1091
                    }
1092
                  break;
1093
                case 'e':
1094
                case 'E':
1095
                  /* no exponent without some digits */
1096
                  if ((flags & (NDIGITS | EXPOK)) == EXPOK
1097
                      || ((flags & EXPOK) && zeroes))
1098
                    {
1099
                      if (! (flags & DPTOK))
1100
                        {
1101
                          exp_adjust = zeroes - leading_zeroes;
1102
                          exp_start = p;
1103
                        }
1104
                      flags =
1105
                        (flags & ~(EXPOK | DPTOK)) |
1106
                        SIGNOK | NDIGITS;
1107
                      zeroes = 0;
1108
                      goto fok;
1109
                    }
1110
                  break;
1111
                }
1112
              break;
1113
            fok:
1114
              *p++ = c;
1115
            fskip:
1116
              fl_width--;
1117
              ++nread;
1118
              if (--fp->_r > 0)
1119
                fp->_p++;
1120
              else
1121
#ifndef CYGNUS_NEC
1122
              if (__srefill (fp))
1123
#endif
1124
                break;          /* EOF */
1125
            }
1126
          if (zeroes)
1127
            flags &= ~NDIGITS;
1128
          /*
1129
           * If no digits, might be missing exponent digits
1130
           * (just give back the exponent) or might be missing
1131
           * regular digits, but had sign and/or decimal point.
1132
           */
1133
          if (flags & NDIGITS)
1134
            {
1135
              if (flags & EXPOK)
1136
                {
1137
                  /* no digits at all */
1138
                  while (p > buf)
1139
                    {
1140
                      ungetc (*(u_char *)-- p, fp);
1141
                      --nread;
1142
                    }
1143
                  goto match_failure;
1144
                }
1145
              /* just a bad exponent (e and maybe sign) */
1146
              c = *(u_char *)-- p;
1147
              --nread;
1148
              if (c != 'e' && c != 'E')
1149
                {
1150
                  _CAST_VOID ungetc (c, fp);    /* sign */
1151
                  c = *(u_char *)-- p;
1152
                  --nread;
1153
                }
1154
              _CAST_VOID ungetc (c, fp);
1155
            }
1156
          if ((flags & SUPPRESS) == 0)
1157
            {
1158
#ifdef _NO_LONGDBL
1159
              double res;
1160
#else  /* !_NO_LONG_DBL */
1161
              long double res;
1162
#endif /* !_NO_LONG_DBL */
1163
              long new_exp = 0;
1164
 
1165
              *p = 0;
1166
              if ((flags & (DPTOK | EXPOK)) == EXPOK)
1167
                {
1168
                  exp_adjust = zeroes - leading_zeroes;
1169
                  new_exp = -exp_adjust;
1170
                  exp_start = p;
1171
                }
1172
              else if (exp_adjust)
1173
                new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust;
1174
              if (exp_adjust)
1175
                {
1176
 
1177
                  /* If there might not be enough space for the new exponent,
1178
                     truncate some trailing digits to make room.  */
1179
                  if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)
1180
                    exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
1181
                 sprintf (exp_start, "e%ld", new_exp);
1182
                }
1183
#ifdef __SPE__
1184
              if (flags & FIXEDPOINT)
1185
                {
1186
                  __uint64_t ufix64;
1187
                  if (flags & SIGNED)
1188
                    ufix64 = (__uint64_t)_strtosfix64_r (rptr, buf, NULL);
1189
                  else
1190
                    ufix64 = _strtoufix64_r (rptr, buf, NULL);
1191
                  if (flags & SHORT)
1192
                    {
1193
                      __uint16_t *sp = va_arg (ap, __uint16_t *);
1194
                      *sp = (__uint16_t)(ufix64 >> 48);
1195
                    }
1196
                  else if (flags & LONG)
1197
                    {
1198
                      __uint64_t *llp = va_arg (ap, __uint64_t *);
1199
                      *llp = ufix64;
1200
                    }
1201
                  else
1202
                    {
1203
                      __uint32_t *lp = va_arg (ap, __uint32_t *);
1204
                      *lp = (__uint32_t)(ufix64 >> 32);
1205
                    }
1206
                  nassigned++;
1207
                  break;
1208
                }
1209
 
1210
#endif /* __SPE__ */
1211
#ifdef _NO_LONGDBL
1212
              res = _strtod_r (rptr, buf, NULL);
1213
#else  /* !_NO_LONGDBL */
1214
              res = _strtold (buf, NULL);
1215
#endif /* !_NO_LONGDBL */
1216
              if (flags & LONG)
1217
                {
1218
                  dp = va_arg (ap, double *);
1219
                  *dp = res;
1220
                }
1221
              else if (flags & LONGDBL)
1222
                {
1223
                  ldp = va_arg (ap, _LONG_DOUBLE *);
1224
                  *ldp = res;
1225
                }
1226
              else
1227
                {
1228
                  if (!(flags & VECTOR))
1229
                    flp = va_arg (ap, float *);
1230
                  else if (!looped)
1231
                    flp = vec_buf.f;
1232
                  *flp++ = res;
1233
                }
1234
              if (!(flags & VECTOR))
1235
                nassigned++;
1236
            }
1237
          break;
1238
        }
1239
#endif /* FLOATING_POINT */
1240
        }
1241
      if (vec_read_count-- > 1)
1242
        {
1243
          looped = 1;
1244
          goto process;
1245
        }
1246
      if (flags & VECTOR)
1247
        {
1248
          int i;
1249
          unsigned long *vp = va_arg (ap, unsigned long *);
1250
          for (i = 0; i < 4; ++i)
1251
            *vp++ = vec_buf.l[i];
1252
          nassigned++;
1253
        }
1254
    }
1255
input_failure:
1256
  return nassigned ? nassigned : -1;
1257
match_failure:
1258
  return nassigned;
1259
}
1260
 

powered by: WebSVN 2.1.0

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