Subversion Repositories Kolibri OS

Rev

Rev 1693 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1693 serge 1
/*-
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
<>, <>, <>---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 
37
	#include 
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 
51
	#include 
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
<>, <>, and <> are (respectively) variants
85
of <>, <>, and <>.  They differ only in
86
allowing their caller to pass the variable argument list as a
87
<> object (initialized by <>) rather than
88
directly accepting a variable number of arguments.
89
 
90
RETURNS
91
The return values are consistent with the corresponding functions:
92
<> 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 <> attempts to read at end-of-file, the return value
97
is <>.
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 
113
#include 
114
#include 
115
#include 
116
#include 
117
#include 
118
#include 
119
#include 
120
#include 
121
#include 
122
#include 
123
#include 
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 
162
#include 
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 */
3065 serge 456
#ifdef _MB_CAPABLE
1693 serge 457
  mbstate_t state;              /* value to keep track of multibyte state */
3065 serge 458
#endif
1693 serge 459
 
460
  #define CCFN_PARAMS	_PARAMS((struct _reent *, const char *, char **, int))
461
  u_long (*ccfn)CCFN_PARAMS=0;	/* conversion function (strtol/strtoul) */
462
  char ccltab[256];		/* character class table for %[...] */
463
  char buf[BUF];		/* buffer for numeric conversions */
464
  unsigned char *lptr;          /* literal pointer */
465
 
466
  char *cp;
467
  short *sp;
468
  int *ip;
469
#ifdef FLOATING_POINT
470
  float *flp;
471
  _LONG_DOUBLE *ldp;
472
  double *dp;
473
#endif
474
  long *lp;
475
#ifndef _NO_LONGLONG
476
  long long *llp;
477
#endif
478
 
479
  /* `basefix' is used to avoid `if' tests in the integer scanner */
480
  static _CONST short basefix[17] =
481
    {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
482
 
483
  /* Macro to support positional arguments */
484
#ifndef _NO_POS_ARGS
485
# define GET_ARG(n, ap, type)					\
486
  ((type) (is_pos_arg						\
487
	   ? (n < numargs					\
488
	      ? args[n]						\
489
	      : get_arg (n, &ap, &numargs, args))		\
490
	   : (arg_index++ < numargs				\
491
	      ? args[n]						\
492
	      : (numargs < MAX_POS_ARGS				\
493
		 ? args[numargs++] = va_arg (ap, void *)	\
494
		 : va_arg (ap, void *)))))
495
#else
496
# define GET_ARG(n, ap, type) (va_arg (ap, type))
497
#endif
498
 
499
  _flockfile (fp);
500
 
501
  ORIENT (fp, -1);
502
 
503
  nassigned = 0;
504
  nread = 0;
505
#ifdef _MB_CAPABLE
506
  memset (&state, 0, sizeof (state));
507
#endif
508
 
509
  for (;;)
510
    {
511
#ifndef _MB_CAPABLE
512
      wc = *fmt;
513
#else
514
      nbytes = __mbtowc (rptr, &wc, fmt, MB_CUR_MAX, __locale_charset (),
515
			 &state);
516
      if (nbytes < 0) {
517
	wc = 0xFFFD; /* Unicode replacement character */
518
	nbytes = 1;
519
	memset (&state, 0, sizeof (state));
520
      }
521
#endif
522
      fmt += nbytes;
523
 
524
      if (wc == 0)
525
	goto all_done;
526
      if (nbytes == 1 && isspace (wc))
527
	{
528
	  for (;;)
529
	    {
530
	      if (BufferEmpty || !isspace (*fp->_p))
531
		break;
532
	      nread++, fp->_r--, fp->_p++;
533
	    }
534
	  continue;
535
	}
536
      if (wc != '%')
537
	goto literal;
538
      width = 0;
539
      flags = 0;
540
#ifndef _NO_POS_ARGS
541
      N = arg_index;
542
      is_pos_arg = 0;
543
#endif
544
 
545
      /*
546
       * switch on the format.  continue if done; break once format
547
       * type is derived.
548
       */
549
 
550
    again:
551
      c = *fmt++;
552
 
553
      switch (c)
554
	{
555
	case '%':
556
	literal:
557
          lptr = fmt - nbytes;
558
          for (n = 0; n < nbytes; ++n)
559
            {
560
	      if (BufferEmpty)
561
	        goto input_failure;
562
	      if (*fp->_p != *lptr)
563
	        goto match_failure;
564
	      fp->_r--, fp->_p++;
565
	      nread++;
566
              ++lptr;
567
            }
568
	  continue;
569
 
570
	case '*':
571
	  flags |= SUPPRESS;
572
	  goto again;
573
	case 'l':
574
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
575
	  if (*fmt == 'l')	/* Check for 'll' = long long (SUSv3) */
576
	    {
577
	      ++fmt;
578
	      flags |= LONGDBL;
579
	    }
580
	  else
581
#endif
582
	    flags |= LONG;
583
	  goto again;
584
	case 'L':
585
	  flags |= LONGDBL;
586
	  goto again;
587
	case 'h':
588
#ifdef _WANT_IO_C99_FORMATS
589
	  if (*fmt == 'h')	/* Check for 'hh' = char int (SUSv3) */
590
	    {
591
	      ++fmt;
592
	      flags |= CHAR;
593
	    }
594
	  else
595
#endif
596
	    flags |= SHORT;
597
	  goto again;
598
#ifdef _WANT_IO_C99_FORMATS
599
	case 'j': /* intmax_t */
600
	  if (sizeof (intmax_t) == sizeof (long))
601
	    flags |= LONG;
602
	  else
603
	    flags |= LONGDBL;
604
	  goto again;
605
	case 't': /* ptrdiff_t */
606
	  if (sizeof (ptrdiff_t) < sizeof (int))
607
	    /* POSIX states ptrdiff_t is 16 or more bits, as
608
	       is short.  */
609
	    flags |= SHORT;
610
	  else if (sizeof (ptrdiff_t) == sizeof (int))
611
	    /* no flag needed */;
612
	  else if (sizeof (ptrdiff_t) <= sizeof (long))
613
	    flags |= LONG;
614
	  else
615
	    /* POSIX states that at least one programming
616
	       environment must support ptrdiff_t no wider than
617
	       long, but that means other environments can
618
	       have ptrdiff_t as wide as long long.  */
619
	    flags |= LONGDBL;
620
	  goto again;
621
	case 'z': /* size_t */
622
	  if (sizeof (size_t) < sizeof (int))
623
	    /* POSIX states size_t is 16 or more bits, as is short.  */
624
	    flags |= SHORT;
625
	  else if (sizeof (size_t) == sizeof (int))
626
	    /* no flag needed */;
627
	  else if (sizeof (size_t) <= sizeof (long))
628
	    flags |= LONG;
629
	  else
630
	    /* POSIX states that at least one programming
631
	       environment must support size_t no wider than
632
	       long, but that means other environments can
633
	       have size_t as wide as long long.  */
634
	    flags |= LONGDBL;
635
	  goto again;
636
#endif /* _WANT_IO_C99_FORMATS */
637
 
638
	case '0':
639
	case '1':
640
	case '2':
641
	case '3':
642
	case '4':
643
	case '5':
644
	case '6':
645
	case '7':
646
	case '8':
647
	case '9':
648
	  width = width * 10 + c - '0';
649
	  goto again;
650
 
651
#ifndef _NO_POS_ARGS
652
	case '$':
653
	  if (width <= MAX_POS_ARGS)
654
	    {
655
	      N = width - 1;
656
	      is_pos_arg = 1;
657
	      width = 0;
658
	      goto again;
659
	    }
660
	  rptr->_errno = EINVAL;
661
	  goto input_failure;
662
#endif /* !_NO_POS_ARGS */
663
 
664
	  /*
665
	   * Conversions. Those marked `compat' are for
666
	   * 4.[123]BSD compatibility.
667
	   *
668
	   * (According to ANSI, E and X formats are supposed to
669
	   * the same as e and x.  Sorry about that.)
670
	   */
671
 
672
	case 'D':		/* compat */
673
	  flags |= LONG;
674
	  /* FALLTHROUGH */
675
	case 'd':
676
	  c = CT_INT;
677
	  ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
678
	  base = 10;
679
	  break;
680
 
681
	case 'i':
682
	  c = CT_INT;
683
	  ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
684
	  base = 0;
685
	  break;
686
 
687
	case 'O':		/* compat */
688
	  flags |= LONG;
689
	  /* FALLTHROUGH */
690
	case 'o':
691
	  c = CT_INT;
692
	  ccfn = _strtoul_r;
693
	  base = 8;
694
	  break;
695
 
696
	case 'u':
697
	  c = CT_INT;
698
	  ccfn = _strtoul_r;
699
	  base = 10;
700
	  break;
701
 
702
	case 'X':
703
	case 'x':
704
	  flags |= PFXOK;	/* enable 0x prefixing */
705
	  c = CT_INT;
706
	  ccfn = _strtoul_r;
707
	  base = 16;
708
	  break;
709
 
710
#ifdef FLOATING_POINT
711
# ifdef _WANT_IO_C99_FORMATS
712
	case 'a':
713
	case 'A':
714
	case 'F':
715
# endif
716
	case 'E':
717
	case 'G':
718
	case 'e':
719
	case 'f':
720
	case 'g':
721
	  c = CT_FLOAT;
722
	  break;
723
#endif
724
 
725
#ifdef _WANT_IO_C99_FORMATS
726
	case 'S':
727
	  flags |= LONG;
728
	  /* FALLTHROUGH */
729
#endif
730
 
731
	case 's':
732
	  c = CT_STRING;
733
	  break;
734
 
735
	case '[':
736
	  fmt = (u_char *) __sccl (ccltab, (unsigned char *) fmt);
737
	  flags |= NOSKIP;
738
	  c = CT_CCL;
739
	  break;
740
 
741
#ifdef _WANT_IO_C99_FORMATS
742
	case 'C':
743
	  flags |= LONG;
744
	  /* FALLTHROUGH */
745
#endif
746
 
747
	case 'c':
748
	  flags |= NOSKIP;
749
	  c = CT_CHAR;
750
	  break;
751
 
752
	case 'p':		/* pointer format is like hex */
753
	  flags |= POINTER | PFXOK;
754
	  c = CT_INT;
755
	  ccfn = _strtoul_r;
756
	  base = 16;
757
	  break;
758
 
759
	case 'n':
760
	  if (flags & SUPPRESS)	/* ??? */
761
	    continue;
762
#ifdef _WANT_IO_C99_FORMATS
763
	  if (flags & CHAR)
764
	    {
765
	      cp = GET_ARG (N, ap, char *);
766
	      *cp = nread;
767
	    }
768
	  else
769
#endif
770
	  if (flags & SHORT)
771
	    {
772
	      sp = GET_ARG (N, ap, short *);
773
	      *sp = nread;
774
	    }
775
	  else if (flags & LONG)
776
	    {
777
	      lp = GET_ARG (N, ap, long *);
778
	      *lp = nread;
779
	    }
780
#ifndef _NO_LONGLONG
781
	  else if (flags & LONGDBL)
782
	    {
783
	      llp = GET_ARG (N, ap, long long*);
784
	      *llp = nread;
785
	    }
786
#endif
787
	  else
788
	    {
789
	      ip = GET_ARG (N, ap, int *);
790
	      *ip = nread;
791
	    }
792
	  continue;
793
 
794
	  /*
795
	   * Disgusting backwards compatibility hacks.	XXX
796
	   */
797
	case '\0':		/* compat */
798
	  _funlockfile (fp);
799
	  return EOF;
800
 
801
	default:		/* compat */
802
	  if (isupper (c))
803
	    flags |= LONG;
804
	  c = CT_INT;
805
	  ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
806
	  base = 10;
807
	  break;
808
	}
809
 
810
      /*
811
       * We have a conversion that requires input.
812
       */
813
      if (BufferEmpty)
814
	goto input_failure;
815
 
816
      /*
817
       * Consume leading white space, except for formats that
818
       * suppress this.
819
       */
820
      if ((flags & NOSKIP) == 0)
821
	{
822
	  while (isspace (*fp->_p))
823
	    {
824
	      nread++;
825
	      if (--fp->_r > 0)
826
		fp->_p++;
827
	      else
828
	      if (__srefill_r (rptr, fp))
829
		goto input_failure;
830
	    }
831
	  /*
832
	   * Note that there is at least one character in the
833
	   * buffer, so conversions that do not set NOSKIP ca
834
	   * no longer result in an input failure.
835
	   */
836
	}
837
 
838
      /*
839
       * Do the conversion.
840
       */
841
      switch (c)
842
	{
843
 
844
	case CT_CHAR:
845
	  /* scan arbitrary characters (sets NOSKIP) */
846
	  if (width == 0)
847
	    width = 1;
848
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
849
          if (flags & LONG)
850
            {
851
              mbstate_t state;
852
              memset (&state, 0, sizeof (mbstate_t));
853
              if ((flags & SUPPRESS) == 0)
854
                wcp = GET_ARG (N, ap, wchar_t *);
855
              else
856
                wcp = NULL;
857
              n = 0;
858
              while (width != 0)
859
                {
860
                  if (n == MB_CUR_MAX)
861
                    goto input_failure;
862
                  buf[n++] = *fp->_p;
863
                  fp->_r -= 1;
864
                  fp->_p += 1;
865
                  if ((mbslen = _mbrtowc_r (rptr, wcp, buf, n, &state))
866
                                                         == (size_t)-1)
867
                    goto input_failure; /* Invalid sequence */
868
                  if (mbslen == 0 && !(flags & SUPPRESS))
869
                    *wcp = L'\0';
870
                  if (mbslen != (size_t)-2) /* Incomplete sequence */
871
                    {
872
                      nread += n;
873
                      width -= 1;
874
                      if (!(flags & SUPPRESS))
875
                        wcp += 1;
876
                      n = 0;
877
                    }
878
                  if (BufferEmpty)
879
	            {
880
                      if (n != 0)
881
                        goto input_failure;
882
                      break;
883
                    }
884
                }
885
              if (!(flags & SUPPRESS))
886
                nassigned++;
887
            }
888
          else
889
#endif
890
        	  if (flags & SUPPRESS)
891
	    {
892
	      size_t sum = 0;
893
	      for (;;)
894
		{
895
		  if ((n = fp->_r) < (int)width)
896
		    {
897
		      sum += n;
898
		      width -= n;
899
		      fp->_p += n;
900
		      if (__srefill_r (rptr, fp))
901
			{
902
			  if (sum == 0)
903
			    goto input_failure;
904
			  break;
905
			}
906
		    }
907
		  else
908
		    {
909
		      sum += width;
910
		      fp->_r -= width;
911
		      fp->_p += width;
912
		      break;
913
		    }
914
		}
915
	      nread += sum;
916
	    }
917
	  else
918
	    {
919
	      size_t r = _fread_r (rptr, (_PTR) GET_ARG (N, ap, char *), 1, width, fp);
920
 
921
	      if (r == 0)
922
		goto input_failure;
923
	      nread += r;
924
	      nassigned++;
925
	    }
926
	  break;
927
 
928
	case CT_CCL:
929
	  /* scan a (nonempty) character class (sets NOSKIP) */
930
	  if (width == 0)
931
	    width = ~0;		/* `infinity' */
932
	  /* take only those things in the class */
933
	  if (flags & SUPPRESS)
934
	    {
935
	      n = 0;
936
	      while (ccltab[*fp->_p])
937
		{
938
		  n++, fp->_r--, fp->_p++;
939
		  if (--width == 0)
940
		    break;
941
		  if (BufferEmpty)
942
		    {
943
		      if (n == 0)
944
			goto input_failure;
945
		      break;
946
		    }
947
		}
948
	      if (n == 0)
949
		goto match_failure;
950
	    }
951
	  else
952
	    {
953
	      p0 = p = GET_ARG (N, ap, char *);
954
	      while (ccltab[*fp->_p])
955
		{
956
		  fp->_r--;
957
		  *p++ = *fp->_p++;
958
		  if (--width == 0)
959
		    break;
960
		  if (BufferEmpty)
961
		    {
962
		      if (p == p0)
963
			goto input_failure;
964
		      break;
965
		    }
966
		}
967
	      n = p - p0;
968
	      if (n == 0)
969
		goto match_failure;
970
	      *p = 0;
971
	      nassigned++;
972
	    }
973
	  nread += n;
974
	  break;
975
 
976
	case CT_STRING:
977
	  /* like CCL, but zero-length string OK, & no NOSKIP */
978
	  if (width == 0)
979
            width = (size_t)~0;
980
#if !defined(_ELIX_LEVEL) || _ELIX_LEVEL >= 2
981
          if (flags & LONG)
982
            {
983
              /* Process %S and %ls placeholders */
984
              mbstate_t state;
985
              memset (&state, 0, sizeof (mbstate_t));
986
              if ((flags & SUPPRESS) == 0)
987
                wcp = GET_ARG (N, ap, wchar_t *);
988
              else
989
                wcp = &wc;
990
              n = 0;
991
              while (!isspace (*fp->_p) && width != 0)
992
                {
993
                  if (n == MB_CUR_MAX)
994
                    goto input_failure;
995
                  buf[n++] = *fp->_p;
996
                  fp->_r -= 1;
997
                  fp->_p += 1;
998
                  if ((mbslen = _mbrtowc_r (rptr, wcp, buf, n, &state))
999
                                                        == (size_t)-1)
1000
                    goto input_failure;
1001
                  if (mbslen == 0)
1002
                    *wcp = L'\0';
1003
                  if (mbslen != (size_t)-2) /* Incomplete sequence */
1004
                    {
1005
                      if (iswspace(*wcp))
1006
                        {
1007
                          while (n != 0)
1008
                            _ungetc_r (rptr, (unsigned char) buf[--n], fp);
1009
                          break;
1010
                        }
1011
                      nread += n;
1012
                      width -= 1;
1013
                      if ((flags & SUPPRESS) == 0)
1014
                        wcp += 1;
1015
                      n = 0;
1016
                    }
1017
                  if (BufferEmpty)
1018
                    {
1019
                      if (n != 0)
1020
                        goto input_failure;
1021
                      break;
1022
                    }
1023
                }
1024
              if (!(flags & SUPPRESS))
1025
                {
1026
                  *wcp = L'\0';
1027
                  nassigned++;
1028
                }
1029
            }
1030
          else
1031
#endif
1032
        	  if (flags & SUPPRESS)
1033
	    {
1034
	      n = 0;
1035
	      while (!isspace (*fp->_p))
1036
		{
1037
		  n++, fp->_r--, fp->_p++;
1038
		  if (--width == 0)
1039
		    break;
1040
		  if (BufferEmpty)
1041
		    break;
1042
		}
1043
	      nread += n;
1044
	    }
1045
	  else
1046
	    {
1047
	      p0 = p = GET_ARG (N, ap, char *);
1048
	      while (!isspace (*fp->_p))
1049
		{
1050
		  fp->_r--;
1051
		  *p++ = *fp->_p++;
1052
		  if (--width == 0)
1053
		    break;
1054
		  if (BufferEmpty)
1055
		    break;
1056
		}
1057
	      *p = 0;
1058
	      nread += p - p0;
1059
	      nassigned++;
1060
	    }
1061
	  continue;
1062
 
1063
	case CT_INT:
1064
	{
1065
	  /* scan an integer as if by strtol/strtoul */
1066
	  unsigned width_left = 0;
1067
	  int skips = 0;
1068
#ifdef hardway
1069
	  if (width == 0 || width > sizeof (buf) - 1)
1070
#else
1071
	  /* size_t is unsigned, hence this optimisation */
1072
	  if (width - 1 > sizeof (buf) - 2)
1073
#endif
1074
	    {
1075
	      width_left = width - (sizeof (buf) - 1);
1076
	      width = sizeof (buf) - 1;
1077
	    }
1078
	  flags |= SIGNOK | NDIGITS | NZDIGITS | NNZDIGITS;
1079
	  for (p = buf; width; width--)
1080
	    {
1081
	      c = *fp->_p;
1082
	      /*
1083
	       * Switch on the character; `goto ok' if we
1084
	       * accept it as a part of number.
1085
	       */
1086
	      switch (c)
1087
		{
1088
		  /*
1089
		   * The digit 0 is always legal, but is special.
1090
		   * For %i conversions, if no digits (zero or nonzero)
1091
		   * have been scanned (only signs), we will have base==0.
1092
		   * In that case, we should set it to 8 and enable 0x
1093
		   * prefixing. Also, if we have not scanned zero digits
1094
		   * before this, do not turn off prefixing (someone else
1095
		   * will turn it off if we have scanned any nonzero digits).
1096
		   */
1097
		case '0':
1098
		  if (! (flags & NNZDIGITS))
1099
		    goto ok;
1100
		  if (base == 0)
1101
		    {
1102
		      base = 8;
1103
		      flags |= PFXOK;
1104
		    }
1105
		  if (flags & NZDIGITS)
1106
		    {
1107
		      flags &= ~(SIGNOK | NZDIGITS | NDIGITS);
1108
		      goto ok;
1109
		    }
1110
		  flags &= ~(SIGNOK | PFXOK | NDIGITS);
1111
		  if (width_left)
1112
		    {
1113
		      width_left--;
1114
		      width++;
1115
		    }
1116
		  ++skips;
1117
		  goto skip;
1118
 
1119
		  /* 1 through 7 always legal */
1120
		case '1':
1121
		case '2':
1122
		case '3':
1123
		case '4':
1124
		case '5':
1125
		case '6':
1126
		case '7':
1127
		  base = basefix[base];
1128
		  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1129
		  goto ok;
1130
 
1131
		  /* digits 8 and 9 ok iff decimal or hex */
1132
		case '8':
1133
		case '9':
1134
		  base = basefix[base];
1135
		  if (base <= 8)
1136
		    break;	/* not legal here */
1137
		  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1138
		  goto ok;
1139
 
1140
		  /* letters ok iff hex */
1141
		case 'A':
1142
		case 'B':
1143
		case 'C':
1144
		case 'D':
1145
		case 'E':
1146
		case 'F':
1147
		case 'a':
1148
		case 'b':
1149
		case 'c':
1150
		case 'd':
1151
		case 'e':
1152
		case 'f':
1153
		  /* no need to fix base here */
1154
		  if (base <= 10)
1155
		    break;	/* not legal here */
1156
		  flags &= ~(SIGNOK | PFXOK | NDIGITS | NNZDIGITS);
1157
		  goto ok;
1158
 
1159
		  /* sign ok only as first character */
1160
		case '+':
1161
		case '-':
1162
		  if (flags & SIGNOK)
1163
		    {
1164
		      flags &= ~SIGNOK;
1165
		      goto ok;
1166
		    }
1167
		  break;
1168
 
1169
		  /* x ok iff flag still set & single 0 seen */
1170
		case 'x':
1171
		case 'X':
1172
		  if ((flags & (PFXOK | NZDIGITS)) == PFXOK)
1173
		    {
1174
		      base = 16;/* if %i */
1175
		      flags &= ~PFXOK;
1176
		      /* We must reset the NZDIGITS and NDIGITS
1177
			 flags that would have been unset by seeing
1178
			 the zero that preceded the X or x.  */
1179
		      flags |= NZDIGITS | NDIGITS;
1180
		      goto ok;
1181
		    }
1182
		  break;
1183
		}
1184
 
1185
	      /*
1186
	       * If we got here, c is not a legal character
1187
	       * for a number.  Stop accumulating digits.
1188
	       */
1189
	      break;
1190
	    ok:
1191
	      /*
1192
	       * c is legal: store it and look at the next.
1193
	       */
1194
	      *p++ = c;
1195
	    skip:
1196
	      if (--fp->_r > 0)
1197
		fp->_p++;
1198
	      else
1199
	      if (__srefill_r (rptr, fp))
1200
		break;		/* EOF */
1201
	    }
1202
	  /*
1203
	   * If we had only a sign, it is no good; push back the sign.
1204
	   * If the number ends in `x', it was [sign] '0' 'x', so push back
1205
	   * the x and treat it as [sign] '0'.
1206
	   * Use of ungetc here and below assumes ASCII encoding; we are only
1207
	   * pushing back 7-bit characters, so casting to unsigned char is
1208
	   * not necessary.
1209
	   */
1210
	  if (flags & NDIGITS)
1211
	    {
1212
	      if (p > buf)
1213
		_ungetc_r (rptr, *--p, fp); /* [-+xX] */
1214
	      if (p == buf)
1215
		goto match_failure;
1216
	    }
1217
	  if ((flags & SUPPRESS) == 0)
1218
	    {
1219
	      u_long res;
1220
 
1221
	      *p = 0;
1222
	      res = (*ccfn) (rptr, buf, (char **) NULL, base);
1223
	      if (flags & POINTER)
1224
		{
1225
		  void **vp = GET_ARG (N, ap, void **);
1226
#ifndef _NO_LONGLONG
1227
		  if (sizeof (uintptr_t) > sizeof (u_long))
1228
		    {
1229
		      u_long_long resll;
1230
		      resll = _strtoull_r (rptr, buf, (char **) NULL, base);
1231
		      *vp = (void *) (uintptr_t) resll;
1232
		    }
1233
		  else
1234
#endif /* !_NO_LONGLONG */
1235
		    *vp = (void *) (uintptr_t) res;
1236
		}
1237
#ifdef _WANT_IO_C99_FORMATS
1238
	      else if (flags & CHAR)
1239
		{
1240
		  cp = GET_ARG (N, ap, char *);
1241
		  *cp = res;
1242
		}
1243
#endif
1244
	      else if (flags & SHORT)
1245
		{
1246
		  sp = GET_ARG (N, ap, short *);
1247
		  *sp = res;
1248
		}
1249
	      else if (flags & LONG)
1250
		{
1251
		  lp = GET_ARG (N, ap, long *);
1252
		  *lp = res;
1253
		}
1254
#ifndef _NO_LONGLONG
1255
	      else if (flags & LONGDBL)
1256
		{
1257
		  u_long_long resll;
1258
		  if (ccfn == _strtoul_r)
1259
		    resll = _strtoull_r (rptr, buf, (char **) NULL, base);
1260
		  else
1261
		    resll = _strtoll_r (rptr, buf, (char **) NULL, base);
1262
		  llp = GET_ARG (N, ap, long long*);
1263
		  *llp = resll;
1264
		}
1265
#endif
1266
	      else
1267
		{
1268
		  ip = GET_ARG (N, ap, int *);
1269
		  *ip = res;
1270
		}
1271
	      nassigned++;
1272
	    }
1273
	  nread += p - buf + skips;
1274
	  break;
1275
	}
1276
#ifdef FLOATING_POINT
1277
	case CT_FLOAT:
1278
	{
1279
	  /* scan a floating point number as if by strtod */
1280
	  /* This code used to assume that the number of digits is reasonable.
1281
	     However, ANSI / ISO C makes no such stipulation; we have to get
1282
	     exact results even when there is an unreasonable amount of
1283
	     leading zeroes.  */
1284
	  long leading_zeroes = 0;
1285
	  long zeroes, exp_adjust;
1286
	  char *exp_start = NULL;
1287
	  unsigned width_left = 0;
1288
	  char nancount = 0;
1289
	  char infcount = 0;
1290
#ifdef hardway
1291
	  if (width == 0 || width > sizeof (buf) - 1)
1292
#else
1293
	  /* size_t is unsigned, hence this optimisation */
1294
	  if (width - 1 > sizeof (buf) - 2)
1295
#endif
1296
	    {
1297
	      width_left = width - (sizeof (buf) - 1);
1298
	      width = sizeof (buf) - 1;
1299
	    }
1300
	  flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
1301
	  zeroes = 0;
1302
	  exp_adjust = 0;
1303
	  for (p = buf; width; )
1304
	    {
1305
	      c = *fp->_p;
1306
	      /*
1307
	       * This code mimicks the integer conversion
1308
	       * code, but is much simpler.
1309
	       */
1310
	      switch (c)
1311
		{
1312
		case '0':
1313
		  if (flags & NDIGITS)
1314
		    {
1315
		      flags &= ~SIGNOK;
1316
		      zeroes++;
1317
		      if (width_left)
1318
			{
1319
			  width_left--;
1320
			  width++;
1321
			}
1322
		      goto fskip;
1323
		    }
1324
		  /* Fall through.  */
1325
		case '1':
1326
		case '2':
1327
		case '3':
1328
		case '4':
1329
		case '5':
1330
		case '6':
1331
		case '7':
1332
		case '8':
1333
		case '9':
1334
		  if (nancount + infcount == 0)
1335
		    {
1336
		      flags &= ~(SIGNOK | NDIGITS);
1337
		      goto fok;
1338
		    }
1339
		  break;
1340
 
1341
		case '+':
1342
		case '-':
1343
		  if (flags & SIGNOK)
1344
		    {
1345
		      flags &= ~SIGNOK;
1346
		      goto fok;
1347
		    }
1348
		  break;
1349
		case 'n':
1350
		case 'N':
1351
		  if (nancount == 0 && zeroes == 0
1352
		      && (flags & (NDIGITS | DPTOK | EXPOK)) ==
1353
				  (NDIGITS | DPTOK | EXPOK))
1354
		    {
1355
		      flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
1356
		      nancount = 1;
1357
		      goto fok;
1358
		    }
1359
		  if (nancount == 2)
1360
		    {
1361
		      nancount = 3;
1362
		      goto fok;
1363
		    }
1364
		  if (infcount == 1 || infcount == 4)
1365
		    {
1366
		      infcount++;
1367
		      goto fok;
1368
		    }
1369
		  break;
1370
		case 'a':
1371
		case 'A':
1372
		  if (nancount == 1)
1373
		    {
1374
		      nancount = 2;
1375
		      goto fok;
1376
		    }
1377
		  break;
1378
		case 'i':
1379
		case 'I':
1380
		  if (infcount == 0 && zeroes == 0
1381
		      && (flags & (NDIGITS | DPTOK | EXPOK)) ==
1382
				  (NDIGITS | DPTOK | EXPOK))
1383
		    {
1384
		      flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
1385
		      infcount = 1;
1386
		      goto fok;
1387
		    }
1388
		  if (infcount == 3 || infcount == 5)
1389
		    {
1390
		      infcount++;
1391
		      goto fok;
1392
		    }
1393
		  break;
1394
		case 'f':
1395
		case 'F':
1396
		  if (infcount == 2)
1397
		    {
1398
		      infcount = 3;
1399
		      goto fok;
1400
		    }
1401
		  break;
1402
		case 't':
1403
		case 'T':
1404
		  if (infcount == 6)
1405
		    {
1406
		      infcount = 7;
1407
		      goto fok;
1408
		    }
1409
		  break;
1410
		case 'y':
1411
		case 'Y':
1412
		  if (infcount == 7)
1413
		    {
1414
		      infcount = 8;
1415
		      goto fok;
1416
		    }
1417
		  break;
1418
		case '.':
1419
		  if (flags & DPTOK)
1420
		    {
1421
		      flags &= ~(SIGNOK | DPTOK);
1422
		      leading_zeroes = zeroes;
1423
		      goto fok;
1424
		    }
1425
		  break;
1426
		case 'e':
1427
		case 'E':
1428
		  /* no exponent without some digits */
1429
		  if ((flags & (NDIGITS | EXPOK)) == EXPOK
1430
		      || ((flags & EXPOK) && zeroes))
1431
		    {
1432
		      if (! (flags & DPTOK))
1433
			{
1434
			  exp_adjust = zeroes - leading_zeroes;
1435
			  exp_start = p;
1436
			}
1437
		      flags =
1438
			(flags & ~(EXPOK | DPTOK)) |
1439
			SIGNOK | NDIGITS;
1440
		      zeroes = 0;
1441
		      goto fok;
1442
		    }
1443
		  break;
1444
		}
1445
	      break;
1446
	    fok:
1447
	      *p++ = c;
1448
	    fskip:
1449
	      width--;
1450
	      ++nread;
1451
	      if (--fp->_r > 0)
1452
		fp->_p++;
1453
	      else
1454
	      if (__srefill_r (rptr, fp))
1455
		break;		/* EOF */
1456
	    }
1457
	  if (zeroes)
1458
	    flags &= ~NDIGITS;
1459
	  /* We may have a 'N' or possibly even [sign] 'N' 'a' as the
1460
	     start of 'NaN', only to run out of chars before it was
1461
	     complete (or having encountered a non-matching char).  So
1462
	     check here if we have an outstanding nancount, and if so
1463
	     put back the chars we did swallow and treat as a failed
1464
	     match.
1465
 
1466
	     FIXME - we still don't handle NAN([0xdigits]).  */
1467
	  if (nancount - 1U < 2U) /* nancount && nancount < 3 */
1468
	    {
1469
	      /* Newlib's ungetc works even if we called __srefill in
1470
		 the middle of a partial parse, but POSIX does not
1471
		 guarantee that in all implementations of ungetc.  */
1472
	      while (p > buf)
1473
		{
1474
		  _ungetc_r (rptr, *--p, fp); /* [-+nNaA] */
1475
		  --nread;
1476
		}
1477
	      goto match_failure;
1478
	    }
1479
	  /* Likewise for 'inf' and 'infinity'.	 But be careful that
1480
	     'infinite' consumes only 3 characters, leaving the stream
1481
	     at the second 'i'.	 */
1482
	  if (infcount - 1U < 7U) /* infcount && infcount < 8 */
1483
	    {
1484
	      if (infcount >= 3) /* valid 'inf', but short of 'infinity' */
1485
		while (infcount-- > 3)
1486
		  {
1487
		    _ungetc_r (rptr, *--p, fp); /* [iInNtT] */
1488
		    --nread;
1489
		  }
1490
	      else
1491
		{
1492
		  while (p > buf)
1493
		    {
1494
		      _ungetc_r (rptr, *--p, fp); /* [-+iInN] */
1495
		      --nread;
1496
		    }
1497
		  goto match_failure;
1498
		}
1499
	    }
1500
	  /*
1501
	   * If no digits, might be missing exponent digits
1502
	   * (just give back the exponent) or might be missing
1503
	   * regular digits, but had sign and/or decimal point.
1504
	   */
1505
	  if (flags & NDIGITS)
1506
	    {
1507
	      if (flags & EXPOK)
1508
		{
1509
		  /* no digits at all */
1510
		  while (p > buf)
1511
		    {
1512
		      _ungetc_r (rptr, *--p, fp); /* [-+.] */
1513
		      --nread;
1514
		    }
1515
		  goto match_failure;
1516
		}
1517
	      /* just a bad exponent (e and maybe sign) */
1518
	      c = *--p;
1519
	      --nread;
1520
	      if (c != 'e' && c != 'E')
1521
		{
1522
		  _ungetc_r (rptr, c, fp); /* [-+] */
1523
		  c = *--p;
1524
		  --nread;
1525
		}
1526
	      _ungetc_r (rptr, c, fp); /* [eE] */
1527
	    }
1528
	  if ((flags & SUPPRESS) == 0)
1529
	    {
1530
	      double res = 0;
1531
#ifdef _NO_LONGDBL
1532
#define QUAD_RES res;
1533
#else  /* !_NO_LONG_DBL */
1534
	      long double qres = 0;
1535
#define QUAD_RES qres;
1536
#endif /* !_NO_LONG_DBL */
1537
	      long new_exp = 0;
1538
 
1539
	      *p = 0;
1540
	      if ((flags & (DPTOK | EXPOK)) == EXPOK)
1541
		{
1542
		  exp_adjust = zeroes - leading_zeroes;
1543
		  new_exp = -exp_adjust;
1544
		  exp_start = p;
1545
		}
1546
	      else if (exp_adjust)
1547
                new_exp = _strtol_r (rptr, (exp_start + 1), NULL, 10) - exp_adjust;
1548
	      if (exp_adjust)
1549
		{
1550
 
1551
		  /* If there might not be enough space for the new exponent,
1552
		     truncate some trailing digits to make room.  */
1553
		  if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN)
1554
		    exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
1555
                 sprintf (exp_start, "e%ld", new_exp);
1556
		}
1557
 
1558
	      /* Current _strtold routine is markedly slower than
1559
	         _strtod_r.  Only use it if we have a long double
1560
	         result.  */
1561
#ifndef _NO_LONGDBL /* !_NO_LONGDBL */
1562
	      if (flags & LONGDBL)
1563
		qres = _strtold (buf, NULL);
1564
	      else
1565
#endif
1566
	        res = _strtod_r (rptr, buf, NULL);
1567
 
1568
	      if (flags & LONG)
1569
		{
1570
		  dp = GET_ARG (N, ap, double *);
1571
		  *dp = res;
1572
		}
1573
	      else if (flags & LONGDBL)
1574
		{
1575
		  ldp = GET_ARG (N, ap, _LONG_DOUBLE *);
1576
		  *ldp = QUAD_RES;
1577
		}
1578
	      else
1579
		{
1580
		  flp = GET_ARG (N, ap, float *);
1581
		  if (isnan (res))
1582
		    *flp = nanf (NULL);
1583
		  else
1584
		    *flp = res;
1585
		}
1586
	      nassigned++;
1587
	    }
1588
	  break;
1589
	}
1590
#endif /* FLOATING_POINT */
1591
	}
1592
    }
1593
input_failure:
1594
  /* On read failure, return EOF failure regardless of matches; errno
1595
     should have been set prior to here.  On EOF failure (including
1596
     invalid format string), return EOF if no matches yet, else number
1597
     of matches made prior to failure.  */
1598
  _funlockfile (fp);
1599
  return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
1600
match_failure:
1601
all_done:
1602
  /* Return number of matches, which can be 0 on match failure.  */
1603
  _funlockfile (fp);
1604
  return nassigned;
1605
}
1606
 
1607
#ifndef _NO_POS_ARGS
1608
/* Process all intermediate arguments.  Fortunately, with scanf, all
1609
   intermediate arguments are sizeof(void*), so we don't need to scan
1610
   ahead in the format string.  */
1611
static void *
1612
get_arg (int n, va_list *ap, int *numargs_p, void **args)
1613
{
1614
  int numargs = *numargs_p;
1615
  while (n >= numargs)
1616
    args[numargs++] = va_arg (*ap, void *);
1617
  *numargs_p = numargs;
1618
  return args[n];
1619
}
1620
#endif /* !_NO_POS_ARGS */