Subversion Repositories Kolibri OS

Rev

Rev 4921 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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