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/] [stdio/] [vfscanf.c] - Blame information for rev 179

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/*-
2
 * Copyright (c) 1990 The Regents of the University of California.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms are permitted
6
 * provided that the above copyright notice and this paragraph are
7
 * duplicated in all such forms and that any documentation,
8
 * advertising materials, and other materials related to such
9
 * distribution and use acknowledge that the software was developed
10
 * by the University of California, Berkeley.  The name of the
11
 * University may not be used to endorse or promote products derived
12
 * from this software without specific prior written permission.
13
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16
 */
17
 
18
/*
19
FUNCTION
20
<<vfscanf>>, <<vscanf>>, <<vsscanf>>---format argument list
21
 
22
INDEX
23
        vfscanf
24
INDEX
25
        _vfscanf_r
26
INDEX
27
        vscanf
28
INDEX
29
        _vscanf_r
30
INDEX
31
        vsscanf
32
INDEX
33
        _vsscanf_r
34
 
35
ANSI_SYNOPSIS
36
        #include <stdio.h>
37
        #include <stdarg.h>
38
        int vscanf(const char *<[fmt]>, va_list <[list]>);
39
        int vfscanf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
40
        int vsscanf(const char *<[str]>, const char *<[fmt]>, va_list <[list]>);
41
 
42
        int _vscanf_r(struct _reent *<[reent]>, const char *<[fmt]>,
43
                       va_list <[list]>);
44
        int _vfscanf_r(struct _reent *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
45
                       va_list <[list]>);
46
        int _vsscanf_r(struct _reent *<[reent]>, const char *<[str]>,
47
                       const char *<[fmt]>, va_list <[list]>);
48
 
49
TRAD_SYNOPSIS
50
        #include <stdio.h>
51
        #include <varargs.h>
52
        int vscanf( <[fmt]>, <[ist]>)
53
        char *<[fmt]>;
54
        va_list <[list]>;
55
 
56
        int vfscanf( <[fp]>, <[fmt]>, <[list]>)
57
        FILE *<[fp]>;
58
        char *<[fmt]>;
59
        va_list <[list]>;
60
 
61
        int vsscanf( <[str]>, <[fmt]>, <[list]>)
62
        char *<[str]>;
63
        char *<[fmt]>;
64
        va_list <[list]>;
65
 
66
        int _vscanf_r( <[reent]>, <[fmt]>, <[ist]>)
67
        struct _reent *<[reent]>;
68
        char *<[fmt]>;
69
        va_list <[list]>;
70
 
71
        int _vfscanf_r( <[reent]>, <[fp]>, <[fmt]>, <[list]>)
72
        struct _reent *<[reent]>;
73
        FILE *<[fp]>;
74
        char *<[fmt]>;
75
        va_list <[list]>;
76
 
77
        int _vsscanf_r( <[reent]>, <[str]>, <[fmt]>, <[list]>)
78
        struct _reent *<[reent]>;
79
        char *<[str]>;
80
        char *<[fmt]>;
81
        va_list <[list]>;
82
 
83
DESCRIPTION
84
<<vscanf>>, <<vfscanf>>, and <<vsscanf>> are (respectively) variants
85
of <<scanf>>, <<fscanf>>, and <<sscanf>>.  They differ only in
86
allowing their caller to pass the variable argument list as a
87
<<va_list>> object (initialized by <<va_start>>) rather than
88
directly accepting a variable number of arguments.
89
 
90
RETURNS
91
The return values are consistent with the corresponding functions:
92
<<vscanf>> returns the number of input fields successfully scanned,
93
converted, and stored; the return value does not include scanned
94
fields which were not stored.
95
 
96
If <<vscanf>> attempts to read at end-of-file, the return value
97
is <<EOF>>.
98
 
99
If no fields were stored, the return value is <<0>>.
100
 
101
The routines <<_vscanf_r>>, <<_vfscanf_f>>, and <<_vsscanf_r>> are
102
reentrant versions which take an additional first parameter which points to the
103
reentrancy structure.
104
 
105
PORTABILITY
106
These are GNU extensions.
107
 
108
Supporting OS subroutines required:
109
*/
110
 
111
#include <_ansi.h>
112
#include <reent.h>
113
#include <newlib.h>
114
#include <ctype.h>
115
#include <wctype.h>
116
#include <stdio.h>
117
#include <stdlib.h>
118
#include <stdint.h>
119
#include <limits.h>
120
#include <wchar.h>
121
#include <string.h>
122
#include <stdarg.h>
123
#include <errno.h>
124
#include "local.h"
125
 
126
#ifdef INTEGER_ONLY
127
#define VFSCANF vfiscanf
128
#define _VFSCANF_R _vfiscanf_r
129
#define __SVFSCANF __svfiscanf
130
#ifdef STRING_ONLY
131
#  define __SVFSCANF_R __ssvfiscanf_r
132
#else
133
#  define __SVFSCANF_R __svfiscanf_r
134
#endif
135
#else
136
#define VFSCANF vfscanf
137
#define _VFSCANF_R _vfscanf_r
138
#define __SVFSCANF __svfscanf
139
#ifdef STRING_ONLY
140
#  define __SVFSCANF_R __ssvfscanf_r
141
#else
142
#  define __SVFSCANF_R __svfscanf_r
143
#endif
144
#ifndef NO_FLOATING_POINT
145
#define FLOATING_POINT
146
#endif
147
#endif
148
 
149
#ifdef STRING_ONLY
150
#undef _flockfile
151
#undef _funlockfile
152
#define _flockfile(x) {}
153
#define _funlockfile(x) {}
154
#define _ungetc_r _sungetc_r
155
#define __srefill_r __ssrefill_r
156
#define _fread_r _sfread_r
157
#endif
158
 
159
#ifdef FLOATING_POINT
160
#include <math.h>
161
#include <float.h>
162
 
163
/* Currently a test is made to see if long double processing is warranted.
164
   This could be changed in the future should the _ldtoa_r code be
165
   preferred over _dtoa_r.  */
166
#define _NO_LONGDBL
167
#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
168
#undef _NO_LONGDBL
169
extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
170
#endif
171
 
172
#include "floatio.h"
173
 
174
#if ((MAXEXP+MAXFRACT+3) > MB_LEN_MAX)
175
#  define BUF (MAXEXP+MAXFRACT+3)        /* 3 = sign + decimal point + NUL */
176
#else
177
#  define BUF MB_LEN_MAX
178
#endif
179
 
180
/* An upper bound for how long a long prints in decimal.  4 / 13 approximates
181
   log (2).  Add one char for roundoff compensation and one for the sign.  */
182
#define MAX_LONG_LEN ((CHAR_BIT * sizeof (long)  - 1) * 4 / 13 + 2)
183
#else
184
#define BUF     40
185
#endif
186
 
187
#define _NO_LONGLONG
188
#if defined _WANT_IO_LONG_LONG \
189
        && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
190
# undef _NO_LONGLONG
191
#endif
192
 
193
#define _NO_POS_ARGS
194
#ifdef _WANT_IO_POS_ARGS
195
# undef _NO_POS_ARGS
196
# ifdef NL_ARGMAX
197
#  define MAX_POS_ARGS NL_ARGMAX
198
# else
199
#  define MAX_POS_ARGS 32
200
# endif
201
 
202
static void * get_arg (int, va_list *, int *, void **);
203
#endif /* _WANT_IO_POS_ARGS */
204
 
205
/*
206
 * Flags used during conversion.
207
 */
208
 
209
#define LONG            0x01    /* l: long or double */
210
#define LONGDBL         0x02    /* L/ll: long double or long long */
211
#define SHORT           0x04    /* h: short */
212
#define CHAR            0x08    /* hh: 8 bit integer */
213
#define SUPPRESS        0x10    /* suppress assignment */
214
#define POINTER         0x20    /* weird %p pointer (`fake hex') */
215
#define NOSKIP          0x40    /* do not skip blanks */
216
 
217
/*
218
 * The following are used in numeric conversions only:
219
 * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
220
 * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
221
 */
222
 
223
#define SIGNOK          0x80    /* +/- is (still) legal */
224
#define NDIGITS         0x100   /* no digits detected */
225
 
226
#define DPTOK           0x200   /* (float) decimal point is still legal */
227
#define EXPOK           0x400   /* (float) exponent (e+3, etc) still legal */
228
 
229
#define PFXOK           0x200   /* 0x prefix is (still) legal */
230
#define NZDIGITS        0x400   /* no zero digits detected */
231
#define NNZDIGITS       0x800   /* no non-zero digits detected */
232
 
233
/*
234
 * Conversion types.
235
 */
236
 
237
#define CT_CHAR         0        /* %c conversion */
238
#define CT_CCL          1       /* %[...] conversion */
239
#define CT_STRING       2       /* %s conversion */
240
#define CT_INT          3       /* integer, i.e., strtol or strtoul */
241
#define CT_FLOAT        4       /* floating, i.e., strtod */
242
 
243
#if 0
244
#define u_char unsigned char
245
#endif
246
#define u_char char
247
#define u_long unsigned long
248
 
249
#ifndef _NO_LONGLONG
250
typedef unsigned long long u_long_long;
251
#endif
252
 
253
/*
254
 * vfscanf
255
 */
256
 
257
#define BufferEmpty (fp->_r <= 0 && __srefill_r(rptr, fp))
258
 
259
#ifndef STRING_ONLY
260
 
261
#ifndef _REENT_ONLY
262
 
263
int
264
_DEFUN(VFSCANF, (fp, fmt, ap),
265
       register FILE *fp _AND
266
       _CONST char *fmt _AND
267
       va_list ap)
268
{
269
  CHECK_INIT(_REENT, fp);
270
  return __SVFSCANF_R (_REENT, fp, fmt, ap);
271
}
272
 
273
int
274
_DEFUN(__SVFSCANF, (fp, fmt0, ap),
275
       register FILE *fp _AND
276
       char _CONST *fmt0 _AND
277
       va_list ap)
278
{
279
  return __SVFSCANF_R (_REENT, fp, fmt0, ap);
280
}
281
 
282
#endif /* !_REENT_ONLY */
283
 
284
int
285
_DEFUN(_VFSCANF_R, (data, fp, fmt, ap),
286
       struct _reent *data _AND
287
       register FILE *fp   _AND
288
       _CONST char *fmt    _AND
289
       va_list ap)
290
{
291
  CHECK_INIT(data, fp);
292
  return __SVFSCANF_R (data, fp, fmt, ap);
293
}
294
#endif /* !STRING_ONLY */
295
 
296
#ifdef STRING_ONLY
297
/* When dealing with the sscanf family, we don't want to use the
298
 * regular ungetc which will drag in file I/O items we don't need.
299
 * So, we create our own trimmed-down version.  */
300
static int
301
_DEFUN(_sungetc_r, (data, fp, ch),
302
        struct _reent *data _AND
303
        int c               _AND
304
        register FILE *fp)
305
{
306
  if (c == EOF)
307
    return (EOF);
308
 
309
  /* After ungetc, we won't be at eof anymore */
310
  fp->_flags &= ~__SEOF;
311
  c = (unsigned char) c;
312
 
313
  /*
314
   * If we are in the middle of ungetc'ing, just continue.
315
   * This may require expanding the current ungetc buffer.
316
   */
317
 
318
  if (HASUB (fp))
319
    {
320
      if (fp->_r >= fp->_ub._size && __submore (data, fp))
321
        {
322
          return EOF;
323
        }
324
      *--fp->_p = c;
325
      fp->_r++;
326
      return c;
327
    }
328
 
329
  /*
330
   * If we can handle this by simply backing up, do so,
331
   * but never replace the original character.
332
   * (This makes sscanf() work when scanning `const' data.)
333
   */
334
 
335
  if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
336
    {
337
      fp->_p--;
338
      fp->_r++;
339
      return c;
340
    }
341
 
342
  /*
343
   * Create an ungetc buffer.
344
   * Initially, we will use the `reserve' buffer.
345
   */
346
 
347
  fp->_ur = fp->_r;
348
  fp->_up = fp->_p;
349
  fp->_ub._base = fp->_ubuf;
350
  fp->_ub._size = sizeof (fp->_ubuf);
351
  fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
352
  fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
353
  fp->_r = 1;
354
  return c;
355
}
356
 
357
/* String only version of __srefill_r for sscanf family.  */
358
static int
359
_DEFUN(__ssrefill_r, (ptr, fp),
360
       struct _reent * ptr _AND
361
       register FILE * fp)
362
{
363
  /*
364
   * Our only hope of further input is the ungetc buffer.
365
   * If there is anything in that buffer to read, return.
366
   */
367
  if (HASUB (fp))
368
    {
369
      FREEUB (ptr, fp);
370
      if ((fp->_r = fp->_ur) != 0)
371
        {
372
          fp->_p = fp->_up;
373
          return 0;
374
        }
375
    }
376
 
377
  /* Otherwise we are out of character input.  */
378
  fp->_p = fp->_bf._base;
379
  fp->_r = 0;
380
  fp->_flags |= __SEOF;
381
  return EOF;
382
}
383
 
384
static size_t
385
_DEFUN(_sfread_r, (ptr, buf, size, count, fp),
386
       struct _reent * ptr _AND
387
       _PTR buf _AND
388
       size_t size _AND
389
       size_t count _AND
390
       FILE * fp)
391
{
392
  register size_t resid;
393
  register char *p;
394
  register int r;
395
  size_t total;
396
 
397
  if ((resid = count * size) == 0)
398
    return 0;
399
 
400
  total = resid;
401
  p = buf;
402
 
403
  while (resid > (r = fp->_r))
404
    {
405
      _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) r);
406
      fp->_p += r;
407
      fp->_r = 0;
408
      p += r;
409
      resid -= r;
410
      if (__ssrefill_r (ptr, fp))
411
        {
412
          /* no more input: return partial result */
413
          return (total - resid) / size;
414
        }
415
    }
416
  _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, resid);
417
  fp->_r -= resid;
418
  fp->_p += resid;
419
  return count;
420
}
421
#endif /* STRING_ONLY */
422
 
423
int
424
_DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
425
       struct _reent *rptr _AND
426
       register FILE *fp   _AND
427
       char _CONST *fmt0   _AND
428
       va_list ap)
429
{
430
  register u_char *fmt = (u_char *) fmt0;
431
  register int c;               /* character from format, or conversion */
432
  register size_t width;        /* field width, or 0 */
433
  register char *p;             /* points into all kinds of strings */
434
  register int n;               /* handy integer */
435
  register int flags;           /* flags as defined above */
436
  register char *p0;            /* saves original value of p when necessary */
437
  int nassigned;                /* number of fields assigned */
438
  int nread;                    /* number of characters consumed from fp */
439
#ifndef _NO_POS_ARGS
440
  int N;                        /* arg number */
441
  int arg_index = 0;             /* index into args processed directly */
442
  int numargs = 0;               /* number of varargs read */
443
  void *args[MAX_POS_ARGS];     /* positional args read */
444
  int is_pos_arg;               /* is current format positional? */
445
#endif
446
  int base = 0;                  /* base argument to strtol/strtoul */
447
  int nbytes = 1;               /* number of bytes read from fmt string */
448
  wchar_t wc;                   /* wchar to use to read format string */
449
  wchar_t *wcp;                 /* handy wide character pointer */
450
  size_t mbslen;                /* length of converted multibyte sequence */
451
  mbstate_t state;              /* value to keep track of multibyte state */
452
 
453
  #define CCFN_PARAMS   _PARAMS((struct _reent *, const char *, char **, int))
454
  u_long (*ccfn)CCFN_PARAMS=0;   /* conversion function (strtol/strtoul) */
455
  char ccltab[256];             /* character class table for %[...] */
456
  char buf[BUF];                /* buffer for numeric conversions */
457
  char *lptr;                   /* literal pointer */
458
 
459
  char *cp;
460
  short *sp;
461
  int *ip;
462
#ifdef FLOATING_POINT
463
  float *flp;
464
  _LONG_DOUBLE *ldp;
465
  double *dp;
466
#endif
467
  long *lp;
468
#ifndef _NO_LONGLONG
469
  long long *llp;
470
#endif
471
 
472
  /* `basefix' is used to avoid `if' tests in the integer scanner */
473
  static _CONST short basefix[17] =
474
    {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
475
 
476
  /* Macro to support positional arguments */
477
#ifndef _NO_POS_ARGS
478
# define GET_ARG(n, ap, type)                                   \
479
  ((type) (is_pos_arg                                           \
480
           ? (n < numargs                                       \
481
              ? args[n]                                         \
482
              : get_arg (n, &ap, &numargs, args))               \
483
           : (arg_index++ < numargs                             \
484
              ? args[n]                                         \
485
              : (numargs < MAX_POS_ARGS                         \
486
                 ? args[numargs++] = va_arg (ap, void *)        \
487
                 : va_arg (ap, void *)))))
488
#else
489
# define GET_ARG(n, ap, type) (va_arg (ap, type))
490
#endif
491
 
492
  _flockfile (fp);
493
 
494
  ORIENT (fp, -1);
495
 
496
  nassigned = 0;
497
  nread = 0;
498
  for (;;)
499
    {
500
#ifndef _MB_CAPABLE
501
      wc = *fmt;
502
#else
503
      memset (&state, '\0', sizeof (state));
504
      nbytes = _mbtowc_r (rptr, &wc, fmt, MB_CUR_MAX, &state);
505
#endif
506
      fmt += nbytes;
507
      if (wc == 0)
508
        goto all_done;
509
      if (nbytes == 1 && isspace (wc))
510
        {
511
          for (;;)
512
            {
513
              if (BufferEmpty || !isspace (*fp->_p))
514
                break;
515
              nread++, fp->_r--, fp->_p++;
516
            }
517
          continue;
518
        }
519
      if (wc != '%')
520
        goto literal;
521
      width = 0;
522
      flags = 0;
523
#ifndef _NO_POS_ARGS
524
      N = arg_index;
525
      is_pos_arg = 0;
526
#endif
527
 
528
      /*
529
       * switch on the format.  continue if done; break once format
530
       * type is derived.
531
       */
532
 
533
    again:
534
      c = *fmt++;
535
 
536
      switch (c)
537
        {
538
        case '%':
539
        literal:
540
          lptr = fmt - nbytes;
541
          for (n = 0; n < nbytes; ++n)
542
            {
543
              if (BufferEmpty)
544
                goto input_failure;
545
              if (*fp->_p != *lptr)
546
                goto match_failure;
547
              fp->_r--, fp->_p++;
548
              nread++;
549
              ++lptr;
550
            }
551
          continue;
552
 
553
        case '*':
554
          flags |= SUPPRESS;
555
          goto again;
556
        case 'l':
557
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
558
          if (*fmt == 'l')      /* Check for 'll' = long long (SUSv3) */
559
            {
560
              ++fmt;
561
              flags |= LONGDBL;
562
            }
563
          else
564
#endif
565
            flags |= LONG;
566
          goto again;
567
        case 'L':
568
          flags |= LONGDBL;
569
          goto again;
570
        case 'h':
571
#ifdef _WANT_IO_C99_FORMATS
572
          if (*fmt == 'h')      /* Check for 'hh' = char int (SUSv3) */
573
            {
574
              ++fmt;
575
              flags |= CHAR;
576
            }
577
          else
578
#endif
579
            flags |= SHORT;
580
          goto again;
581
#ifdef _WANT_IO_C99_FORMATS
582
        case 'j': /* intmax_t */
583
          if (sizeof (intmax_t) == sizeof (long))
584
            flags |= LONG;
585
          else
586
            flags |= LONGDBL;
587
          goto again;
588
        case 't': /* ptrdiff_t */
589
          if (sizeof (ptrdiff_t) < sizeof (int))
590
            /* POSIX states ptrdiff_t is 16 or more bits, as
591
               is short.  */
592
            flags |= SHORT;
593
          else if (sizeof (ptrdiff_t) == sizeof (int))
594
            /* no flag needed */;
595
          else if (sizeof (ptrdiff_t) <= sizeof (long))
596
            flags |= LONG;
597
          else
598
            /* POSIX states that at least one programming
599
               environment must support ptrdiff_t no wider than
600
               long, but that means other environments can
601
               have ptrdiff_t as wide as long long.  */
602
            flags |= LONGDBL;
603
          goto again;
604
        case 'z': /* size_t */
605
          if (sizeof (size_t) < sizeof (int))
606
            /* POSIX states size_t is 16 or more bits, as is short.  */
607
            flags |= SHORT;
608
          else if (sizeof (size_t) == sizeof (int))
609
            /* no flag needed */;
610
          else if (sizeof (size_t) <= sizeof (long))
611
            flags |= LONG;
612
          else
613
            /* POSIX states that at least one programming
614
               environment must support size_t no wider than
615
               long, but that means other environments can
616
               have size_t as wide as long long.  */
617
            flags |= LONGDBL;
618
          goto again;
619
#endif /* _WANT_IO_C99_FORMATS */
620
 
621
        case '0':
622
        case '1':
623
        case '2':
624
        case '3':
625
        case '4':
626
        case '5':
627
        case '6':
628
        case '7':
629
        case '8':
630
        case '9':
631
          width = width * 10 + c - '0';
632
          goto again;
633
 
634
#ifndef _NO_POS_ARGS
635
        case '$':
636
          if (width <= MAX_POS_ARGS)
637
            {
638
              N = width - 1;
639
              is_pos_arg = 1;
640
              width = 0;
641
              goto again;
642
            }
643
          rptr->_errno = EINVAL;
644
          goto input_failure;
645
#endif /* !_NO_POS_ARGS */
646
 
647
          /*
648
           * Conversions. Those marked `compat' are for
649
           * 4.[123]BSD compatibility.
650
           *
651
           * (According to ANSI, E and X formats are supposed to
652
           * the same as e and x.  Sorry about that.)
653
           */
654
 
655
        case 'D':               /* compat */
656
          flags |= LONG;
657
          /* FALLTHROUGH */
658
        case 'd':
659
          c = CT_INT;
660
          ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
661
          base = 10;
662
          break;
663
 
664
        case 'i':
665
          c = CT_INT;
666
          ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
667
          base = 0;
668
          break;
669
 
670
        case 'O':               /* compat */
671
          flags |= LONG;
672
          /* FALLTHROUGH */
673
        case 'o':
674
          c = CT_INT;
675
          ccfn = _strtoul_r;
676
          base = 8;
677
          break;
678
 
679
        case 'u':
680
          c = CT_INT;
681
          ccfn = _strtoul_r;
682
          base = 10;
683
          break;
684
 
685
        case 'X':
686
        case 'x':
687
          flags |= PFXOK;       /* enable 0x prefixing */
688
          c = CT_INT;
689
          ccfn = _strtoul_r;
690
          base = 16;
691
          break;
692
 
693
#ifdef FLOATING_POINT
694
# ifdef _WANT_IO_C99_FORMATS
695
        case 'a':
696
        case 'A':
697
        case 'F':
698
# endif
699
        case 'E':
700
        case 'G':
701
        case 'e':
702
        case 'f':
703
        case 'g':
704
          c = CT_FLOAT;
705
          break;
706
#endif
707
 
708
#ifdef _WANT_IO_C99_FORMATS
709
        case 'S':
710
          flags |= LONG;
711
          /* FALLTHROUGH */
712
#endif
713
 
714
        case 's':
715
          c = CT_STRING;
716
          break;
717
 
718
        case '[':
719
          fmt = __sccl (ccltab, fmt);
720
          flags |= NOSKIP;
721
          c = CT_CCL;
722
          break;
723
 
724
#ifdef _WANT_IO_C99_FORMATS
725
        case 'C':
726
          flags |= LONG;
727
          /* FALLTHROUGH */
728
#endif
729
 
730
        case 'c':
731
          flags |= NOSKIP;
732
          c = CT_CHAR;
733
          break;
734
 
735
        case 'p':               /* pointer format is like hex */
736
          flags |= POINTER | PFXOK;
737
          c = CT_INT;
738
          ccfn = _strtoul_r;
739
          base = 16;
740
          break;
741
 
742
        case 'n':
743
          if (flags & SUPPRESS) /* ??? */
744
            continue;
745
#ifdef _WANT_IO_C99_FORMATS
746
          if (flags & CHAR)
747
            {
748
              cp = GET_ARG (N, ap, char *);
749
              *cp = nread;
750
            }
751
          else
752
#endif
753
          if (flags & SHORT)
754
            {
755
              sp = GET_ARG (N, ap, short *);
756
              *sp = nread;
757
            }
758
          else if (flags & LONG)
759
            {
760
              lp = GET_ARG (N, ap, long *);
761
              *lp = nread;
762
            }
763
#ifndef _NO_LONGLONG
764
          else if (flags & LONGDBL)
765
            {
766
              llp = GET_ARG (N, ap, long long*);
767
              *llp = nread;
768
            }
769
#endif
770
          else
771
            {
772
              ip = GET_ARG (N, ap, int *);
773
              *ip = nread;
774
            }
775
          continue;
776
 
777
          /*
778
           * Disgusting backwards compatibility hacks.  XXX
779
           */
780
        case '\0':              /* compat */
781
          _funlockfile (fp);
782
          return EOF;
783
 
784
        default:                /* compat */
785
          if (isupper (c))
786
            flags |= LONG;
787
          c = CT_INT;
788
          ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
789
          base = 10;
790
          break;
791
        }
792
 
793
      /*
794
       * We have a conversion that requires input.
795
       */
796
      if (BufferEmpty)
797
        goto input_failure;
798
 
799
      /*
800
       * Consume leading white space, except for formats that
801
       * suppress this.
802
       */
803
      if ((flags & NOSKIP) == 0)
804
        {
805
          while (isspace (*fp->_p))
806
            {
807
              nread++;
808
              if (--fp->_r > 0)
809
                fp->_p++;
810
              else
811
              if (__srefill_r (rptr, fp))
812
                goto input_failure;
813
            }
814
          /*
815
           * Note that there is at least one character in the
816
           * buffer, so conversions that do not set NOSKIP ca
817
           * no longer result in an input failure.
818
           */
819
        }
820
 
821
      /*
822
       * Do the conversion.
823
       */
824
      switch (c)
825
        {
826
 
827
        case CT_CHAR:
828
          /* scan arbitrary characters (sets NOSKIP) */
829
          if (width == 0)
830
            width = 1;
831
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
832
          if (flags & LONG)
833
            {
834
              if ((flags & SUPPRESS) == 0)
835
                wcp = GET_ARG (N, ap, wchar_t *);
836
              else
837
                wcp = NULL;
838
              n = 0;
839
              while (width != 0)
840
                {
841
                  if (n == MB_CUR_MAX)
842
                    goto input_failure;
843
                  buf[n++] = *fp->_p;
844
                  fp->_r -= 1;
845
                  fp->_p += 1;
846
                  memset ((_PTR)&state, '\0', sizeof (mbstate_t));
847
                  if ((mbslen = _mbrtowc_r (rptr, wcp, buf, n, &state))
848
                                                         == (size_t)-1)
849
                    goto input_failure; /* Invalid sequence */
850
                  if (mbslen == 0 && !(flags & SUPPRESS))
851
                    *wcp = L'\0';
852
                  if (mbslen != (size_t)-2) /* Incomplete sequence */
853
                    {
854
                      nread += n;
855
                      width -= 1;
856
                      if (!(flags & SUPPRESS))
857
                        wcp += 1;
858
                      n = 0;
859
                    }
860
                  if (BufferEmpty)
861
                    {
862
                      if (n != 0)
863
                        goto input_failure;
864
                      break;
865
                    }
866
                }
867
              if (!(flags & SUPPRESS))
868
                nassigned++;
869
            }
870
          else
871
#endif
872
                  if (flags & SUPPRESS)
873
            {
874
              size_t sum = 0;
875
              for (;;)
876
                {
877
                  if ((n = fp->_r) < (int)width)
878
                    {
879
                      sum += n;
880
                      width -= n;
881
                      fp->_p += n;
882
                      if (__srefill_r (rptr, fp))
883
                        {
884
                          if (sum == 0)
885
                            goto input_failure;
886
                          break;
887
                        }
888
                    }
889
                  else
890
                    {
891
                      sum += width;
892
                      fp->_r -= width;
893
                      fp->_p += width;
894
                      break;
895
                    }
896
                }
897
              nread += sum;
898
            }
899
          else
900
            {
901
              size_t r = _fread_r (rptr, (_PTR) GET_ARG (N, ap, char *), 1, width, fp);
902
 
903
              if (r == 0)
904
                goto input_failure;
905
              nread += r;
906
              nassigned++;
907
            }
908
          break;
909
 
910
        case CT_CCL:
911
          /* scan a (nonempty) character class (sets NOSKIP) */
912
          if (width == 0)
913
            width = ~0;          /* `infinity' */
914
          /* take only those things in the class */
915
          if (flags & SUPPRESS)
916
            {
917
              n = 0;
918
              while (ccltab[*fp->_p])
919
                {
920
                  n++, fp->_r--, fp->_p++;
921
                  if (--width == 0)
922
                    break;
923
                  if (BufferEmpty)
924
                    {
925
                      if (n == 0)
926
                        goto input_failure;
927
                      break;
928
                    }
929
                }
930
              if (n == 0)
931
                goto match_failure;
932
            }
933
          else
934
            {
935
              p0 = p = GET_ARG (N, ap, char *);
936
              while (ccltab[*fp->_p])
937
                {
938
                  fp->_r--;
939
                  *p++ = *fp->_p++;
940
                  if (--width == 0)
941
                    break;
942
                  if (BufferEmpty)
943
                    {
944
                      if (p == p0)
945
                        goto input_failure;
946
                      break;
947
                    }
948
                }
949
              n = p - p0;
950
              if (n == 0)
951
                goto match_failure;
952
              *p = 0;
953
              nassigned++;
954
            }
955
          nread += n;
956
          break;
957
 
958
        case CT_STRING:
959
          /* like CCL, but zero-length string OK, & no NOSKIP */
960
          if (width == 0)
961
            width = (size_t)~0;
962
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
963
          if (flags & LONG)
964
            {
965
              /* Process %S and %ls placeholders */
966
              if ((flags & SUPPRESS) == 0)
967
                wcp = GET_ARG (N, ap, wchar_t *);
968
              else
969
                wcp = &wc;
970
              n = 0;
971
              while (!isspace (*fp->_p) && width != 0)
972
                {
973
                  if (n == MB_CUR_MAX)
974
                    goto input_failure;
975
                  buf[n++] = *fp->_p;
976
                  fp->_r -= 1;
977
                  fp->_p += 1;
978
                  memset ((_PTR)&state, '\0', sizeof (mbstate_t));
979
                  if ((mbslen = _mbrtowc_r (rptr, wcp, buf, n, &state))
980
                                                        == (size_t)-1)
981
                    goto input_failure;
982
                  if (mbslen == 0)
983
                    *wcp = L'\0';
984
                  if (mbslen != (size_t)-2) /* Incomplete sequence */
985
                    {
986
                      if (iswspace(*wcp))
987
                        {
988
                          while (n != 0)
989
                            _ungetc_r (rptr, (unsigned char) buf[--n], fp);
990
                          break;
991
                        }
992
                      nread += n;
993
                      width -= 1;
994
                      if ((flags & SUPPRESS) == 0)
995
                        wcp += 1;
996
                      n = 0;
997
                    }
998
                  if (BufferEmpty)
999
                    {
1000
                      if (n != 0)
1001
                        goto input_failure;
1002
                      break;
1003
                    }
1004
                }
1005
              if (!(flags & SUPPRESS))
1006
                {
1007
                  *wcp = L'\0';
1008
                  nassigned++;
1009
                }
1010
            }
1011
          else
1012
#endif
1013
                  if (flags & SUPPRESS)
1014
            {
1015
              n = 0;
1016
              while (!isspace (*fp->_p))
1017
                {
1018
                  n++, fp->_r--, fp->_p++;
1019
                  if (--width == 0)
1020
                    break;
1021
                  if (BufferEmpty)
1022
                    break;
1023
                }
1024
              nread += n;
1025
            }
1026
          else
1027
            {
1028
              p0 = p = GET_ARG (N, ap, char *);
1029
              while (!isspace (*fp->_p))
1030
                {
1031
                  fp->_r--;
1032
                  *p++ = *fp->_p++;
1033
                  if (--width == 0)
1034
                    break;
1035
                  if (BufferEmpty)
1036
                    break;
1037
                }
1038
              *p = 0;
1039
              nread += p - p0;
1040
              nassigned++;
1041
            }
1042
          continue;
1043
 
1044
        case CT_INT:
1045
        {
1046
          /* scan an integer as if by strtol/strtoul */
1047
          unsigned width_left = 0;
1048
          int skips = 0;
1049
#ifdef hardway
1050
          if (width == 0 || width > sizeof (buf) - 1)
1051
#else
1052
          /* size_t is unsigned, hence this optimisation */
1053
          if (width - 1 > sizeof (buf) - 2)
1054
#endif
1055
            {
1056
              width_left = width - (sizeof (buf) - 1);
1057
              width = sizeof (buf) - 1;
1058
            }
1059
          flags |= SIGNOK | NDIGITS | NZDIGITS | NNZDIGITS;
1060
          for (p = buf; width; width--)
1061
            {
1062
              c = *fp->_p;
1063
              /*
1064
               * Switch on the character; `goto ok' if we
1065
               * accept it as a part of number.
1066
               */
1067
              switch (c)
1068
                {
1069
                  /*
1070
                   * The digit 0 is always legal, but is special.
1071
                   * For %i conversions, if no digits (zero or nonzero)
1072
                   * have been scanned (only signs), we will have base==0.
1073
                   * In that case, we should set it to 8 and enable 0x
1074
                   * prefixing. Also, if we have not scanned zero digits
1075
                   * before this, do not turn off prefixing (someone else
1076
                   * will turn it off if we have scanned any nonzero digits).
1077
                   */
1078
                case '0':
1079
                  if (! (flags & NNZDIGITS))
1080
                    goto ok;
1081
                  if (base == 0)
1082
                    {
1083
                      base = 8;
1084
                      flags |= PFXOK;
1085
                    }
1086
                  if (flags & NZDIGITS)
1087
                    {
1088
                      flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
1089
                      goto ok;
1090
                    }
1091
                  flags &= ~(SIGNOK | PFXOK | NDIGITS);
1092
                  if (width_left)
1093
                    {
1094
                      width_left--;
1095
                      width++;
1096
                    }
1097
                  ++skips;
1098
                  goto skip;
1099
 
1100
                  /* 1 through 7 always legal */
1101
                case '1':
1102
                case '2':
1103
                case '3':
1104
                case '4':
1105
                case '5':
1106
                case '6':
1107
                case '7':
1108
                  base = basefix[base];
1109
                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1110
                  goto ok;
1111
 
1112
                  /* digits 8 and 9 ok iff decimal or hex */
1113
                case '8':
1114
                case '9':
1115
                  base = basefix[base];
1116
                  if (base <= 8)
1117
                    break;      /* not legal here */
1118
                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1119
                  goto ok;
1120
 
1121
                  /* letters ok iff hex */
1122
                case 'A':
1123
                case 'B':
1124
                case 'C':
1125
                case 'D':
1126
                case 'E':
1127
                case 'F':
1128
                case 'a':
1129
                case 'b':
1130
                case 'c':
1131
                case 'd':
1132
                case 'e':
1133
                case 'f':
1134
                  /* no need to fix base here */
1135
                  if (base <= 10)
1136
                    break;      /* not legal here */
1137
                  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1138
                  goto ok;
1139
 
1140
                  /* sign ok only as first character */
1141
                case '+':
1142
                case '-':
1143
                  if (flags & SIGNOK)
1144
                    {
1145
                      flags &= ~SIGNOK;
1146
                      goto ok;
1147
                    }
1148
                  break;
1149
 
1150
                  /* x ok iff flag still set & single 0 seen */
1151
                case 'x':
1152
                case 'X':
1153
                  if ((flags & (PFXOK | NZDIGITS)) == PFXOK)
1154
                    {
1155
                      base = 16;/* if %i */
1156
                      flags &= ~PFXOK;
1157
                      /* We must reset the NZDIGITS and NDIGITS
1158
                         flags that would have been unset by seeing
1159
                         the zero that preceded the X or x.  */
1160
                      flags |= NZDIGITS | NDIGITS;
1161
                      goto ok;
1162
                    }
1163
                  break;
1164
                }
1165
 
1166
              /*
1167
               * If we got here, c is not a legal character
1168
               * for a number.  Stop accumulating digits.
1169
               */
1170
              break;
1171
            ok:
1172
              /*
1173
               * c is legal: store it and look at the next.
1174
               */
1175
              *p++ = c;
1176
            skip:
1177
              if (--fp->_r > 0)
1178
                fp->_p++;
1179
              else
1180
              if (__srefill_r (rptr, fp))
1181
                break;          /* EOF */
1182
            }
1183
          /*
1184
           * If we had only a sign, it is no good; push back the sign.
1185
           * If the number ends in `x', it was [sign] '0' 'x', so push back
1186
           * the x and treat it as [sign] '0'.
1187
           * Use of ungetc here and below assumes ASCII encoding; we are only
1188
           * pushing back 7-bit characters, so casting to unsigned char is
1189
           * not necessary.
1190
           */
1191
          if (flags & NDIGITS)
1192
            {
1193
              if (p > buf)
1194
                _ungetc_r (rptr, *--p, fp); /* [-+xX] */
1195
              if (p == buf)
1196
                goto match_failure;
1197
            }
1198
          if ((flags & SUPPRESS) == 0)
1199
            {
1200
              u_long res;
1201
 
1202
              *p = 0;
1203
              res = (*ccfn) (rptr, buf, (char **) NULL, base);
1204
              if (flags & POINTER)
1205
                {
1206
                  void **vp = GET_ARG (N, ap, void **);
1207
#ifndef _NO_LONGLONG
1208
                  if (sizeof (uintptr_t) > sizeof (u_long))
1209
                    {
1210
                      u_long_long resll;
1211
                      resll = _strtoull_r (rptr, buf, (char **) NULL, base);
1212
                      *vp = (void *) (uintptr_t) resll;
1213
                    }
1214
                  else
1215
#endif /* !_NO_LONGLONG */
1216
                    *vp = (void *) (uintptr_t) res;
1217
                }
1218
#ifdef _WANT_IO_C99_FORMATS
1219
              else if (flags & CHAR)
1220
                {
1221
                  cp = GET_ARG (N, ap, char *);
1222
                  *cp = res;
1223
                }
1224
#endif
1225
              else if (flags & SHORT)
1226
                {
1227
                  sp = GET_ARG (N, ap, short *);
1228
                  *sp = res;
1229
                }
1230
              else if (flags & LONG)
1231
                {
1232
                  lp = GET_ARG (N, ap, long *);
1233
                  *lp = res;
1234
                }
1235
#ifndef _NO_LONGLONG
1236
              else if (flags & LONGDBL)
1237
                {
1238
                  u_long_long resll;
1239
                  if (ccfn == _strtoul_r)
1240
                    resll = _strtoull_r (rptr, buf, (char **) NULL, base);
1241
                  else
1242
                    resll = _strtoll_r (rptr, buf, (char **) NULL, base);
1243
                  llp = GET_ARG (N, ap, long long*);
1244
                  *llp = resll;
1245
                }
1246
#endif
1247
              else
1248
                {
1249
                  ip = GET_ARG (N, ap, int *);
1250
                  *ip = res;
1251
                }
1252
              nassigned++;
1253
            }
1254
          nread += p - buf + skips;
1255
          break;
1256
        }
1257
#ifdef FLOATING_POINT
1258
        case CT_FLOAT:
1259
        {
1260
          /* scan a floating point number as if by strtod */
1261
          /* This code used to assume that the number of digits is reasonable.
1262
             However, ANSI / ISO C makes no such stipulation; we have to get
1263
             exact results even when there is an unreasonable amount of
1264
             leading zeroes.  */
1265
          long leading_zeroes = 0;
1266
          long zeroes, exp_adjust;
1267
          char *exp_start = NULL;
1268
          unsigned width_left = 0;
1269
          char nancount = 0;
1270
          char infcount = 0;
1271
#ifdef hardway
1272
          if (width == 0 || width > sizeof (buf) - 1)
1273
#else
1274
          /* size_t is unsigned, hence this optimisation */
1275
          if (width - 1 > sizeof (buf) - 2)
1276
#endif
1277
            {
1278
              width_left = width - (sizeof (buf) - 1);
1279
              width = sizeof (buf) - 1;
1280
            }
1281
          flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
1282
          zeroes = 0;
1283
          exp_adjust = 0;
1284
          for (p = buf; width; )
1285
            {
1286
              c = *fp->_p;
1287
              /*
1288
               * This code mimicks the integer conversion
1289
               * code, but is much simpler.
1290
               */
1291
              switch (c)
1292
                {
1293
                case '0':
1294
                  if (flags & NDIGITS)
1295
                    {
1296
                      flags &= ~SIGNOK;
1297
                      zeroes++;
1298
                      if (width_left)
1299
                        {
1300
                          width_left--;
1301
                          width++;
1302
                        }
1303
                      goto fskip;
1304
                    }
1305
                  /* Fall through.  */
1306
                case '1':
1307
                case '2':
1308
                case '3':
1309
                case '4':
1310
                case '5':
1311
                case '6':
1312
                case '7':
1313
                case '8':
1314
                case '9':
1315
                  if (nancount + infcount == 0)
1316
                    {
1317
                      flags &= ~(SIGNOK | NDIGITS);
1318
                      goto fok;
1319
                    }
1320
                  break;
1321
 
1322
                case '+':
1323
                case '-':
1324
                  if (flags & SIGNOK)
1325
                    {
1326
                      flags &= ~SIGNOK;
1327
                      goto fok;
1328
                    }
1329
                  break;
1330
                case 'n':
1331
                case 'N':
1332
                  if (nancount == 0
1333
                      && (flags & (NDIGITS | DPTOK | EXPOK)) ==
1334
                                  (NDIGITS | DPTOK | EXPOK))
1335
                    {
1336
                      flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
1337
                      nancount = 1;
1338
                      goto fok;
1339
                    }
1340
                  if (nancount == 2)
1341
                    {
1342
                      nancount = 3;
1343
                      goto fok;
1344
                    }
1345
                  if (infcount == 1 || infcount == 4)
1346
                    {
1347
                      infcount++;
1348
                      goto fok;
1349
                    }
1350
                  break;
1351
                case 'a':
1352
                case 'A':
1353
                  if (nancount == 1)
1354
                    {
1355
                      nancount = 2;
1356
                      goto fok;
1357
                    }
1358
                  break;
1359
                case 'i':
1360
                case 'I':
1361
                  if (infcount == 0
1362
                      && (flags & (NDIGITS | DPTOK | EXPOK)) ==
1363
                                  (NDIGITS | DPTOK | EXPOK))
1364
                    {
1365
                      flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
1366
                      infcount = 1;
1367
                      goto fok;
1368
                    }
1369
                  if (infcount == 3 || infcount == 5)
1370
                    {
1371
                      infcount++;
1372
                      goto fok;
1373
                    }
1374
                  break;
1375
                case 'f':
1376
                case 'F':
1377
                  if (infcount == 2)
1378
                    {
1379
                      infcount = 3;
1380
                      goto fok;
1381
                    }
1382
                  break;
1383
                case 't':
1384
                case 'T':
1385
                  if (infcount == 6)
1386
                    {
1387
                      infcount = 7;
1388
                      goto fok;
1389
                    }
1390
                  break;
1391
                case 'y':
1392
                case 'Y':
1393
                  if (infcount == 7)
1394
                    {
1395
                      infcount = 8;
1396
                      goto fok;
1397
                    }
1398
                  break;
1399
                case '.':
1400
                  if (flags & DPTOK)
1401
                    {
1402
                      flags &= ~(SIGNOK | DPTOK);
1403
                      leading_zeroes = zeroes;
1404
                      goto fok;
1405
                    }
1406
                  break;
1407
                case 'e':
1408
                case 'E':
1409
                  /* no exponent without some digits */
1410
                  if ((flags & (NDIGITS | EXPOK)) == EXPOK
1411
                      || ((flags & EXPOK) && zeroes))
1412
                    {
1413
                      if (! (flags & DPTOK))
1414
                        {
1415
                          exp_adjust = zeroes - leading_zeroes;
1416
                          exp_start = p;
1417
                        }
1418
                      flags =
1419
                        (flags & ~(EXPOK | DPTOK)) |
1420
                        SIGNOK | NDIGITS;
1421
                      zeroes = 0;
1422
                      goto fok;
1423
                    }
1424
                  break;
1425
                }
1426
              break;
1427
            fok:
1428
              *p++ = c;
1429
            fskip:
1430
              width--;
1431
              ++nread;
1432
              if (--fp->_r > 0)
1433
                fp->_p++;
1434
              else
1435
              if (__srefill_r (rptr, fp))
1436
                break;          /* EOF */
1437
            }
1438
          if (zeroes)
1439
            flags &= ~NDIGITS;
1440
          /* We may have a 'N' or possibly even [sign] 'N' 'a' as the
1441
             start of 'NaN', only to run out of chars before it was
1442
             complete (or having encountered a non-matching char).  So
1443
             check here if we have an outstanding nancount, and if so
1444
             put back the chars we did swallow and treat as a failed
1445
             match.
1446
 
1447
             FIXME - we still don't handle NAN([0xdigits]).  */
1448
          if (nancount - 1U < 2U) /* nancount && nancount < 3 */
1449
            {
1450
              /* Newlib's ungetc works even if we called __srefill in
1451
                 the middle of a partial parse, but POSIX does not
1452
                 guarantee that in all implementations of ungetc.  */
1453
              while (p > buf)
1454
                {
1455
                  _ungetc_r (rptr, *--p, fp); /* [-+nNaA] */
1456
                  --nread;
1457
                }
1458
              goto match_failure;
1459
            }
1460
          /* Likewise for 'inf' and 'infinity'.  But be careful that
1461
             'infinite' consumes only 3 characters, leaving the stream
1462
             at the second 'i'.  */
1463
          if (infcount - 1U < 7U) /* infcount && infcount < 8 */
1464
            {
1465
              if (infcount >= 3) /* valid 'inf', but short of 'infinity' */
1466
                while (infcount-- > 3)
1467
                  {
1468
                    _ungetc_r (rptr, *--p, fp); /* [iInNtT] */
1469
                    --nread;
1470
                  }
1471
              else
1472
                {
1473
                  while (p > buf)
1474
                    {
1475
                      _ungetc_r (rptr, *--p, fp); /* [-+iInN] */
1476
                      --nread;
1477
                    }
1478
                  goto match_failure;
1479
                }
1480
            }
1481
          /*
1482
           * If no digits, might be missing exponent digits
1483
           * (just give back the exponent) or might be missing
1484
           * regular digits, but had sign and/or decimal point.
1485
           */
1486
          if (flags & NDIGITS)
1487
            {
1488
              if (flags & EXPOK)
1489
                {
1490
                  /* no digits at all */
1491
                  while (p > buf)
1492
                    {
1493
                      _ungetc_r (rptr, *--p, fp); /* [-+.] */
1494
                      --nread;
1495
                    }
1496
                  goto match_failure;
1497
                }
1498
              /* just a bad exponent (e and maybe sign) */
1499
              c = *--p;
1500
              --nread;
1501
              if (c != 'e' && c != 'E')
1502
                {
1503
                  _ungetc_r (rptr, c, fp); /* [-+] */
1504
                  c = *--p;
1505
                  --nread;
1506
                }
1507
              _ungetc_r (rptr, c, fp); /* [eE] */
1508
            }
1509
          if ((flags & SUPPRESS) == 0)
1510
            {
1511
              double res = 0;
1512
#ifdef _NO_LONGDBL
1513
#define QUAD_RES res;
1514
#else  /* !_NO_LONG_DBL */
1515
              long double qres = 0;
1516
#define QUAD_RES qres;
1517
#endif /* !_NO_LONG_DBL */
1518
              long new_exp = 0;
1519
 
1520
              *p = 0;
1521
              if ((flags & (DPTOK | EXPOK)) == EXPOK)
1522
                {
1523
                  exp_adjust = zeroes - leading_zeroes;
1524
                  new_exp = -exp_adjust;
1525
                  exp_start = p;
1526
                }
1527
              else if (exp_adjust)
1528
                new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust;
1529
              if (exp_adjust)
1530
                {
1531
 
1532
                  /* If there might not be enough space for the new exponent,
1533
                     truncate some trailing digits to make room.  */
1534
                  if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)
1535
                    exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
1536
                 sprintf (exp_start, "e%ld", new_exp);
1537
                }
1538
 
1539
              /* Current _strtold routine is markedly slower than
1540
                 _strtod_r.  Only use it if we have a long double
1541
                 result.  */
1542
#ifndef _NO_LONGDBL /* !_NO_LONGDBL */
1543
              if (flags & LONGDBL)
1544
                qres = _strtold (buf, NULL);
1545
              else
1546
#endif
1547
                res = _strtod_r (rptr, buf, NULL);
1548
 
1549
              if (flags & LONG)
1550
                {
1551
                  dp = GET_ARG (N, ap, double *);
1552
                  *dp = res;
1553
                }
1554
              else if (flags & LONGDBL)
1555
                {
1556
                  ldp = GET_ARG (N, ap, _LONG_DOUBLE *);
1557
                  *ldp = QUAD_RES;
1558
                }
1559
              else
1560
                {
1561
                  flp = GET_ARG (N, ap, float *);
1562
                  if (isnan (res))
1563
                    *flp = nanf (NULL);
1564
                  else
1565
                    *flp = res;
1566
                }
1567
              nassigned++;
1568
            }
1569
          break;
1570
        }
1571
#endif /* FLOATING_POINT */
1572
        }
1573
    }
1574
input_failure:
1575
  /* On read failure, return EOF failure regardless of matches; errno
1576
     should have been set prior to here.  On EOF failure (including
1577
     invalid format string), return EOF if no matches yet, else number
1578
     of matches made prior to failure.  */
1579
  _funlockfile (fp);
1580
  return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
1581
match_failure:
1582
all_done:
1583
  /* Return number of matches, which can be 0 on match failure.  */
1584
  _funlockfile (fp);
1585
  return nassigned;
1586
}
1587
 
1588
#ifndef _NO_POS_ARGS
1589
/* Process all intermediate arguments.  Fortunately, with scanf, all
1590
   intermediate arguments are sizeof(void*), so we don't need to scan
1591
   ahead in the format string.  */
1592
static void *
1593
get_arg (int n, va_list *ap, int *numargs_p, void **args)
1594
{
1595
  int numargs = *numargs_p;
1596
  while (n >= numargs)
1597
    args[numargs++] = va_arg (*ap, void *);
1598
  *numargs_p = numargs;
1599
  return args[n];
1600
}
1601
#endif /* !_NO_POS_ARGS */

powered by: WebSVN 2.1.0

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