Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | 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 */
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
  unsigned 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
#ifdef _MB_CAPABLE
505
  memset (&state, 0, sizeof (state));
506
#endif
507
 
508
  for (;;)
509
    {
510
#ifndef _MB_CAPABLE
511
      wc = *fmt;
512
#else
513
      nbytes = __mbtowc (rptr, &wc, fmt, MB_CUR_MAX, __locale_charset (),
514
			 &state);
515
      if (nbytes < 0) {
516
	wc = 0xFFFD; /* Unicode replacement character */
517
	nbytes = 1;
518
	memset (&state, 0, sizeof (state));
519
      }
520
#endif
521
      fmt += nbytes;
522
 
523
      if (wc == 0)
524
	goto all_done;
525
      if (nbytes == 1 && isspace (wc))
526
	{
527
	  for (;;)
528
	    {
529
	      if (BufferEmpty || !isspace (*fp->_p))
530
		break;
531
	      nread++, fp->_r--, fp->_p++;
532
	    }
533
	  continue;
534
	}
535
      if (wc != '%')
536
	goto literal;
537
      width = 0;
538
      flags = 0;
539
#ifndef _NO_POS_ARGS
540
      N = arg_index;
541
      is_pos_arg = 0;
542
#endif
543
 
544
      /*
545
       * switch on the format.  continue if done; break once format
546
       * type is derived.
547
       */
548
 
549
    again:
550
      c = *fmt++;
551
 
552
      switch (c)
553
	{
554
	case '%':
555
	literal:
556
          lptr = fmt - nbytes;
557
          for (n = 0; n < nbytes; ++n)
558
            {
559
	      if (BufferEmpty)
560
	        goto input_failure;
561
	      if (*fp->_p != *lptr)
562
	        goto match_failure;
563
	      fp->_r--, fp->_p++;
564
	      nread++;
565
              ++lptr;
566
            }
567
	  continue;
568
 
569
	case '*':
570
	  flags |= SUPPRESS;
571
	  goto again;
572
	case 'l':
573
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
574
	  if (*fmt == 'l')	/* Check for 'll' = long long (SUSv3) */
575
	    {
576
	      ++fmt;
577
	      flags |= LONGDBL;
578
	    }
579
	  else
580
#endif
581
	    flags |= LONG;
582
	  goto again;
583
	case 'L':
584
	  flags |= LONGDBL;
585
	  goto again;
586
	case 'h':
587
#ifdef _WANT_IO_C99_FORMATS
588
	  if (*fmt == 'h')	/* Check for 'hh' = char int (SUSv3) */
589
	    {
590
	      ++fmt;
591
	      flags |= CHAR;
592
	    }
593
	  else
594
#endif
595
	    flags |= SHORT;
596
	  goto again;
597
#ifdef _WANT_IO_C99_FORMATS
598
	case 'j': /* intmax_t */
599
	  if (sizeof (intmax_t) == sizeof (long))
600
	    flags |= LONG;
601
	  else
602
	    flags |= LONGDBL;
603
	  goto again;
604
	case 't': /* ptrdiff_t */
605
	  if (sizeof (ptrdiff_t) < sizeof (int))
606
	    /* POSIX states ptrdiff_t is 16 or more bits, as
607
	       is short.  */
608
	    flags |= SHORT;
609
	  else if (sizeof (ptrdiff_t) == sizeof (int))
610
	    /* no flag needed */;
611
	  else if (sizeof (ptrdiff_t) <= sizeof (long))
612
	    flags |= LONG;
613
	  else
614
	    /* POSIX states that at least one programming
615
	       environment must support ptrdiff_t no wider than
616
	       long, but that means other environments can
617
	       have ptrdiff_t as wide as long long.  */
618
	    flags |= LONGDBL;
619
	  goto again;
620
	case 'z': /* size_t */
621
	  if (sizeof (size_t) < sizeof (int))
622
	    /* POSIX states size_t is 16 or more bits, as is short.  */
623
	    flags |= SHORT;
624
	  else if (sizeof (size_t) == sizeof (int))
625
	    /* no flag needed */;
626
	  else if (sizeof (size_t) <= sizeof (long))
627
	    flags |= LONG;
628
	  else
629
	    /* POSIX states that at least one programming
630
	       environment must support size_t no wider than
631
	       long, but that means other environments can
632
	       have size_t as wide as long long.  */
633
	    flags |= LONGDBL;
634
	  goto again;
635
#endif /* _WANT_IO_C99_FORMATS */
636
 
637
	case '0':
638
	case '1':
639
	case '2':
640
	case '3':
641
	case '4':
642
	case '5':
643
	case '6':
644
	case '7':
645
	case '8':
646
	case '9':
647
	  width = width * 10 + c - '0';
648
	  goto again;
649
 
650
#ifndef _NO_POS_ARGS
651
	case '$':
652
	  if (width <= MAX_POS_ARGS)
653
	    {
654
	      N = width - 1;
655
	      is_pos_arg = 1;
656
	      width = 0;
657
	      goto again;
658
	    }
659
	  rptr->_errno = EINVAL;
660
	  goto input_failure;
661
#endif /* !_NO_POS_ARGS */
662
 
663
	  /*
664
	   * Conversions. Those marked `compat' are for
665
	   * 4.[123]BSD compatibility.
666
	   *
667
	   * (According to ANSI, E and X formats are supposed to
668
	   * the same as e and x.  Sorry about that.)
669
	   */
670
 
671
	case 'D':		/* compat */
672
	  flags |= LONG;
673
	  /* FALLTHROUGH */
674
	case 'd':
675
	  c = CT_INT;
676
	  ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
677
	  base = 10;
678
	  break;
679
 
680
	case 'i':
681
	  c = CT_INT;
682
	  ccfn = (u_long (*)CCFN_PARAMS)_strtol_r;
683
	  base = 0;
684
	  break;
685
 
686
	case 'O':		/* compat */
687
	  flags |= LONG;
688
	  /* FALLTHROUGH */
689
	case 'o':
690
	  c = CT_INT;
691
	  ccfn = _strtoul_r;
692
	  base = 8;
693
	  break;
694
 
695
	case 'u':
696
	  c = CT_INT;
697
	  ccfn = _strtoul_r;
698
	  base = 10;
699
	  break;
700
 
701
	case 'X':
702
	case 'x':
703
	  flags |= PFXOK;	/* enable 0x prefixing */
704
	  c = CT_INT;
705
	  ccfn = _strtoul_r;
706
	  base = 16;
707
	  break;
708
 
709
#ifdef FLOATING_POINT
710
# ifdef _WANT_IO_C99_FORMATS
711
	case 'a':
712
	case 'A':
713
	case 'F':
714
# endif
715
	case 'E':
716
	case 'G':
717
	case 'e':
718
	case 'f':
719
	case 'g':
720
	  c = CT_FLOAT;
721
	  break;
722
#endif
723
 
724
#ifdef _WANT_IO_C99_FORMATS
725
	case 'S':
726
	  flags |= LONG;
727
	  /* FALLTHROUGH */
728
#endif
729
 
730
	case 's':
731
	  c = CT_STRING;
732
	  break;
733
 
734
	case '[':
735
	  fmt = (u_char *) __sccl (ccltab, (unsigned char *) fmt);
736
	  flags |= NOSKIP;
737
	  c = CT_CCL;
738
	  break;
739
 
740
#ifdef _WANT_IO_C99_FORMATS
741
	case 'C':
742
	  flags |= LONG;
743
	  /* FALLTHROUGH */
744
#endif
745
 
746
	case 'c':
747
	  flags |= NOSKIP;
748
	  c = CT_CHAR;
749
	  break;
750
 
751
	case 'p':		/* pointer format is like hex */
752
	  flags |= POINTER | PFXOK;
753
	  c = CT_INT;
754
	  ccfn = _strtoul_r;
755
	  base = 16;
756
	  break;
757
 
758
	case 'n':
759
	  if (flags & SUPPRESS)	/* ??? */
760
	    continue;
761
#ifdef _WANT_IO_C99_FORMATS
762
	  if (flags & CHAR)
763
	    {
764
	      cp = GET_ARG (N, ap, char *);
765
	      *cp = nread;
766
	    }
767
	  else
768
#endif
769
	  if (flags & SHORT)
770
	    {
771
	      sp = GET_ARG (N, ap, short *);
772
	      *sp = nread;
773
	    }
774
	  else if (flags & LONG)
775
	    {
776
	      lp = GET_ARG (N, ap, long *);
777
	      *lp = nread;
778
	    }
779
#ifndef _NO_LONGLONG
780
	  else if (flags & LONGDBL)
781
	    {
782
	      llp = GET_ARG (N, ap, long long*);
783
	      *llp = nread;
784
	    }
785
#endif
786
	  else
787
	    {
788
	      ip = GET_ARG (N, ap, int *);
789
	      *ip = nread;
790
	    }
791
	  continue;
792
 
793
	  /*
794
	   * Disgusting backwards compatibility hacks.	XXX
795
	   */
796
	case '\0':		/* compat */
797
	  _funlockfile (fp);
798
	  __sfp_lock_release ();
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
  __sfp_lock_release ();
1600
  return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF;
1601
match_failure:
1602
all_done:
1603
  /* Return number of matches, which can be 0 on match failure.  */
1604
  _funlockfile (fp);
1605
  __sfp_lock_release ();
1606
  return nassigned;
1607
}
1608
 
1609
#ifndef _NO_POS_ARGS
1610
/* Process all intermediate arguments.  Fortunately, with scanf, all
1611
   intermediate arguments are sizeof(void*), so we don't need to scan
1612
   ahead in the format string.  */
1613
static void *
1614
get_arg (int n, va_list *ap, int *numargs_p, void **args)
1615
{
1616
  int numargs = *numargs_p;
1617
  while (n >= numargs)
1618
    args[numargs++] = va_arg (*ap, void *);
1619
  *numargs_p = numargs;
1620
  return args[n];
1621
}
1622
#endif /* !_NO_POS_ARGS */