Subversion Repositories Kolibri OS

Rev

Rev 4921 | Details | Compare with Previous | Last modification | View Log | RSS feed

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