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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.18.0/] [newlib/] [libc/] [stdio/] [vfscanf.c] - Blame information for rev 207

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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