Subversion Repositories Kolibri OS

Rev

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