Subversion Repositories Kolibri OS

Rev

Rev 4921 | Go to most recent revision | Only display areas with differences | Ignore 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
 * This code is derived from software contributed to Berkeley by
5
 * This code is derived from software contributed to Berkeley by
6
 * Chris Torek.
6
 * Chris Torek.
7
 *
7
 *
8
 * Redistribution and use in source and binary forms, with or without
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
9
 * modification, are permitted provided that the following conditions
10
 * are met:
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. All advertising materials mentioning features or use of this software
16
 * 3. All advertising materials mentioning features or use of this software
17
 *    must display the following acknowledgement:
17
 *    must display the following acknowledgement:
18
 *	This product includes software developed by the University of
18
 *	This product includes software developed by the University of
19
 *	California, Berkeley and its contributors.
19
 *	California, Berkeley and its contributors.
20
 * 4. Neither the name of the University nor the names of its contributors
20
 * 4. Neither the name of the University nor the names of its contributors
21
 *    may be used to endorse or promote products derived from this software
21
 *    may be used to endorse or promote products derived from this software
22
 *    without specific prior written permission.
22
 *    without specific prior written permission.
23
 *
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
 * SUCH DAMAGE.
34
 * SUCH DAMAGE.
35
 */
35
 */
36
 
36
 
37
/*
37
/*
38
FUNCTION
38
FUNCTION
39
<>, <>, <>, <>, <>, <>---format argument list
39
<>, <>, <>, <>, <>, <>---format argument list
40
 
40
 
41
INDEX
41
INDEX
42
	vfprintf
42
	vfprintf
43
INDEX
43
INDEX
44
	_vfprintf_r
44
	_vfprintf_r
45
INDEX
45
INDEX
46
	vprintf
46
	vprintf
47
INDEX
47
INDEX
48
	_vprintf_r
48
	_vprintf_r
49
INDEX
49
INDEX
50
	vsprintf
50
	vsprintf
51
INDEX
51
INDEX
52
	_vsprintf_r
52
	_vsprintf_r
53
INDEX
53
INDEX
54
	vsnprintf
54
	vsnprintf
55
INDEX
55
INDEX
56
	_vsnprintf_r
56
	_vsnprintf_r
57
INDEX
57
INDEX
58
	vasprintf
58
	vasprintf
59
INDEX
59
INDEX
60
	_vasprintf_r
60
	_vasprintf_r
61
INDEX
61
INDEX
62
	vasnprintf
62
	vasnprintf
63
INDEX
63
INDEX
64
	_vasnprintf_r
64
	_vasnprintf_r
65
 
65
 
66
ANSI_SYNOPSIS
66
ANSI_SYNOPSIS
67
	#include 
67
	#include 
68
	#include 
68
	#include 
69
	int vprintf(const char *<[fmt]>, va_list <[list]>);
69
	int vprintf(const char *<[fmt]>, va_list <[list]>);
70
	int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
70
	int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
71
	int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
71
	int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
72
	int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
72
	int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
73
                      va_list <[list]>);
73
                      va_list <[list]>);
74
	int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
74
	int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
75
	char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
75
	char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
76
                         va_list <[list]>);
76
                         va_list <[list]>);
77
 
77
 
78
	int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
78
	int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
79
                        va_list <[list]>);
79
                        va_list <[list]>);
80
	int _vfprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
80
	int _vfprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
81
                        const char *<[fmt]>, va_list <[list]>);
81
                        const char *<[fmt]>, va_list <[list]>);
82
	int _vsprintf_r(struct _reent *<[reent]>, char *<[str]>,
82
	int _vsprintf_r(struct _reent *<[reent]>, char *<[str]>,
83
                        const char *<[fmt]>, va_list <[list]>);
83
                        const char *<[fmt]>, va_list <[list]>);
84
	int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
84
	int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
85
                         const char *<[fmt]>, va_list <[list]>);
85
                         const char *<[fmt]>, va_list <[list]>);
86
	int _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>,
86
	int _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>,
87
                         size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
87
                         size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
88
	char *_vasnprintf_r(struct _reent *<[reent]>, char *<[str]>,
88
	char *_vasnprintf_r(struct _reent *<[reent]>, char *<[str]>,
89
                            size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
89
                            size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
90
 
90
 
91
DESCRIPTION
91
DESCRIPTION
92
<>, <>, <>, <>, <>,
92
<>, <>, <>, <>, <>,
93
and <> are (respectively) variants of <>,
93
and <> are (respectively) variants of <>,
94
<>, <>, <>, <>, and
94
<>, <>, <>, <>, and
95
<>.  They differ only in allowing their caller to pass the
95
<>.  They differ only in allowing their caller to pass the
96
variable argument list as a <> object (initialized by
96
variable argument list as a <> object (initialized by
97
<>) rather than directly accepting a variable number of
97
<>) rather than directly accepting a variable number of
98
arguments.  The caller is responsible for calling <>.
98
arguments.  The caller is responsible for calling <>.
99
 
99
 
100
<<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
100
<<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
101
<<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
101
<<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
102
above.
102
above.
103
 
103
 
104
RETURNS
104
RETURNS
105
The return values are consistent with the corresponding functions.
105
The return values are consistent with the corresponding functions.
106
 
106
 
107
PORTABILITY
107
PORTABILITY
108
ANSI C requires <>, <>, <>, and
108
ANSI C requires <>, <>, <>, and
109
<>.  The remaining functions are newlib extensions.
109
<>.  The remaining functions are newlib extensions.
110
 
110
 
111
Supporting OS subroutines required: <>, <>, <>,
111
Supporting OS subroutines required: <>, <>, <>,
112
<>, <>, <>, <>.
112
<>, <>, <>, <>.
113
*/
113
*/
114
 
114
 
115
#if defined(LIBC_SCCS) && !defined(lint)
115
#if defined(LIBC_SCCS) && !defined(lint)
116
/*static char *sccsid = "from: @(#)vfprintf.c	5.50 (Berkeley) 12/16/92";*/
116
/*static char *sccsid = "from: @(#)vfprintf.c	5.50 (Berkeley) 12/16/92";*/
117
static char *rcsid = "$Id: vfprintf.c,v 1.43 2002/08/13 02:40:06 fitzsim Exp $";
117
static char *rcsid = "$Id$";
118
#endif /* LIBC_SCCS and not lint */
118
#endif /* LIBC_SCCS and not lint */
119
 
119
 
120
/*
120
/*
121
 * Actual printf innards.
121
 * Actual printf innards.
122
 *
122
 *
123
 * This code is large and complicated...
123
 * This code is large and complicated...
124
 */
124
 */
125
#include 
125
#include 
126
 
126
 
127
#ifdef INTEGER_ONLY
127
#ifdef INTEGER_ONLY
128
# define VFPRINTF vfiprintf
128
# define VFPRINTF vfiprintf
129
# ifdef STRING_ONLY
129
# ifdef STRING_ONLY
130
#   define _VFPRINTF_R _svfiprintf_r
130
#   define _VFPRINTF_R _svfiprintf_r
131
# else
131
# else
132
#   define _VFPRINTF_R _vfiprintf_r
132
#   define _VFPRINTF_R _vfiprintf_r
133
# endif
133
# endif
134
#else
134
#else
135
# define VFPRINTF vfprintf
135
# define VFPRINTF vfprintf
136
# ifdef STRING_ONLY
136
# ifdef STRING_ONLY
137
#   define _VFPRINTF_R _svfprintf_r
137
#   define _VFPRINTF_R _svfprintf_r
138
# else
138
# else
139
#   define _VFPRINTF_R _vfprintf_r
139
#   define _VFPRINTF_R _vfprintf_r
140
# endif
140
# endif
141
# ifndef NO_FLOATING_POINT
141
# ifndef NO_FLOATING_POINT
142
#  define FLOATING_POINT
142
#  define FLOATING_POINT
143
# endif
143
# endif
144
#endif
144
#endif
145
 
145
 
146
#define _NO_POS_ARGS
146
#define _NO_POS_ARGS
147
#ifdef _WANT_IO_POS_ARGS
147
#ifdef _WANT_IO_POS_ARGS
148
# undef _NO_POS_ARGS
148
# undef _NO_POS_ARGS
149
#endif
149
#endif
150
 
150
 
151
#include <_ansi.h>
151
#include <_ansi.h>
152
#include 
152
#include 
153
#include 
153
#include 
154
#include 
154
#include 
155
#include 
155
#include 
156
#include 
156
#include 
157
#include 
157
#include 
158
#include 
158
#include 
159
#include 
159
#include 
160
#include 
160
#include 
161
#include "local.h"
161
#include "local.h"
162
#include "../stdlib/local.h"
162
#include "../stdlib/local.h"
163
#include "fvwrite.h"
163
#include "fvwrite.h"
164
#include "vfieeefp.h"
164
#include "vfieeefp.h"
165
 
165
 
166
/* Currently a test is made to see if long double processing is warranted.
166
/* Currently a test is made to see if long double processing is warranted.
167
   This could be changed in the future should the _ldtoa_r code be
167
   This could be changed in the future should the _ldtoa_r code be
168
   preferred over _dtoa_r.  */
168
   preferred over _dtoa_r.  */
169
#define _NO_LONGDBL
169
#define _NO_LONGDBL
170
#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
170
#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
171
#undef _NO_LONGDBL
171
#undef _NO_LONGDBL
172
#endif
172
#endif
173
 
173
 
174
#define _NO_LONGLONG
174
#define _NO_LONGLONG
175
#if defined _WANT_IO_LONG_LONG \
175
#if defined _WANT_IO_LONG_LONG \
176
	&& (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
176
	&& (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
177
# undef _NO_LONGLONG
177
# undef _NO_LONGLONG
178
#endif
178
#endif
179
 
179
 
180
#ifdef STRING_ONLY
180
#ifdef STRING_ONLY
181
# ifdef _FVWRITE_IN_STREAMIO
181
# ifdef _FVWRITE_IN_STREAMIO
182
#  define __SPRINT __ssprint_r
182
#  define __SPRINT __ssprint_r
183
# else
183
# else
184
#  define __SPRINT __ssputs_r
184
#  define __SPRINT __ssputs_r
185
# endif
185
# endif
186
#else
186
#else
187
# ifdef _FVWRITE_IN_STREAMIO
187
# ifdef _FVWRITE_IN_STREAMIO
188
#  define __SPRINT __sprint_r
188
#  define __SPRINT __sprint_r
189
# else
189
# else
190
#  define __SPRINT __sfputs_r
190
#  define __SPRINT __sfputs_r
191
# endif
191
# endif
192
#endif
192
#endif
193
 
193
 
194
/* The __sprint_r/__ssprint_r functions are shared between all versions of
194
/* The __sprint_r/__ssprint_r functions are shared between all versions of
195
   vfprintf and vfwprintf.  They must only be defined once, which we do in
195
   vfprintf and vfwprintf.  They must only be defined once, which we do in
196
   the INTEGER_ONLY versions here. */
196
   the INTEGER_ONLY versions here. */
197
#ifdef STRING_ONLY
197
#ifdef STRING_ONLY
198
#ifdef INTEGER_ONLY
198
#ifdef INTEGER_ONLY
199
#ifndef _FVWRITE_IN_STREAMIO
199
#ifndef _FVWRITE_IN_STREAMIO
200
int
200
int
201
_DEFUN(__ssputs_r, (ptr, fp, buf, len),
201
_DEFUN(__ssputs_r, (ptr, fp, buf, len),
202
       struct _reent *ptr _AND
202
       struct _reent *ptr _AND
203
       FILE *fp _AND
203
       FILE *fp _AND
204
       _CONST char *buf _AND
204
       _CONST char *buf _AND
205
       size_t len)
205
       size_t len)
206
{
206
{
207
	register int w;
207
	register int w;
208
 
208
 
209
	w = fp->_w;
209
	w = fp->_w;
210
	if (len >= w && fp->_flags & (__SMBF | __SOPT)) {
210
	if (len >= w && fp->_flags & (__SMBF | __SOPT)) {
211
		/* must be asprintf family */
211
		/* must be asprintf family */
212
		unsigned char *str;
212
		unsigned char *str;
213
		int curpos = (fp->_p - fp->_bf._base);
213
		int curpos = (fp->_p - fp->_bf._base);
214
		/* Choose a geometric growth factor to avoid
214
		/* Choose a geometric growth factor to avoid
215
	 	 * quadratic realloc behavior, but use a rate less
215
	 	 * quadratic realloc behavior, but use a rate less
216
		 * than (1+sqrt(5))/2 to accomodate malloc
216
		 * than (1+sqrt(5))/2 to accomodate malloc
217
	 	 * overhead. asprintf EXPECTS us to overallocate, so
217
	 	 * overhead. asprintf EXPECTS us to overallocate, so
218
	 	 * that it can add a trailing \0 without
218
	 	 * that it can add a trailing \0 without
219
	 	 * reallocating.  The new allocation should thus be
219
	 	 * reallocating.  The new allocation should thus be
220
	 	 * max(prev_size*1.5, curpos+len+1). */
220
	 	 * max(prev_size*1.5, curpos+len+1). */
221
		int newsize = fp->_bf._size * 3 / 2;
221
		int newsize = fp->_bf._size * 3 / 2;
222
		if (newsize < curpos + len + 1)
222
		if (newsize < curpos + len + 1)
223
			newsize = curpos + len + 1;
223
			newsize = curpos + len + 1;
224
		if (fp->_flags & __SOPT)
224
		if (fp->_flags & __SOPT)
225
		{
225
		{
226
			/* asnprintf leaves original buffer alone.  */
226
			/* asnprintf leaves original buffer alone.  */
227
			str = (unsigned char *)_malloc_r (ptr, newsize);
227
			str = (unsigned char *)_malloc_r (ptr, newsize);
228
			if (!str)
228
			if (!str)
229
			{
229
			{
230
				ptr->_errno = ENOMEM;
230
				ptr->_errno = ENOMEM;
231
				goto err;
231
				goto err;
232
			}
232
			}
233
			memcpy (str, fp->_bf._base, curpos);
233
			memcpy (str, fp->_bf._base, curpos);
234
			fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
234
			fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
235
		}
235
		}
236
		else
236
		else
237
		{
237
		{
238
			str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
238
			str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
239
					newsize);
239
					newsize);
240
			if (!str) {
240
			if (!str) {
241
				/* Free unneeded buffer.  */
241
				/* Free unneeded buffer.  */
242
				_free_r (ptr, fp->_bf._base);
242
				_free_r (ptr, fp->_bf._base);
243
				/* Ensure correct errno, even if free
243
				/* Ensure correct errno, even if free
244
				 * changed it.  */
244
				 * changed it.  */
245
				ptr->_errno = ENOMEM;
245
				ptr->_errno = ENOMEM;
246
				goto err;
246
				goto err;
247
			}
247
			}
248
		}
248
		}
249
		fp->_bf._base = str;
249
		fp->_bf._base = str;
250
		fp->_p = str + curpos;
250
		fp->_p = str + curpos;
251
		fp->_bf._size = newsize;
251
		fp->_bf._size = newsize;
252
		w = len;
252
		w = len;
253
		fp->_w = newsize - curpos;
253
		fp->_w = newsize - curpos;
254
	}
254
	}
255
	if (len < w)
255
	if (len < w)
256
		w = len;
256
		w = len;
257
	(void)memmove ((_PTR) fp->_p, (_PTR) buf, (size_t) (w));
257
	(void)memmove ((_PTR) fp->_p, (_PTR) buf, (size_t) (w));
258
	fp->_w -= w;
258
	fp->_w -= w;
259
	fp->_p += w;
259
	fp->_p += w;
260
 
260
 
261
	return 0;
261
	return 0;
262
 
262
 
263
err:
263
err:
264
	fp->_flags |= __SERR;
264
	fp->_flags |= __SERR;
265
	return EOF;
265
	return EOF;
266
}
266
}
267
#endif
267
#endif
268
 
268
 
269
int
269
int
270
_DEFUN(__ssprint_r, (ptr, fp, uio),
270
_DEFUN(__ssprint_r, (ptr, fp, uio),
271
       struct _reent *ptr _AND
271
       struct _reent *ptr _AND
272
       FILE *fp _AND
272
       FILE *fp _AND
273
       register struct __suio *uio)
273
       register struct __suio *uio)
274
{
274
{
275
	register size_t len;
275
	register size_t len;
276
	register int w;
276
	register int w;
277
	register struct __siov *iov;
277
	register struct __siov *iov;
278
	register _CONST char *p = NULL;
278
	register _CONST char *p = NULL;
279
 
279
 
280
	iov = uio->uio_iov;
280
	iov = uio->uio_iov;
281
	len = 0;
281
	len = 0;
282
 
282
 
283
	if (uio->uio_resid == 0) {
283
	if (uio->uio_resid == 0) {
284
		uio->uio_iovcnt = 0;
284
		uio->uio_iovcnt = 0;
285
		return (0);
285
		return (0);
286
	}
286
	}
287
 
287
 
288
        do {
288
        do {
289
		while (len == 0) {
289
		while (len == 0) {
290
			p = iov->iov_base;
290
			p = iov->iov_base;
291
			len = iov->iov_len;
291
			len = iov->iov_len;
292
			iov++;
292
			iov++;
293
		}
293
		}
294
		w = fp->_w;
294
		w = fp->_w;
295
		if (len >= w && fp->_flags & (__SMBF | __SOPT)) {
295
		if (len >= w && fp->_flags & (__SMBF | __SOPT)) {
296
			/* must be asprintf family */
296
			/* must be asprintf family */
297
			unsigned char *str;
297
			unsigned char *str;
298
			int curpos = (fp->_p - fp->_bf._base);
298
			int curpos = (fp->_p - fp->_bf._base);
299
			/* Choose a geometric growth factor to avoid
299
			/* Choose a geometric growth factor to avoid
300
		 	 * quadratic realloc behavior, but use a rate less
300
		 	 * quadratic realloc behavior, but use a rate less
301
			 * than (1+sqrt(5))/2 to accomodate malloc
301
			 * than (1+sqrt(5))/2 to accomodate malloc
302
		 	 * overhead. asprintf EXPECTS us to overallocate, so
302
		 	 * overhead. asprintf EXPECTS us to overallocate, so
303
		 	 * that it can add a trailing \0 without
303
		 	 * that it can add a trailing \0 without
304
		 	 * reallocating.  The new allocation should thus be
304
		 	 * reallocating.  The new allocation should thus be
305
		 	 * max(prev_size*1.5, curpos+len+1). */
305
		 	 * max(prev_size*1.5, curpos+len+1). */
306
			int newsize = fp->_bf._size * 3 / 2;
306
			int newsize = fp->_bf._size * 3 / 2;
307
			if (newsize < curpos + len + 1)
307
			if (newsize < curpos + len + 1)
308
				newsize = curpos + len + 1;
308
				newsize = curpos + len + 1;
309
			if (fp->_flags & __SOPT)
309
			if (fp->_flags & __SOPT)
310
			{
310
			{
311
				/* asnprintf leaves original buffer alone.  */
311
				/* asnprintf leaves original buffer alone.  */
312
				str = (unsigned char *)_malloc_r (ptr, newsize);
312
				str = (unsigned char *)_malloc_r (ptr, newsize);
313
				if (!str)
313
				if (!str)
314
				{
314
				{
315
					ptr->_errno = ENOMEM;
315
					ptr->_errno = ENOMEM;
316
					goto err;
316
					goto err;
317
				}
317
				}
318
				memcpy (str, fp->_bf._base, curpos);
318
				memcpy (str, fp->_bf._base, curpos);
319
				fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
319
				fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
320
			}
320
			}
321
			else
321
			else
322
			{
322
			{
323
				str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
323
				str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
324
						newsize);
324
						newsize);
325
				if (!str) {
325
				if (!str) {
326
					/* Free unneeded buffer.  */
326
					/* Free unneeded buffer.  */
327
					_free_r (ptr, fp->_bf._base);
327
					_free_r (ptr, fp->_bf._base);
328
					/* Ensure correct errno, even if free
328
					/* Ensure correct errno, even if free
329
					 * changed it.  */
329
					 * changed it.  */
330
					ptr->_errno = ENOMEM;
330
					ptr->_errno = ENOMEM;
331
					goto err;
331
					goto err;
332
				}
332
				}
333
			}
333
			}
334
			fp->_bf._base = str;
334
			fp->_bf._base = str;
335
			fp->_p = str + curpos;
335
			fp->_p = str + curpos;
336
			fp->_bf._size = newsize;
336
			fp->_bf._size = newsize;
337
			w = len;
337
			w = len;
338
			fp->_w = newsize - curpos;
338
			fp->_w = newsize - curpos;
339
		}
339
		}
340
		if (len < w)
340
		if (len < w)
341
			w = len;
341
			w = len;
342
		(void)memmove ((_PTR) fp->_p, (_PTR) p, (size_t) (w));
342
		(void)memmove ((_PTR) fp->_p, (_PTR) p, (size_t) (w));
343
		fp->_w -= w;
343
		fp->_w -= w;
344
		fp->_p += w;
344
		fp->_p += w;
345
		w = len;          /* pretend we copied all */
345
		w = len;          /* pretend we copied all */
346
		p += w;
346
		p += w;
347
		len -= w;
347
		len -= w;
348
        } while ((uio->uio_resid -= w) != 0);
348
        } while ((uio->uio_resid -= w) != 0);
349
 
349
 
350
	uio->uio_resid = 0;
350
	uio->uio_resid = 0;
351
	uio->uio_iovcnt = 0;
351
	uio->uio_iovcnt = 0;
352
	return 0;
352
	return 0;
353
 
353
 
354
err:
354
err:
355
  fp->_flags |= __SERR;
355
  fp->_flags |= __SERR;
356
  uio->uio_resid = 0;
356
  uio->uio_resid = 0;
357
  uio->uio_iovcnt = 0;
357
  uio->uio_iovcnt = 0;
358
  return EOF;
358
  return EOF;
359
}
359
}
360
#else /* !INTEGER_ONLY */
360
#else /* !INTEGER_ONLY */
361
#ifndef _FVWRITE_IN_STREAMIO
361
#ifndef _FVWRITE_IN_STREAMIO
362
int __ssputs_r (struct _reent *, FILE *, _CONST char *, size_t);
362
int __ssputs_r (struct _reent *, FILE *, _CONST char *, size_t);
363
#endif
363
#endif
364
int __ssprint_r (struct _reent *, FILE *, register struct __suio *);
364
int __ssprint_r (struct _reent *, FILE *, register struct __suio *);
365
#endif /* !INTEGER_ONLY */
365
#endif /* !INTEGER_ONLY */
366
 
366
 
367
#else /* !STRING_ONLY */
367
#else /* !STRING_ONLY */
368
#ifdef INTEGER_ONLY
368
#ifdef INTEGER_ONLY
369
 
369
 
370
#ifndef _FVWRITE_IN_STREAMIO
370
#ifndef _FVWRITE_IN_STREAMIO
371
int
371
int
372
_DEFUN(__sfputs_r, (ptr, fp, buf, len),
372
_DEFUN(__sfputs_r, (ptr, fp, buf, len),
373
       struct _reent *ptr _AND
373
       struct _reent *ptr _AND
374
       FILE *fp _AND
374
       FILE *fp _AND
375
       _CONST char *buf _AND
375
       _CONST char *buf _AND
376
       size_t len)
376
       size_t len)
377
{
377
{
378
	register int i;
378
	register int i;
379
 
379
 
380
#ifdef _WIDE_ORIENT
380
#ifdef _WIDE_ORIENT
381
	if (fp->_flags2 & __SWID) {
381
	if (fp->_flags2 & __SWID) {
382
		wchar_t *p;
382
		wchar_t *p;
383
 
383
 
384
		p = (wchar_t *) buf;
384
		p = (wchar_t *) buf;
385
		for (i = 0; i < (len / sizeof (wchar_t)); i++) {
385
		for (i = 0; i < (len / sizeof (wchar_t)); i++) {
386
			if (_fputwc_r (ptr, p[i], fp) == WEOF)
386
			if (_fputwc_r (ptr, p[i], fp) == WEOF)
387
				return -1;
387
				return -1;
388
		}
388
		}
389
	} else {
389
	} else {
390
#else
390
#else
391
	{
391
	{
392
#endif
392
#endif
393
		for (i = 0; i < len; i++) {
393
		for (i = 0; i < len; i++) {
394
			if (_fputc_r (ptr, buf[i], fp) == EOF)
394
			if (_fputc_r (ptr, buf[i], fp) == EOF)
395
				return -1;
395
				return -1;
396
		}
396
		}
397
	}
397
	}
398
	return (0);
398
	return (0);
399
}
399
}
400
#endif
400
#endif
401
/*
401
/*
402
 * Flush out all the vectors defined by the given uio,
402
 * Flush out all the vectors defined by the given uio,
403
 * then reset it so that it can be reused.
403
 * then reset it so that it can be reused.
404
 */
404
 */
405
int
405
int
406
_DEFUN(__sprint_r, (ptr, fp, uio),
406
_DEFUN(__sprint_r, (ptr, fp, uio),
407
       struct _reent *ptr _AND
407
       struct _reent *ptr _AND
408
       FILE *fp _AND
408
       FILE *fp _AND
409
       register struct __suio *uio)
409
       register struct __suio *uio)
410
{
410
{
411
	register int err = 0;
411
	register int err = 0;
412
 
412
 
413
	if (uio->uio_resid == 0) {
413
	if (uio->uio_resid == 0) {
414
		uio->uio_iovcnt = 0;
414
		uio->uio_iovcnt = 0;
415
		return (0);
415
		return (0);
416
	}
416
	}
417
#ifdef _WIDE_ORIENT
417
#ifdef _WIDE_ORIENT
418
	if (fp->_flags2 & __SWID) {
418
	if (fp->_flags2 & __SWID) {
419
		struct __siov *iov;
419
		struct __siov *iov;
420
		wchar_t *p;
420
		wchar_t *p;
421
		int i, len;
421
		int i, len;
422
 
422
 
423
		iov = uio->uio_iov;
423
		iov = uio->uio_iov;
424
		for (; uio->uio_resid != 0;
424
		for (; uio->uio_resid != 0;
425
		     uio->uio_resid -= len * sizeof (wchar_t), iov++) {
425
		     uio->uio_resid -= len * sizeof (wchar_t), iov++) {
426
			p = (wchar_t *) iov->iov_base;
426
			p = (wchar_t *) iov->iov_base;
427
			len = iov->iov_len / sizeof (wchar_t);
427
			len = iov->iov_len / sizeof (wchar_t);
428
			for (i = 0; i < len; i++) {
428
			for (i = 0; i < len; i++) {
429
				if (_fputwc_r (ptr, p[i], fp) == WEOF) {
429
				if (_fputwc_r (ptr, p[i], fp) == WEOF) {
430
					err = -1;
430
					err = -1;
431
					goto out;
431
					goto out;
432
				}
432
				}
433
			}
433
			}
434
		}
434
		}
435
	} else
435
	} else
436
#endif
436
#endif
437
		err = __sfvwrite_r(ptr, fp, uio);
437
		err = __sfvwrite_r(ptr, fp, uio);
438
out:
438
out:
439
	uio->uio_resid = 0;
439
	uio->uio_resid = 0;
440
	uio->uio_iovcnt = 0;
440
	uio->uio_iovcnt = 0;
441
	return (err);
441
	return (err);
442
}
442
}
443
#else /* !INTEGER_ONLY */
443
#else /* !INTEGER_ONLY */
444
#ifndef _FVWRITE_IN_STREAMIO
444
#ifndef _FVWRITE_IN_STREAMIO
445
int __sfputs_r (struct _reent *, FILE *, _CONST char *buf, size_t);
445
int __sfputs_r (struct _reent *, FILE *, _CONST char *buf, size_t);
446
#endif
446
#endif
447
int __sprint_r (struct _reent *, FILE *, register struct __suio *);
447
int __sprint_r (struct _reent *, FILE *, register struct __suio *);
448
#endif /* !INTEGER_ONLY */
448
#endif /* !INTEGER_ONLY */
449
 
449
 
450
#ifdef _UNBUF_STREAM_OPT
450
#ifdef _UNBUF_STREAM_OPT
451
/*
451
/*
452
 * Helper function for `fprintf to unbuffered unix file': creates a
452
 * Helper function for `fprintf to unbuffered unix file': creates a
453
 * temporary buffer.  We only work on write-only files; this avoids
453
 * temporary buffer.  We only work on write-only files; this avoids
454
 * worries about ungetc buffers and so forth.
454
 * worries about ungetc buffers and so forth.
455
 *
455
 *
456
 * Make sure to avoid inlining.
456
 * Make sure to avoid inlining.
457
 */
457
 */
458
_NOINLINE_STATIC int
458
_NOINLINE_STATIC int
459
_DEFUN(__sbprintf, (rptr, fp, fmt, ap),
459
_DEFUN(__sbprintf, (rptr, fp, fmt, ap),
460
       struct _reent *rptr _AND
460
       struct _reent *rptr _AND
461
       register FILE *fp   _AND
461
       register FILE *fp   _AND
462
       _CONST char *fmt  _AND
462
       _CONST char *fmt  _AND
463
       va_list ap)
463
       va_list ap)
464
{
464
{
465
	int ret;
465
	int ret;
466
	FILE fake;
466
	FILE fake;
467
	unsigned char buf[BUFSIZ];
467
	unsigned char buf[BUFSIZ];
468
 
468
 
469
	/* copy the important variables */
469
	/* copy the important variables */
470
	fake._flags = fp->_flags & ~__SNBF;
470
	fake._flags = fp->_flags & ~__SNBF;
471
	fake._flags2 = fp->_flags2;
471
	fake._flags2 = fp->_flags2;
472
	fake._file = fp->_file;
472
	fake._file = fp->_file;
473
	fake._cookie = fp->_cookie;
473
	fake._cookie = fp->_cookie;
474
	fake._write = fp->_write;
474
	fake._write = fp->_write;
475
 
475
 
476
	/* set up the buffer */
476
	/* set up the buffer */
477
	fake._bf._base = fake._p = buf;
477
	fake._bf._base = fake._p = buf;
478
	fake._bf._size = fake._w = sizeof (buf);
478
	fake._bf._size = fake._w = sizeof (buf);
479
	fake._lbfsize = 0;	/* not actually used, but Just In Case */
479
	fake._lbfsize = 0;	/* not actually used, but Just In Case */
480
#ifndef __SINGLE_THREAD__
480
#ifndef __SINGLE_THREAD__
481
	__lock_init_recursive (fake._lock);
481
	__lock_init_recursive (fake._lock);
482
#endif
482
#endif
483
 
483
 
484
	/* do the work, then copy any error status */
484
	/* do the work, then copy any error status */
485
	ret = _VFPRINTF_R (rptr, &fake, fmt, ap);
485
	ret = _VFPRINTF_R (rptr, &fake, fmt, ap);
486
	if (ret >= 0 && _fflush_r (rptr, &fake))
486
	if (ret >= 0 && _fflush_r (rptr, &fake))
487
		ret = EOF;
487
		ret = EOF;
488
	if (fake._flags & __SERR)
488
	if (fake._flags & __SERR)
489
		fp->_flags |= __SERR;
489
		fp->_flags |= __SERR;
490
 
490
 
491
#ifndef __SINGLE_THREAD__
491
#ifndef __SINGLE_THREAD__
492
	__lock_close_recursive (fake._lock);
492
	__lock_close_recursive (fake._lock);
493
#endif
493
#endif
494
	return (ret);
494
	return (ret);
495
}
495
}
496
#endif /* _UNBUF_STREAM_OPT */
496
#endif /* _UNBUF_STREAM_OPT */
497
#endif /* !STRING_ONLY */
497
#endif /* !STRING_ONLY */
498
 
498
 
499
 
499
 
500
#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
500
#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
501
# include 
501
# include 
502
#endif
502
#endif
503
#ifdef FLOATING_POINT
503
#ifdef FLOATING_POINT
504
# include 
504
# include 
505
 
505
 
506
/* For %La, an exponent of 15 bits occupies the exponent character, a
506
/* For %La, an exponent of 15 bits occupies the exponent character, a
507
   sign, and up to 5 digits.  */
507
   sign, and up to 5 digits.  */
508
# define MAXEXPLEN		7
508
# define MAXEXPLEN		7
509
# define DEFPREC		6
509
# define DEFPREC		6
510
 
510
 
511
# ifdef _NO_LONGDBL
511
# ifdef _NO_LONGDBL
512
 
512
 
513
extern char *_dtoa_r _PARAMS((struct _reent *, double, int,
513
extern char *_dtoa_r _PARAMS((struct _reent *, double, int,
514
			      int, int *, int *, char **));
514
			      int, int *, int *, char **));
515
 
515
 
516
#  define _PRINTF_FLOAT_TYPE double
516
#  define _PRINTF_FLOAT_TYPE double
517
#  define _DTOA_R _dtoa_r
517
#  define _DTOA_R _dtoa_r
518
#  define FREXP frexp
518
#  define FREXP frexp
519
 
519
 
520
# else /* !_NO_LONGDBL */
520
# else /* !_NO_LONGDBL */
521
 
521
 
522
extern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int,
522
extern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int,
523
			      int, int *, int *, char **));
523
			      int, int *, int *, char **));
524
 
524
 
525
extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *));
525
extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *));
526
 
526
 
527
#  define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
527
#  define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
528
#  define _DTOA_R _ldtoa_r
528
#  define _DTOA_R _ldtoa_r
529
/* FIXME - frexpl is not yet supported; and cvt infloops if (double)f
529
/* FIXME - frexpl is not yet supported; and cvt infloops if (double)f
530
   converts a finite value into infinity.  */
530
   converts a finite value into infinity.  */
531
/* #  define FREXP frexpl */
531
/* #  define FREXP frexpl */
532
#  define FREXP(f,e) ((_LONG_DOUBLE) frexp ((double)f, e))
532
#  define FREXP(f,e) ((_LONG_DOUBLE) frexp ((double)f, e))
533
# endif /* !_NO_LONGDBL */
533
# endif /* !_NO_LONGDBL */
534
 
534
 
535
static char *cvt(struct _reent *, _PRINTF_FLOAT_TYPE, int, int, char *, int *,
535
static char *cvt(struct _reent *, _PRINTF_FLOAT_TYPE, int, int, char *, int *,
536
                 int, int *, char *);
536
                 int, int *, char *);
537
 
537
 
538
static int exponent(char *, int, int);
538
static int exponent(char *, int, int);
539
 
539
 
540
#endif /* FLOATING_POINT */
540
#endif /* FLOATING_POINT */
541
 
541
 
542
/* BUF must be big enough for the maximum %#llo (assuming long long is
542
/* BUF must be big enough for the maximum %#llo (assuming long long is
543
   at most 64 bits, this would be 23 characters), the maximum
543
   at most 64 bits, this would be 23 characters), the maximum
544
   multibyte character %C, and the maximum default precision of %La
544
   multibyte character %C, and the maximum default precision of %La
545
   (assuming long double is at most 128 bits with 113 bits of
545
   (assuming long double is at most 128 bits with 113 bits of
546
   mantissa, this would be 29 characters).  %e, %f, and %g use
546
   mantissa, this would be 29 characters).  %e, %f, and %g use
547
   reentrant storage shared with mprec.  All other formats that use
547
   reentrant storage shared with mprec.  All other formats that use
548
   buf get by with fewer characters.  Making BUF slightly bigger
548
   buf get by with fewer characters.  Making BUF slightly bigger
549
   reduces the need for malloc in %.*a and %S, when large precision or
549
   reduces the need for malloc in %.*a and %S, when large precision or
550
   long strings are processed.
550
   long strings are processed.
551
   The bigger size of 100 bytes is used on systems which allow number
551
   The bigger size of 100 bytes is used on systems which allow number
552
   strings using the locale's grouping character.  Since that's a multibyte
552
   strings using the locale's grouping character.  Since that's a multibyte
553
   value, we should use a conservative value.
553
   value, we should use a conservative value.
554
   */
554
   */
555
#ifdef _WANT_IO_C99_FORMATS
555
#ifdef _WANT_IO_C99_FORMATS
556
#define	BUF		100
556
#define	BUF		100
557
#else
557
#else
558
#define	BUF		40
558
#define	BUF		40
559
#endif
559
#endif
560
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF
560
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF
561
# undef BUF
561
# undef BUF
562
# define BUF MB_LEN_MAX
562
# define BUF MB_LEN_MAX
563
#endif
563
#endif
564
 
564
 
565
#ifndef _NO_LONGLONG
565
#ifndef _NO_LONGLONG
566
# define quad_t long long
566
# define quad_t long long
567
# define u_quad_t unsigned long long
567
# define u_quad_t unsigned long long
568
#else
568
#else
569
# define quad_t long
569
# define quad_t long
570
# define u_quad_t unsigned long
570
# define u_quad_t unsigned long
571
#endif
571
#endif
572
 
572
 
573
typedef quad_t * quad_ptr_t;
573
typedef quad_t * quad_ptr_t;
574
typedef _PTR     void_ptr_t;
574
typedef _PTR     void_ptr_t;
575
typedef char *   char_ptr_t;
575
typedef char *   char_ptr_t;
576
typedef long *   long_ptr_t;
576
typedef long *   long_ptr_t;
577
typedef int  *   int_ptr_t;
577
typedef int  *   int_ptr_t;
578
typedef short *  short_ptr_t;
578
typedef short *  short_ptr_t;
579
 
579
 
580
#ifndef _NO_POS_ARGS
580
#ifndef _NO_POS_ARGS
581
# ifdef NL_ARGMAX
581
# ifdef NL_ARGMAX
582
#  define MAX_POS_ARGS NL_ARGMAX
582
#  define MAX_POS_ARGS NL_ARGMAX
583
# else
583
# else
584
#  define MAX_POS_ARGS 32
584
#  define MAX_POS_ARGS 32
585
# endif
585
# endif
586
 
586
 
587
union arg_val
587
union arg_val
588
{
588
{
589
  int val_int;
589
  int val_int;
590
  u_int val_u_int;
590
  u_int val_u_int;
591
  long val_long;
591
  long val_long;
592
  u_long val_u_long;
592
  u_long val_u_long;
593
  float val_float;
593
  float val_float;
594
  double val_double;
594
  double val_double;
595
  _LONG_DOUBLE val__LONG_DOUBLE;
595
  _LONG_DOUBLE val__LONG_DOUBLE;
596
  int_ptr_t val_int_ptr_t;
596
  int_ptr_t val_int_ptr_t;
597
  short_ptr_t val_short_ptr_t;
597
  short_ptr_t val_short_ptr_t;
598
  long_ptr_t val_long_ptr_t;
598
  long_ptr_t val_long_ptr_t;
599
  char_ptr_t val_char_ptr_t;
599
  char_ptr_t val_char_ptr_t;
600
  quad_ptr_t val_quad_ptr_t;
600
  quad_ptr_t val_quad_ptr_t;
601
  void_ptr_t val_void_ptr_t;
601
  void_ptr_t val_void_ptr_t;
602
  quad_t val_quad_t;
602
  quad_t val_quad_t;
603
  u_quad_t val_u_quad_t;
603
  u_quad_t val_u_quad_t;
604
  wint_t val_wint_t;
604
  wint_t val_wint_t;
605
};
605
};
606
 
606
 
607
static union arg_val *
607
static union arg_val *
608
_EXFUN(get_arg, (struct _reent *data, int n, char *fmt,
608
_EXFUN(get_arg, (struct _reent *data, int n, char *fmt,
609
                 va_list *ap, int *numargs, union arg_val *args,
609
                 va_list *ap, int *numargs, union arg_val *args,
610
                 int *arg_type, char **last_fmt));
610
                 int *arg_type, char **last_fmt));
611
#endif /* !_NO_POS_ARGS */
611
#endif /* !_NO_POS_ARGS */
612
 
612
 
613
/*
613
/*
614
 * Macros for converting digits to letters and vice versa
614
 * Macros for converting digits to letters and vice versa
615
 */
615
 */
616
#define	to_digit(c)	((c) - '0')
616
#define	to_digit(c)	((c) - '0')
617
#define is_digit(c)	((unsigned)to_digit (c) <= 9)
617
#define is_digit(c)	((unsigned)to_digit (c) <= 9)
618
#define	to_char(n)	((n) + '0')
618
#define	to_char(n)	((n) + '0')
619
 
619
 
620
/*
620
/*
621
 * Flags used during conversion.
621
 * Flags used during conversion.
622
 */
622
 */
623
#define	ALT		0x001		/* alternate form */
623
#define	ALT		0x001		/* alternate form */
624
#define	HEXPREFIX	0x002		/* add 0x or 0X prefix */
624
#define	HEXPREFIX	0x002		/* add 0x or 0X prefix */
625
#define	LADJUST		0x004		/* left adjustment */
625
#define	LADJUST		0x004		/* left adjustment */
626
#define	LONGDBL		0x008		/* long double */
626
#define	LONGDBL		0x008		/* long double */
627
#define	LONGINT		0x010		/* long integer */
627
#define	LONGINT		0x010		/* long integer */
628
#ifndef _NO_LONGLONG
628
#ifndef _NO_LONGLONG
629
# define QUADINT	0x020		/* quad integer */
629
# define QUADINT	0x020		/* quad integer */
630
#else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
630
#else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
631
	 that %lld behaves the same as %ld, not as %d, as expected if:
631
	 that %lld behaves the same as %ld, not as %d, as expected if:
632
	 sizeof (long long) = sizeof long > sizeof int  */
632
	 sizeof (long long) = sizeof long > sizeof int  */
633
# define QUADINT	LONGINT
633
# define QUADINT	LONGINT
634
#endif
634
#endif
635
#define	SHORTINT	0x040		/* short integer */
635
#define	SHORTINT	0x040		/* short integer */
636
#define	ZEROPAD		0x080		/* zero (as opposed to blank) pad */
636
#define	ZEROPAD		0x080		/* zero (as opposed to blank) pad */
637
#define FPT		0x100		/* Floating point number */
637
#define FPT		0x100		/* Floating point number */
638
#ifdef _WANT_IO_C99_FORMATS
638
#ifdef _WANT_IO_C99_FORMATS
639
# define CHARINT	0x200		/* char as integer */
639
# define CHARINT	0x200		/* char as integer */
640
#else /* define as 0, to make SARG and UARG occupy fewer instructions  */
640
#else /* define as 0, to make SARG and UARG occupy fewer instructions  */
641
# define CHARINT	0
641
# define CHARINT	0
642
#endif
642
#endif
643
#ifdef _WANT_IO_C99_FORMATS
643
#ifdef _WANT_IO_C99_FORMATS
644
# define GROUPING	0x400		/* use grouping ("'" flag) */
644
# define GROUPING	0x400		/* use grouping ("'" flag) */
645
#endif
645
#endif
646
 
646
 
647
int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));
647
int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));
648
 
648
 
649
#ifndef STRING_ONLY
649
#ifndef STRING_ONLY
650
int
650
int
651
_DEFUN(VFPRINTF, (fp, fmt0, ap),
651
_DEFUN(VFPRINTF, (fp, fmt0, ap),
652
       FILE * fp         _AND
652
       FILE * fp         _AND
653
       _CONST char *fmt0 _AND
653
       _CONST char *fmt0 _AND
654
       va_list ap)
654
       va_list ap)
655
{
655
{
656
  int result;
656
  int result;
657
  result = _VFPRINTF_R (_REENT, fp, fmt0, ap);
657
  result = _VFPRINTF_R (_REENT, fp, fmt0, ap);
658
  return result;
658
  return result;
659
}
659
}
660
#endif /* STRING_ONLY */
660
#endif /* STRING_ONLY */
661
 
661
 
662
int
662
int
663
_DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
663
_DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
664
       struct _reent *data _AND
664
       struct _reent *data _AND
665
       FILE * fp           _AND
665
       FILE * fp           _AND
666
       _CONST char *fmt0   _AND
666
       _CONST char *fmt0   _AND
667
       va_list ap)
667
       va_list ap)
668
{
668
{
669
	register char *fmt;	/* format string */
669
	register char *fmt;	/* format string */
670
	register int ch;	/* character from fmt */
670
	register int ch;	/* character from fmt */
671
	register int n, m;	/* handy integers (short term usage) */
671
	register int n, m;	/* handy integers (short term usage) */
672
	register char *cp;	/* handy char pointer (short term usage) */
672
	register char *cp;	/* handy char pointer (short term usage) */
673
	register int flags;	/* flags as above */
673
	register int flags;	/* flags as above */
674
	char *fmt_anchor;       /* current format spec being processed */
674
	char *fmt_anchor;       /* current format spec being processed */
675
#ifndef _NO_POS_ARGS
675
#ifndef _NO_POS_ARGS
676
	int N;                  /* arg number */
676
	int N;                  /* arg number */
677
	int arg_index;          /* index into args processed directly */
677
	int arg_index;          /* index into args processed directly */
678
	int numargs;            /* number of varargs read */
678
	int numargs;            /* number of varargs read */
679
	char *saved_fmt;        /* saved fmt pointer */
679
	char *saved_fmt;        /* saved fmt pointer */
680
	union arg_val args[MAX_POS_ARGS];
680
	union arg_val args[MAX_POS_ARGS];
681
	int arg_type[MAX_POS_ARGS];
681
	int arg_type[MAX_POS_ARGS];
682
	int is_pos_arg;         /* is current format positional? */
682
	int is_pos_arg;         /* is current format positional? */
683
	int old_is_pos_arg;     /* is current format positional? */
683
	int old_is_pos_arg;     /* is current format positional? */
684
#endif
684
#endif
685
	int ret;		/* return value accumulator */
685
	int ret;		/* return value accumulator */
686
	int width;		/* width from format (%8d), or 0 */
686
	int width;		/* width from format (%8d), or 0 */
687
	int prec;		/* precision from format (%.3d), or -1 */
687
	int prec;		/* precision from format (%.3d), or -1 */
688
	char sign;		/* sign prefix (' ', '+', '-', or \0) */
688
	char sign;		/* sign prefix (' ', '+', '-', or \0) */
689
#ifdef _WANT_IO_C99_FORMATS
689
#ifdef _WANT_IO_C99_FORMATS
690
				/* locale specific numeric grouping */
690
				/* locale specific numeric grouping */
691
	char *thousands_sep = NULL;
691
	char *thousands_sep = NULL;
692
	size_t thsnd_len = 0;
692
	size_t thsnd_len = 0;
693
	const char *grouping = NULL;
693
	const char *grouping = NULL;
694
#endif
694
#endif
695
#ifdef FLOATING_POINT
695
#ifdef FLOATING_POINT
696
	char *decimal_point = _localeconv_r (data)->decimal_point;
696
	char *decimal_point = _localeconv_r (data)->decimal_point;
697
	size_t decp_len = strlen (decimal_point);
697
	size_t decp_len = strlen (decimal_point);
698
	char softsign;		/* temporary negative sign for floats */
698
	char softsign;		/* temporary negative sign for floats */
699
	union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
699
	union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
700
# define _fpvalue (_double_.fp)
700
# define _fpvalue (_double_.fp)
701
	int expt;		/* integer value of exponent */
701
	int expt;		/* integer value of exponent */
702
	int expsize = 0;	/* character count for expstr */
702
	int expsize = 0;	/* character count for expstr */
703
	char expstr[MAXEXPLEN];	/* buffer for exponent string */
703
	char expstr[MAXEXPLEN];	/* buffer for exponent string */
704
	int lead;		/* sig figs before decimal or group sep */
704
	int lead;		/* sig figs before decimal or group sep */
705
#endif /* FLOATING_POINT */
705
#endif /* FLOATING_POINT */
706
#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
706
#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
707
	int ndig = 0;		/* actual number of digits returned by cvt */
707
	int ndig = 0;		/* actual number of digits returned by cvt */
708
#endif
708
#endif
709
#if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
709
#if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
710
	int nseps;		/* number of group separators with ' */
710
	int nseps;		/* number of group separators with ' */
711
	int nrepeats;		/* number of repeats of the last group */
711
	int nrepeats;		/* number of repeats of the last group */
712
#endif
712
#endif
713
	u_quad_t _uquad;	/* integer arguments %[diouxX] */
713
	u_quad_t _uquad;	/* integer arguments %[diouxX] */
714
	enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
714
	enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
715
	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
715
	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
716
	int realsz;		/* field size expanded by dprec */
716
	int realsz;		/* field size expanded by dprec */
717
	int size;		/* size of converted field or string */
717
	int size;		/* size of converted field or string */
718
	char *xdigs = NULL;	/* digits for [xX] conversion */
718
	char *xdigs = NULL;	/* digits for [xX] conversion */
719
#ifdef _FVWRITE_IN_STREAMIO
719
#ifdef _FVWRITE_IN_STREAMIO
720
#define NIOV 8
720
#define NIOV 8
721
	struct __suio uio;	/* output information: summary */
721
	struct __suio uio;	/* output information: summary */
722
	struct __siov iov[NIOV];/* ... and individual io vectors */
722
	struct __siov iov[NIOV];/* ... and individual io vectors */
723
	register struct __siov *iovp;/* for PRINT macro */
723
	register struct __siov *iovp;/* for PRINT macro */
724
#endif
724
#endif
725
	char buf[BUF];		/* space for %c, %S, %[diouxX], %[aA] */
725
	char buf[BUF];		/* space for %c, %S, %[diouxX], %[aA] */
726
	char ox[2];		/* space for 0x hex-prefix */
726
	char ox[2];		/* space for 0x hex-prefix */
727
#ifdef _MB_CAPABLE
727
#ifdef _MB_CAPABLE
728
	wchar_t wc;
728
	wchar_t wc;
729
	mbstate_t state;        /* mbtowc calls from library must not change state */
729
	mbstate_t state;        /* mbtowc calls from library must not change state */
730
#endif
730
#endif
731
	char *malloc_buf = NULL;/* handy pointer for malloced buffers */
731
	char *malloc_buf = NULL;/* handy pointer for malloced buffers */
732
 
732
 
733
	/*
733
	/*
734
	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
734
	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
735
	 * fields occur frequently, increase PADSIZE and make the initialisers
735
	 * fields occur frequently, increase PADSIZE and make the initialisers
736
	 * below longer.
736
	 * below longer.
737
	 */
737
	 */
738
#define	PADSIZE	16		/* pad chunk size */
738
#define	PADSIZE	16		/* pad chunk size */
739
	static _CONST char blanks[PADSIZE] =
739
	static _CONST char blanks[PADSIZE] =
740
	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
740
	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
741
	static _CONST char zeroes[PADSIZE] =
741
	static _CONST char zeroes[PADSIZE] =
742
	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
742
	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
743
 
743
 
744
#ifdef _MB_CAPABLE
744
#ifdef _MB_CAPABLE
745
	memset (&state, '\0', sizeof (state));
745
	memset (&state, '\0', sizeof (state));
746
#endif
746
#endif
747
	/*
747
	/*
748
	 * BEWARE, these `goto error' on error, and PAD uses `n'.
748
	 * BEWARE, these `goto error' on error, and PAD uses `n'.
749
	 */
749
	 */
750
#ifdef _FVWRITE_IN_STREAMIO
750
#ifdef _FVWRITE_IN_STREAMIO
751
#define	PRINT(ptr, len) { \
751
#define	PRINT(ptr, len) { \
752
	iovp->iov_base = (ptr); \
752
	iovp->iov_base = (ptr); \
753
	iovp->iov_len = (len); \
753
	iovp->iov_len = (len); \
754
	uio.uio_resid += (len); \
754
	uio.uio_resid += (len); \
755
	iovp++; \
755
	iovp++; \
756
	if (++uio.uio_iovcnt >= NIOV) { \
756
	if (++uio.uio_iovcnt >= NIOV) { \
757
		if (__SPRINT(data, fp, &uio)) \
757
		if (__SPRINT(data, fp, &uio)) \
758
			goto error; \
758
			goto error; \
759
		iovp = iov; \
759
		iovp = iov; \
760
	} \
760
	} \
761
}
761
}
762
#define	PAD(howmany, with) { \
762
#define	PAD(howmany, with) { \
763
	if ((n = (howmany)) > 0) { \
763
	if ((n = (howmany)) > 0) { \
764
		while (n > PADSIZE) { \
764
		while (n > PADSIZE) { \
765
			PRINT (with, PADSIZE); \
765
			PRINT (with, PADSIZE); \
766
			n -= PADSIZE; \
766
			n -= PADSIZE; \
767
		} \
767
		} \
768
		PRINT (with, n); \
768
		PRINT (with, n); \
769
	} \
769
	} \
770
}
770
}
771
#define PRINTANDPAD(p, ep, len, with) { \
771
#define PRINTANDPAD(p, ep, len, with) { \
772
	int n = (ep) - (p); \
772
	int n = (ep) - (p); \
773
	if (n > (len)) \
773
	if (n > (len)) \
774
		n = (len); \
774
		n = (len); \
775
	if (n > 0) \
775
	if (n > 0) \
776
		PRINT((p), n); \
776
		PRINT((p), n); \
777
	PAD((len) - (n > 0 ? n : 0), (with)); \
777
	PAD((len) - (n > 0 ? n : 0), (with)); \
778
}
778
}
779
#define	FLUSH() { \
779
#define	FLUSH() { \
780
	if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
780
	if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
781
		goto error; \
781
		goto error; \
782
	uio.uio_iovcnt = 0; \
782
	uio.uio_iovcnt = 0; \
783
	iovp = iov; \
783
	iovp = iov; \
784
}
784
}
785
#else
785
#else
786
#define PRINT(ptr, len) {		\
786
#define PRINT(ptr, len) {		\
787
	if (__SPRINT (data, fp, (ptr), (len)) == EOF) \
787
	if (__SPRINT (data, fp, (ptr), (len)) == EOF) \
788
		goto error;		\
788
		goto error;		\
789
}
789
}
790
#define	PAD(howmany, with) {		\
790
#define	PAD(howmany, with) {		\
791
	if ((n = (howmany)) > 0) {	\
791
	if ((n = (howmany)) > 0) {	\
792
		while (n > PADSIZE) {	\
792
		while (n > PADSIZE) {	\
793
			PRINT (with, PADSIZE);	\
793
			PRINT (with, PADSIZE);	\
794
			n -= PADSIZE;	\
794
			n -= PADSIZE;	\
795
		}			\
795
		}			\
796
		PRINT (with, n);	\
796
		PRINT (with, n);	\
797
	}				\
797
	}				\
798
}
798
}
799
#define PRINTANDPAD(p, ep, len, with) {	\
799
#define PRINTANDPAD(p, ep, len, with) {	\
800
	int n = (ep) - (p);		\
800
	int n = (ep) - (p);		\
801
	if (n > (len))			\
801
	if (n > (len))			\
802
		n = (len);		\
802
		n = (len);		\
803
	if (n > 0)			\
803
	if (n > 0)			\
804
		PRINT((p), n);		\
804
		PRINT((p), n);		\
805
	PAD((len) - (n > 0 ? n : 0), (with)); \
805
	PAD((len) - (n > 0 ? n : 0), (with)); \
806
}
806
}
807
#define FLUSH()
807
#define FLUSH()
808
#endif
808
#endif
809
 
809
 
810
	/* Macros to support positional arguments */
810
	/* Macros to support positional arguments */
811
#ifndef _NO_POS_ARGS
811
#ifndef _NO_POS_ARGS
812
# define GET_ARG(n, ap, type)						\
812
# define GET_ARG(n, ap, type)						\
813
	(is_pos_arg							\
813
	(is_pos_arg							\
814
	 ? (n < numargs							\
814
	 ? (n < numargs							\
815
	    ? args[n].val_##type					\
815
	    ? args[n].val_##type					\
816
	    : get_arg (data, n, fmt_anchor, &ap, &numargs, args,	\
816
	    : get_arg (data, n, fmt_anchor, &ap, &numargs, args,	\
817
		       arg_type, &saved_fmt)->val_##type)		\
817
		       arg_type, &saved_fmt)->val_##type)		\
818
	 : (arg_index++ < numargs					\
818
	 : (arg_index++ < numargs					\
819
	    ? args[n].val_##type					\
819
	    ? args[n].val_##type					\
820
	    : (numargs < MAX_POS_ARGS					\
820
	    : (numargs < MAX_POS_ARGS					\
821
	       ? args[numargs++].val_##type = va_arg (ap, type)		\
821
	       ? args[numargs++].val_##type = va_arg (ap, type)		\
822
	       : va_arg (ap, type))))
822
	       : va_arg (ap, type))))
823
#else
823
#else
824
# define GET_ARG(n, ap, type) (va_arg (ap, type))
824
# define GET_ARG(n, ap, type) (va_arg (ap, type))
825
#endif
825
#endif
826
 
826
 
827
	/*
827
	/*
828
	 * To extend shorts properly, we need both signed and unsigned
828
	 * To extend shorts properly, we need both signed and unsigned
829
	 * argument extraction methods.
829
	 * argument extraction methods.
830
	 */
830
	 */
831
#ifndef _NO_LONGLONG
831
#ifndef _NO_LONGLONG
832
#define	SARG() \
832
#define	SARG() \
833
	(flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
833
	(flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
834
	    flags&LONGINT ? GET_ARG (N, ap, long) : \
834
	    flags&LONGINT ? GET_ARG (N, ap, long) : \
835
	    flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
835
	    flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
836
	    flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
836
	    flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
837
	    (long)GET_ARG (N, ap, int))
837
	    (long)GET_ARG (N, ap, int))
838
#define	UARG() \
838
#define	UARG() \
839
	(flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
839
	(flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
840
	    flags&LONGINT ? GET_ARG (N, ap, u_long) : \
840
	    flags&LONGINT ? GET_ARG (N, ap, u_long) : \
841
	    flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
841
	    flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
842
	    flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
842
	    flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
843
	    (u_long)GET_ARG (N, ap, u_int))
843
	    (u_long)GET_ARG (N, ap, u_int))
844
#else
844
#else
845
#define	SARG() \
845
#define	SARG() \
846
	(flags&LONGINT ? GET_ARG (N, ap, long) : \
846
	(flags&LONGINT ? GET_ARG (N, ap, long) : \
847
	    flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
847
	    flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
848
	    flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
848
	    flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
849
	    (long)GET_ARG (N, ap, int))
849
	    (long)GET_ARG (N, ap, int))
850
#define	UARG() \
850
#define	UARG() \
851
	(flags&LONGINT ? GET_ARG (N, ap, u_long) : \
851
	(flags&LONGINT ? GET_ARG (N, ap, u_long) : \
852
	    flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
852
	    flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
853
	    flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
853
	    flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
854
	    (u_long)GET_ARG (N, ap, u_int))
854
	    (u_long)GET_ARG (N, ap, u_int))
855
#endif
855
#endif
856
 
856
 
857
#ifndef STRING_ONLY
857
#ifndef STRING_ONLY
858
	/* Initialize std streams if not dealing with sprintf family.  */
858
	/* Initialize std streams if not dealing with sprintf family.  */
859
	CHECK_INIT (data, fp);
859
	CHECK_INIT (data, fp);
860
    _newlib_flockfile_start (fp);
860
	_newlib_flockfile_start (fp);
861
 
861
 
862
	ORIENT(fp, -1);
862
	ORIENT(fp, -1);
863
 
863
 
864
	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
864
	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
865
	if (cantwrite (data, fp)) {
865
	if (cantwrite (data, fp)) {
866
		_newlib_flockfile_exit (fp);
866
		_newlib_flockfile_exit (fp);
867
		return (EOF);
867
		return (EOF);
868
	}
868
	}
869
 
869
 
870
#ifdef _UNBUF_STREAM_OPT
870
#ifdef _UNBUF_STREAM_OPT
871
	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
871
	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
872
	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
872
	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
873
	    fp->_file >= 0) {
873
	    fp->_file >= 0) {
874
		_newlib_flockfile_exit (fp);
874
		_newlib_flockfile_exit (fp);
875
		return (__sbprintf (data, fp, fmt0, ap));
875
		return (__sbprintf (data, fp, fmt0, ap));
876
	}
876
	}
877
#endif
877
#endif
878
#else /* STRING_ONLY */
878
#else /* STRING_ONLY */
879
        /* Create initial buffer if we are called by asprintf family.  */
879
        /* Create initial buffer if we are called by asprintf family.  */
880
        if (fp->_flags & __SMBF && !fp->_bf._base)
880
        if (fp->_flags & __SMBF && !fp->_bf._base)
881
        {
881
        {
882
		fp->_bf._base = fp->_p = _malloc_r (data, 64);
882
		fp->_bf._base = fp->_p = _malloc_r (data, 64);
883
		if (!fp->_p)
883
		if (!fp->_p)
884
		{
884
		{
885
			data->_errno = ENOMEM;
885
			data->_errno = ENOMEM;
886
			return EOF;
886
			return EOF;
887
		}
887
		}
888
		fp->_bf._size = 64;
888
		fp->_bf._size = 64;
889
        }
889
        }
890
#endif /* STRING_ONLY */
890
#endif /* STRING_ONLY */
891
 
891
 
892
	fmt = (char *)fmt0;
892
	fmt = (char *)fmt0;
893
#ifdef _FVWRITE_IN_STREAMIO
893
#ifdef _FVWRITE_IN_STREAMIO
894
	uio.uio_iov = iovp = iov;
894
	uio.uio_iov = iovp = iov;
895
	uio.uio_resid = 0;
895
	uio.uio_resid = 0;
896
	uio.uio_iovcnt = 0;
896
	uio.uio_iovcnt = 0;
897
#endif
897
#endif
898
	ret = 0;
898
	ret = 0;
899
#ifndef _NO_POS_ARGS
899
#ifndef _NO_POS_ARGS
900
	arg_index = 0;
900
	arg_index = 0;
901
	saved_fmt = NULL;
901
	saved_fmt = NULL;
902
	arg_type[0] = -1;
902
	arg_type[0] = -1;
903
	numargs = 0;
903
	numargs = 0;
904
	is_pos_arg = 0;
904
	is_pos_arg = 0;
905
#endif
905
#endif
906
 
906
 
907
	/*
907
	/*
908
	 * Scan the format for conversions (`%' character).
908
	 * Scan the format for conversions (`%' character).
909
	 */
909
	 */
910
	for (;;) {
910
	for (;;) {
911
	        cp = fmt;
911
	        cp = fmt;
912
#ifdef _MB_CAPABLE
912
#ifdef _MB_CAPABLE
913
	        while ((n = __mbtowc (data, &wc, fmt, MB_CUR_MAX,
913
	        while ((n = __mbtowc (data, &wc, fmt, MB_CUR_MAX,
914
				      __locale_charset (), &state)) != 0) {
914
				      __locale_charset (), &state)) != 0) {
915
		    if (n < 0) {
915
		    if (n < 0) {
916
			/* Wave invalid chars through. */
916
			/* Wave invalid chars through. */
917
			memset (&state, 0, sizeof state);
917
			memset (&state, 0, sizeof state);
918
			n = 1;
918
			n = 1;
919
		    }
919
		    }
920
                    else if (wc == '%')
920
                    else if (wc == '%')
921
                        break;
921
                        break;
922
                    fmt += n;
922
                    fmt += n;
923
		}
923
		}
924
#else
924
#else
925
                while (*fmt != '\0' && *fmt != '%')
925
                while (*fmt != '\0' && *fmt != '%')
926
                    fmt += 1;
926
                    fmt += 1;
927
#endif
927
#endif
928
		if ((m = fmt - cp) != 0) {
928
		if ((m = fmt - cp) != 0) {
929
			PRINT (cp, m);
929
			PRINT (cp, m);
930
			ret += m;
930
			ret += m;
931
		}
931
		}
932
#ifdef _MB_CAPABLE
932
#ifdef _MB_CAPABLE
933
		if (n <= 0)
933
		if (n <= 0)
934
                    goto done;
934
                    goto done;
935
#else
935
#else
936
                if (*fmt == '\0')
936
                if (*fmt == '\0')
937
                    goto done;
937
                    goto done;
938
#endif
938
#endif
939
		fmt_anchor = fmt;
939
		fmt_anchor = fmt;
940
		fmt++;		/* skip over '%' */
940
		fmt++;		/* skip over '%' */
941
 
941
 
942
		flags = 0;
942
		flags = 0;
943
		dprec = 0;
943
		dprec = 0;
944
		width = 0;
944
		width = 0;
945
		prec = -1;
945
		prec = -1;
946
		sign = '\0';
946
		sign = '\0';
947
#ifdef FLOATING_POINT
947
#ifdef FLOATING_POINT
948
		lead = 0;
948
		lead = 0;
949
#ifdef _WANT_IO_C99_FORMATS
949
#ifdef _WANT_IO_C99_FORMATS
950
		nseps = nrepeats = 0;
950
		nseps = nrepeats = 0;
951
#endif
951
#endif
952
#endif
952
#endif
953
#ifndef _NO_POS_ARGS
953
#ifndef _NO_POS_ARGS
954
		N = arg_index;
954
		N = arg_index;
955
		is_pos_arg = 0;
955
		is_pos_arg = 0;
956
#endif
956
#endif
957
 
957
 
958
rflag:		ch = *fmt++;
958
rflag:		ch = *fmt++;
959
reswitch:	switch (ch) {
959
reswitch:	switch (ch) {
960
#ifdef _WANT_IO_C99_FORMATS
960
#ifdef _WANT_IO_C99_FORMATS
961
		case '\'':
961
		case '\'':
962
			thousands_sep = _localeconv_r (data)->thousands_sep;
962
			thousands_sep = _localeconv_r (data)->thousands_sep;
963
			thsnd_len = strlen (thousands_sep);
963
			thsnd_len = strlen (thousands_sep);
964
			grouping = _localeconv_r (data)->grouping;
964
			grouping = _localeconv_r (data)->grouping;
965
			if (thsnd_len > 0 && grouping && *grouping)
965
			if (thsnd_len > 0 && grouping && *grouping)
966
			  flags |= GROUPING;
966
			  flags |= GROUPING;
967
		  goto rflag;
967
			goto rflag;
968
#endif
968
#endif
969
		case ' ':
969
		case ' ':
970
			/*
970
			/*
971
			 * ``If the space and + flags both appear, the space
971
			 * ``If the space and + flags both appear, the space
972
			 * flag will be ignored.''
972
			 * flag will be ignored.''
973
			 *	-- ANSI X3J11
973
			 *	-- ANSI X3J11
974
			 */
974
			 */
975
			if (!sign)
975
			if (!sign)
976
				sign = ' ';
976
				sign = ' ';
977
			goto rflag;
977
			goto rflag;
978
		case '#':
978
		case '#':
979
			flags |= ALT;
979
			flags |= ALT;
980
			goto rflag;
980
			goto rflag;
981
		case '*':
981
		case '*':
982
#ifndef _NO_POS_ARGS
982
#ifndef _NO_POS_ARGS
983
			/* we must check for positional arg used for dynamic width */
983
			/* we must check for positional arg used for dynamic width */
984
			n = N;
984
			n = N;
985
			old_is_pos_arg = is_pos_arg;
985
			old_is_pos_arg = is_pos_arg;
986
			is_pos_arg = 0;
986
			is_pos_arg = 0;
987
			if (is_digit (*fmt)) {
987
			if (is_digit (*fmt)) {
988
				char *old_fmt = fmt;
988
				char *old_fmt = fmt;
989
 
989
 
990
				n = 0;
990
				n = 0;
991
				ch = *fmt++;
991
				ch = *fmt++;
992
				do {
992
				do {
993
					n = 10 * n + to_digit (ch);
993
					n = 10 * n + to_digit (ch);
994
					ch = *fmt++;
994
					ch = *fmt++;
995
				} while (is_digit (ch));
995
				} while (is_digit (ch));
996
 
996
 
997
				if (ch == '$') {
997
				if (ch == '$') {
998
					if (n <= MAX_POS_ARGS) {
998
					if (n <= MAX_POS_ARGS) {
999
						n -= 1;
999
						n -= 1;
1000
						is_pos_arg = 1;
1000
						is_pos_arg = 1;
1001
					}
1001
					}
1002
					else
1002
					else
1003
						goto error;
1003
						goto error;
1004
				}
1004
				}
1005
				else {
1005
				else {
1006
					fmt = old_fmt;
1006
					fmt = old_fmt;
1007
					goto rflag;
1007
					goto rflag;
1008
				}
1008
				}
1009
			}
1009
			}
1010
#endif /* !_NO_POS_ARGS */
1010
#endif /* !_NO_POS_ARGS */
1011
 
1011
 
1012
			/*
1012
			/*
1013
			 * ``A negative field width argument is taken as a
1013
			 * ``A negative field width argument is taken as a
1014
			 * - flag followed by a positive field width.''
1014
			 * - flag followed by a positive field width.''
1015
			 *	-- ANSI X3J11
1015
			 *	-- ANSI X3J11
1016
			 * They don't exclude field widths read from args.
1016
			 * They don't exclude field widths read from args.
1017
			 */
1017
			 */
1018
			width = GET_ARG (n, ap, int);
1018
			width = GET_ARG (n, ap, int);
1019
#ifndef _NO_POS_ARGS
1019
#ifndef _NO_POS_ARGS
1020
			is_pos_arg = old_is_pos_arg;
1020
			is_pos_arg = old_is_pos_arg;
1021
#endif
1021
#endif
1022
			if (width >= 0)
1022
			if (width >= 0)
1023
				goto rflag;
1023
				goto rflag;
1024
			width = -width;
1024
			width = -width;
1025
			/* FALLTHROUGH */
1025
			/* FALLTHROUGH */
1026
		case '-':
1026
		case '-':
1027
			flags |= LADJUST;
1027
			flags |= LADJUST;
1028
			goto rflag;
1028
			goto rflag;
1029
		case '+':
1029
		case '+':
1030
			sign = '+';
1030
			sign = '+';
1031
			goto rflag;
1031
			goto rflag;
1032
		case '.':
1032
		case '.':
1033
			if ((ch = *fmt++) == '*') {
1033
			if ((ch = *fmt++) == '*') {
1034
#ifndef _NO_POS_ARGS
1034
#ifndef _NO_POS_ARGS
1035
				/* we must check for positional arg used for dynamic width */
1035
				/* we must check for positional arg used for dynamic width */
1036
				n = N;
1036
				n = N;
1037
				old_is_pos_arg = is_pos_arg;
1037
				old_is_pos_arg = is_pos_arg;
1038
				is_pos_arg = 0;
1038
				is_pos_arg = 0;
1039
				if (is_digit (*fmt)) {
1039
				if (is_digit (*fmt)) {
1040
					char *old_fmt = fmt;
1040
					char *old_fmt = fmt;
1041
 
1041
 
1042
					n = 0;
1042
					n = 0;
1043
					ch = *fmt++;
1043
					ch = *fmt++;
1044
					do {
1044
					do {
1045
						n = 10 * n + to_digit (ch);
1045
						n = 10 * n + to_digit (ch);
1046
						ch = *fmt++;
1046
						ch = *fmt++;
1047
					} while (is_digit (ch));
1047
					} while (is_digit (ch));
1048
 
1048
 
1049
					if (ch == '$') {
1049
					if (ch == '$') {
1050
						if (n <= MAX_POS_ARGS) {
1050
						if (n <= MAX_POS_ARGS) {
1051
							n -= 1;
1051
							n -= 1;
1052
							is_pos_arg = 1;
1052
							is_pos_arg = 1;
1053
						}
1053
						}
1054
						else
1054
						else
1055
							goto error;
1055
							goto error;
1056
					}
1056
					}
1057
					else {
1057
					else {
1058
						fmt = old_fmt;
1058
						fmt = old_fmt;
1059
						goto rflag;
1059
						goto rflag;
1060
					}
1060
					}
1061
				}
1061
				}
1062
#endif /* !_NO_POS_ARGS */
1062
#endif /* !_NO_POS_ARGS */
1063
				prec = GET_ARG (n, ap, int);
1063
				prec = GET_ARG (n, ap, int);
1064
#ifndef _NO_POS_ARGS
1064
#ifndef _NO_POS_ARGS
1065
				is_pos_arg = old_is_pos_arg;
1065
				is_pos_arg = old_is_pos_arg;
1066
#endif
1066
#endif
1067
				if (prec < 0)
1067
				if (prec < 0)
1068
					prec = -1;
1068
					prec = -1;
1069
				goto rflag;
1069
				goto rflag;
1070
			}
1070
			}
1071
			n = 0;
1071
			n = 0;
1072
			while (is_digit (ch)) {
1072
			while (is_digit (ch)) {
1073
				n = 10 * n + to_digit (ch);
1073
				n = 10 * n + to_digit (ch);
1074
				ch = *fmt++;
1074
				ch = *fmt++;
1075
			}
1075
			}
1076
			prec = n < 0 ? -1 : n;
1076
			prec = n < 0 ? -1 : n;
1077
			goto reswitch;
1077
			goto reswitch;
1078
		case '0':
1078
		case '0':
1079
			/*
1079
			/*
1080
			 * ``Note that 0 is taken as a flag, not as the
1080
			 * ``Note that 0 is taken as a flag, not as the
1081
			 * beginning of a field width.''
1081
			 * beginning of a field width.''
1082
			 *	-- ANSI X3J11
1082
			 *	-- ANSI X3J11
1083
			 */
1083
			 */
1084
			flags |= ZEROPAD;
1084
			flags |= ZEROPAD;
1085
			goto rflag;
1085
			goto rflag;
1086
		case '1': case '2': case '3': case '4':
1086
		case '1': case '2': case '3': case '4':
1087
		case '5': case '6': case '7': case '8': case '9':
1087
		case '5': case '6': case '7': case '8': case '9':
1088
			n = 0;
1088
			n = 0;
1089
			do {
1089
			do {
1090
				n = 10 * n + to_digit (ch);
1090
				n = 10 * n + to_digit (ch);
1091
				ch = *fmt++;
1091
				ch = *fmt++;
1092
			} while (is_digit (ch));
1092
			} while (is_digit (ch));
1093
#ifndef _NO_POS_ARGS
1093
#ifndef _NO_POS_ARGS
1094
			if (ch == '$') {
1094
			if (ch == '$') {
1095
				if (n <= MAX_POS_ARGS) {
1095
				if (n <= MAX_POS_ARGS) {
1096
					N = n - 1;
1096
					N = n - 1;
1097
					is_pos_arg = 1;
1097
					is_pos_arg = 1;
1098
					goto rflag;
1098
					goto rflag;
1099
				}
1099
				}
1100
				else
1100
				else
1101
					goto error;
1101
					goto error;
1102
			}
1102
			}
1103
#endif /* !_NO_POS_ARGS */
1103
#endif /* !_NO_POS_ARGS */
1104
			width = n;
1104
			width = n;
1105
			goto reswitch;
1105
			goto reswitch;
1106
#ifdef FLOATING_POINT
1106
#ifdef FLOATING_POINT
1107
		case 'L':
1107
		case 'L':
1108
			flags |= LONGDBL;
1108
			flags |= LONGDBL;
1109
			goto rflag;
1109
			goto rflag;
1110
#endif
1110
#endif
1111
		case 'h':
1111
		case 'h':
1112
#ifdef _WANT_IO_C99_FORMATS
1112
#ifdef _WANT_IO_C99_FORMATS
1113
			if (*fmt == 'h') {
1113
			if (*fmt == 'h') {
1114
				fmt++;
1114
				fmt++;
1115
				flags |= CHARINT;
1115
				flags |= CHARINT;
1116
			} else
1116
			} else
1117
#endif
1117
#endif
1118
				flags |= SHORTINT;
1118
				flags |= SHORTINT;
1119
			goto rflag;
1119
			goto rflag;
1120
		case 'l':
1120
		case 'l':
1121
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1121
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1122
			if (*fmt == 'l') {
1122
			if (*fmt == 'l') {
1123
				fmt++;
1123
				fmt++;
1124
				flags |= QUADINT;
1124
				flags |= QUADINT;
1125
			} else
1125
			} else
1126
#endif
1126
#endif
1127
				flags |= LONGINT;
1127
				flags |= LONGINT;
1128
			goto rflag;
1128
			goto rflag;
1129
		case 'q': /* extension */
1129
		case 'q': /* extension */
1130
			flags |= QUADINT;
1130
			flags |= QUADINT;
1131
			goto rflag;
1131
			goto rflag;
1132
#ifdef _WANT_IO_C99_FORMATS
1132
#ifdef _WANT_IO_C99_FORMATS
1133
		case 'j':
1133
		case 'j':
1134
		  if (sizeof (intmax_t) == sizeof (long))
1134
		  if (sizeof (intmax_t) == sizeof (long))
1135
		    flags |= LONGINT;
1135
		    flags |= LONGINT;
1136
		  else
1136
		  else
1137
		    flags |= QUADINT;
1137
		    flags |= QUADINT;
1138
		  goto rflag;
1138
		  goto rflag;
1139
		case 'z':
1139
		case 'z':
1140
		  if (sizeof (size_t) < sizeof (int))
1140
		  if (sizeof (size_t) < sizeof (int))
1141
		    /* POSIX states size_t is 16 or more bits, as is short.  */
1141
		    /* POSIX states size_t is 16 or more bits, as is short.  */
1142
		    flags |= SHORTINT;
1142
		    flags |= SHORTINT;
1143
		  else if (sizeof (size_t) == sizeof (int))
1143
		  else if (sizeof (size_t) == sizeof (int))
1144
		    /* no flag needed */;
1144
		    /* no flag needed */;
1145
		  else if (sizeof (size_t) <= sizeof (long))
1145
		  else if (sizeof (size_t) <= sizeof (long))
1146
		    flags |= LONGINT;
1146
		    flags |= LONGINT;
1147
		  else
1147
		  else
1148
		    /* POSIX states that at least one programming
1148
		    /* POSIX states that at least one programming
1149
		       environment must support size_t no wider than
1149
		       environment must support size_t no wider than
1150
		       long, but that means other environments can
1150
		       long, but that means other environments can
1151
		       have size_t as wide as long long.  */
1151
		       have size_t as wide as long long.  */
1152
		    flags |= QUADINT;
1152
		    flags |= QUADINT;
1153
		  goto rflag;
1153
		  goto rflag;
1154
		case 't':
1154
		case 't':
1155
		  if (sizeof (ptrdiff_t) < sizeof (int))
1155
		  if (sizeof (ptrdiff_t) < sizeof (int))
1156
		    /* POSIX states ptrdiff_t is 16 or more bits, as
1156
		    /* POSIX states ptrdiff_t is 16 or more bits, as
1157
		       is short.  */
1157
		       is short.  */
1158
		    flags |= SHORTINT;
1158
		    flags |= SHORTINT;
1159
		  else if (sizeof (ptrdiff_t) == sizeof (int))
1159
		  else if (sizeof (ptrdiff_t) == sizeof (int))
1160
		    /* no flag needed */;
1160
		    /* no flag needed */;
1161
		  else if (sizeof (ptrdiff_t) <= sizeof (long))
1161
		  else if (sizeof (ptrdiff_t) <= sizeof (long))
1162
		    flags |= LONGINT;
1162
		    flags |= LONGINT;
1163
		  else
1163
		  else
1164
		    /* POSIX states that at least one programming
1164
		    /* POSIX states that at least one programming
1165
		       environment must support ptrdiff_t no wider than
1165
		       environment must support ptrdiff_t no wider than
1166
		       long, but that means other environments can
1166
		       long, but that means other environments can
1167
		       have ptrdiff_t as wide as long long.  */
1167
		       have ptrdiff_t as wide as long long.  */
1168
		    flags |= QUADINT;
1168
		    flags |= QUADINT;
1169
		  goto rflag;
1169
		  goto rflag;
1170
		case 'C':
1170
		case 'C':
1171
#endif /* _WANT_IO_C99_FORMATS */
1171
#endif /* _WANT_IO_C99_FORMATS */
1172
		case 'c':
1172
		case 'c':
1173
			cp = buf;
1173
			cp = buf;
1174
#ifdef _MB_CAPABLE
1174
#ifdef _MB_CAPABLE
1175
			if (ch == 'C' || (flags & LONGINT)) {
1175
			if (ch == 'C' || (flags & LONGINT)) {
1176
				mbstate_t ps;
1176
				mbstate_t ps;
1177
 
1177
 
1178
				memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1178
				memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1179
				if ((size = (int)_wcrtomb_r (data, cp,
1179
				if ((size = (int)_wcrtomb_r (data, cp,
1180
					       (wchar_t)GET_ARG (N, ap, wint_t),
1180
					       (wchar_t)GET_ARG (N, ap, wint_t),
1181
						&ps)) == -1) {
1181
						&ps)) == -1) {
1182
					fp->_flags |= __SERR;
1182
					fp->_flags |= __SERR;
1183
					goto error;
1183
					goto error;
1184
				}
1184
				}
1185
			}
1185
			}
1186
			else
1186
			else
1187
#endif /* _MB_CAPABLE */
1187
#endif /* _MB_CAPABLE */
1188
			{
1188
			{
1189
				*cp = GET_ARG (N, ap, int);
1189
				*cp = GET_ARG (N, ap, int);
1190
				size = 1;
1190
				size = 1;
1191
			}
1191
			}
1192
			sign = '\0';
1192
			sign = '\0';
1193
			break;
1193
			break;
1194
		case 'D':  /* extension */
1194
		case 'D':  /* extension */
1195
			flags |= LONGINT;
1195
			flags |= LONGINT;
1196
			/*FALLTHROUGH*/
1196
			/*FALLTHROUGH*/
1197
		case 'd':
1197
		case 'd':
1198
		case 'i':
1198
		case 'i':
1199
			_uquad = SARG ();
1199
			_uquad = SARG ();
1200
#ifndef _NO_LONGLONG
1200
#ifndef _NO_LONGLONG
1201
			if ((quad_t)_uquad < 0)
1201
			if ((quad_t)_uquad < 0)
1202
#else
1202
#else
1203
			if ((long) _uquad < 0)
1203
			if ((long) _uquad < 0)
1204
#endif
1204
#endif
1205
			{
1205
			{
1206
 
1206
 
1207
				_uquad = -_uquad;
1207
				_uquad = -_uquad;
1208
				sign = '-';
1208
				sign = '-';
1209
			}
1209
			}
1210
			base = DEC;
1210
			base = DEC;
1211
			goto number;
1211
			goto number;
1212
#ifdef FLOATING_POINT
1212
#ifdef FLOATING_POINT
1213
# ifdef _WANT_IO_C99_FORMATS
1213
# ifdef _WANT_IO_C99_FORMATS
1214
		case 'a':
1214
		case 'a':
1215
		case 'A':
1215
		case 'A':
1216
		case 'F':
1216
		case 'F':
1217
# endif
1217
# endif
1218
		case 'e':
1218
		case 'e':
1219
		case 'E':
1219
		case 'E':
1220
		case 'f':
1220
		case 'f':
1221
		case 'g':
1221
		case 'g':
1222
		case 'G':
1222
		case 'G':
1223
# ifdef _NO_LONGDBL
1223
# ifdef _NO_LONGDBL
1224
			if (flags & LONGDBL) {
1224
			if (flags & LONGDBL) {
1225
				_fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
1225
				_fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
1226
			} else {
1226
			} else {
1227
				_fpvalue = GET_ARG (N, ap, double);
1227
				_fpvalue = GET_ARG (N, ap, double);
1228
			}
1228
			}
1229
 
1229
 
1230
			/* do this before tricky precision changes
1230
			/* do this before tricky precision changes
1231
 
1231
 
1232
			   If the output is infinite or NaN, leading
1232
			   If the output is infinite or NaN, leading
1233
			   zeros are not permitted.  Otherwise, scanf
1233
			   zeros are not permitted.  Otherwise, scanf
1234
			   could not read what printf wrote.
1234
			   could not read what printf wrote.
1235
			 */
1235
			 */
1236
			if (isinf (_fpvalue)) {
1236
			if (isinf (_fpvalue)) {
1237
				if (_fpvalue < 0)
1237
				if (_fpvalue < 0)
1238
					sign = '-';
1238
					sign = '-';
1239
				if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1239
				if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1240
					cp = "INF";
1240
					cp = "INF";
1241
				else
1241
				else
1242
					cp = "inf";
1242
					cp = "inf";
1243
				size = 3;
1243
				size = 3;
1244
				flags &= ~ZEROPAD;
1244
				flags &= ~ZEROPAD;
1245
				break;
1245
				break;
1246
			}
1246
			}
1247
			if (isnan (_fpvalue)) {
1247
			if (isnan (_fpvalue)) {
1248
				if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1248
				if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1249
					cp = "NAN";
1249
					cp = "NAN";
1250
				else
1250
				else
1251
					cp = "nan";
1251
					cp = "nan";
1252
				size = 3;
1252
				size = 3;
1253
				flags &= ~ZEROPAD;
1253
				flags &= ~ZEROPAD;
1254
				break;
1254
				break;
1255
			}
1255
			}
1256
 
1256
 
1257
# else /* !_NO_LONGDBL */
1257
# else /* !_NO_LONGDBL */
1258
 
1258
 
1259
			if (flags & LONGDBL) {
1259
			if (flags & LONGDBL) {
1260
				_fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
1260
				_fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
1261
			} else {
1261
			} else {
1262
				_fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
1262
				_fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
1263
			}
1263
			}
1264
 
1264
 
1265
			/* do this before tricky precision changes */
1265
			/* do this before tricky precision changes */
1266
			expt = _ldcheck (&_fpvalue);
1266
			expt = _ldcheck (&_fpvalue);
1267
			if (expt == 2) {
1267
			if (expt == 2) {
1268
				if (_fpvalue < 0)
1268
				if (_fpvalue < 0)
1269
					sign = '-';
1269
					sign = '-';
1270
				if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1270
				if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1271
					cp = "INF";
1271
					cp = "INF";
1272
				else
1272
				else
1273
					cp = "inf";
1273
					cp = "inf";
1274
				size = 3;
1274
				size = 3;
1275
				flags &= ~ZEROPAD;
1275
				flags &= ~ZEROPAD;
1276
				break;
1276
				break;
1277
			}
1277
			}
1278
			if (expt == 1) {
1278
			if (expt == 1) {
1279
				if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1279
				if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1280
					cp = "NAN";
1280
					cp = "NAN";
1281
				else
1281
				else
1282
					cp = "nan";
1282
					cp = "nan";
1283
				size = 3;
1283
				size = 3;
1284
				flags &= ~ZEROPAD;
1284
				flags &= ~ZEROPAD;
1285
				break;
1285
				break;
1286
			}
1286
			}
1287
# endif /* !_NO_LONGDBL */
1287
# endif /* !_NO_LONGDBL */
1288
 
1288
 
1289
# ifdef _WANT_IO_C99_FORMATS
1289
# ifdef _WANT_IO_C99_FORMATS
1290
			if (ch == 'a' || ch == 'A') {
1290
			if (ch == 'a' || ch == 'A') {
1291
				ox[0] = '0';
1291
				ox[0] = '0';
1292
				ox[1] = ch == 'a' ? 'x' : 'X';
1292
				ox[1] = ch == 'a' ? 'x' : 'X';
1293
				flags |= HEXPREFIX;
1293
				flags |= HEXPREFIX;
1294
				if (prec >= BUF)
1294
				if (prec >= BUF)
1295
				  {
1295
				  {
1296
				    if ((malloc_buf =
1296
				    if ((malloc_buf =
1297
					 (char *)_malloc_r (data, prec + 1))
1297
					 (char *)_malloc_r (data, prec + 1))
1298
					== NULL)
1298
					== NULL)
1299
				      {
1299
				      {
1300
					fp->_flags |= __SERR;
1300
					fp->_flags |= __SERR;
1301
					goto error;
1301
					goto error;
1302
				      }
1302
				      }
1303
				    cp = malloc_buf;
1303
				    cp = malloc_buf;
1304
				  }
1304
				  }
1305
				else
1305
				else
1306
				  cp = buf;
1306
				  cp = buf;
1307
			} else
1307
			} else
1308
# endif /* _WANT_IO_C99_FORMATS */
1308
# endif /* _WANT_IO_C99_FORMATS */
1309
			if (prec == -1) {
1309
			if (prec == -1) {
1310
				prec = DEFPREC;
1310
				prec = DEFPREC;
1311
			} else if ((ch == 'g' || ch == 'G') && prec == 0) {
1311
			} else if ((ch == 'g' || ch == 'G') && prec == 0) {
1312
				prec = 1;
1312
				prec = 1;
1313
			}
1313
			}
1314
 
1314
 
1315
			flags |= FPT;
1315
			flags |= FPT;
1316
 
1316
 
1317
			cp = cvt (data, _fpvalue, prec, flags, &softsign,
1317
			cp = cvt (data, _fpvalue, prec, flags, &softsign,
1318
				  &expt, ch, &ndig, cp);
1318
				  &expt, ch, &ndig, cp);
1319
 
1319
 
1320
			if (ch == 'g' || ch == 'G') {
1320
			if (ch == 'g' || ch == 'G') {
1321
				if (expt <= -4 || expt > prec)
1321
				if (expt <= -4 || expt > prec)
1322
					ch -= 2; /* 'e' or 'E' */
1322
					ch -= 2; /* 'e' or 'E' */
1323
				else
1323
				else
1324
					ch = 'g';
1324
					ch = 'g';
1325
			}
1325
			}
1326
# ifdef _WANT_IO_C99_FORMATS
1326
# ifdef _WANT_IO_C99_FORMATS
1327
			else if (ch == 'F')
1327
			else if (ch == 'F')
1328
				ch = 'f';
1328
				ch = 'f';
1329
# endif
1329
# endif
1330
			if (ch <= 'e') {	/* 'a', 'A', 'e', or 'E' fmt */
1330
			if (ch <= 'e') {	/* 'a', 'A', 'e', or 'E' fmt */
1331
				--expt;
1331
				--expt;
1332
				expsize = exponent (expstr, expt, ch);
1332
				expsize = exponent (expstr, expt, ch);
1333
				size = expsize + ndig;
1333
				size = expsize + ndig;
1334
				if (ndig > 1 || flags & ALT)
1334
				if (ndig > 1 || flags & ALT)
1335
					++size;
1335
					++size;
1336
# ifdef _WANT_IO_C99_FORMATS
1336
# ifdef _WANT_IO_C99_FORMATS
1337
				flags &= ~GROUPING;
1337
				flags &= ~GROUPING;
1338
# endif
1338
# endif
1339
			} else {
1339
			} else {
1340
				if (ch == 'f') {		/* f fmt */
1340
				if (ch == 'f') {		/* f fmt */
1341
				if (expt > 0) {
1341
					if (expt > 0) {
-
 
1342
						size = expt;
-
 
1343
						if (prec || flags & ALT)
-
 
1344
							size += prec + 1;
-
 
1345
					} else	/* "0.X" */
-
 
1346
						size = (prec || flags & ALT)
-
 
1347
							  ? prec + 2
-
 
1348
							  : 1;
-
 
1349
				} else if (expt >= ndig) { /* fixed g fmt */
1342
					size = expt;
1350
					size = expt;
1343
					if (prec || flags & ALT)
-
 
1344
						size += prec + 1;
-
 
1345
				} else	/* "0.X" */
-
 
1346
					size = (prec || flags & ALT)
-
 
1347
						  ? prec + 2
-
 
1348
						  : 1;
-
 
1349
			} else if (expt >= ndig) {	/* fixed g fmt */
-
 
1350
				size = expt;
-
 
1351
				if (flags & ALT)
1351
					if (flags & ALT)
1352
					++size;
1352
						++size;
1353
			} else
1353
				} else
1354
				size = ndig + (expt > 0 ?
1354
					size = ndig + (expt > 0 ?
1355
					1 : 2 - expt);
1355
						1 : 2 - expt);
1356
# ifdef _WANT_IO_C99_FORMATS
1356
# ifdef _WANT_IO_C99_FORMATS
1357
				if ((flags & GROUPING) && expt > 0) {
1357
				if ((flags & GROUPING) && expt > 0) {
1358
					/* space for thousands' grouping */
1358
					/* space for thousands' grouping */
1359
					nseps = nrepeats = 0;
1359
					nseps = nrepeats = 0;
1360
					lead = expt;
1360
					lead = expt;
1361
					while (*grouping != CHAR_MAX) {
1361
					while (*grouping != CHAR_MAX) {
1362
						if (lead <= *grouping)
1362
						if (lead <= *grouping)
1363
							break;
1363
							break;
1364
						lead -= *grouping;
1364
						lead -= *grouping;
1365
						if (grouping[1]) {
1365
						if (grouping[1]) {
1366
							nseps++;
1366
							nseps++;
1367
							grouping++;
1367
							grouping++;
1368
						} else
1368
						} else
1369
							nrepeats++;
1369
							nrepeats++;
1370
					}
1370
					}
1371
					size += (nseps + nrepeats) * thsnd_len;
1371
					size += (nseps + nrepeats) * thsnd_len;
1372
				} else
1372
				} else
1373
# endif
1373
# endif
1374
					lead = expt;
1374
					lead = expt;
1375
			}
1375
			}
1376
 
1376
 
1377
			if (softsign)
1377
			if (softsign)
1378
				sign = '-';
1378
				sign = '-';
1379
			break;
1379
			break;
1380
#endif /* FLOATING_POINT */
1380
#endif /* FLOATING_POINT */
1381
#ifdef _GLIBC_EXTENSION
1381
#ifdef _GLIBC_EXTENSION
1382
		case 'm':  /* extension */
1382
		case 'm':  /* extension */
1383
			{
1383
			{
1384
				int dummy;
1384
				int dummy;
1385
				cp = _strerror_r (data, data->_errno, 1, &dummy);
1385
				cp = _strerror_r (data, data->_errno, 1, &dummy);
1386
			}
1386
			}
1387
			flags &= ~LONGINT;
1387
			flags &= ~LONGINT;
1388
			goto string;
1388
			goto string;
1389
#endif
1389
#endif
1390
		case 'n':
1390
		case 'n':
1391
#ifndef _NO_LONGLONG
1391
#ifndef _NO_LONGLONG
1392
			if (flags & QUADINT)
1392
			if (flags & QUADINT)
1393
				*GET_ARG (N, ap, quad_ptr_t) = ret;
1393
				*GET_ARG (N, ap, quad_ptr_t) = ret;
1394
			else
1394
			else
1395
#endif
1395
#endif
1396
			if (flags & LONGINT)
1396
			if (flags & LONGINT)
1397
				*GET_ARG (N, ap, long_ptr_t) = ret;
1397
				*GET_ARG (N, ap, long_ptr_t) = ret;
1398
			else if (flags & SHORTINT)
1398
			else if (flags & SHORTINT)
1399
				*GET_ARG (N, ap, short_ptr_t) = ret;
1399
				*GET_ARG (N, ap, short_ptr_t) = ret;
1400
#ifdef _WANT_IO_C99_FORMATS
1400
#ifdef _WANT_IO_C99_FORMATS
1401
			else if (flags & CHARINT)
1401
			else if (flags & CHARINT)
1402
				*GET_ARG (N, ap, char_ptr_t) = ret;
1402
				*GET_ARG (N, ap, char_ptr_t) = ret;
1403
#endif
1403
#endif
1404
			else
1404
			else
1405
				*GET_ARG (N, ap, int_ptr_t) = ret;
1405
				*GET_ARG (N, ap, int_ptr_t) = ret;
1406
			continue;	/* no output */
1406
			continue;	/* no output */
1407
		case 'O': /* extension */
1407
		case 'O': /* extension */
1408
			flags |= LONGINT;
1408
			flags |= LONGINT;
1409
			/*FALLTHROUGH*/
1409
			/*FALLTHROUGH*/
1410
		case 'o':
1410
		case 'o':
1411
			_uquad = UARG ();
1411
			_uquad = UARG ();
1412
			base = OCT;
1412
			base = OCT;
1413
#ifdef _WANT_IO_C99_FORMATS
1413
#ifdef _WANT_IO_C99_FORMATS
1414
			flags &= ~GROUPING;
1414
			flags &= ~GROUPING;
1415
#endif
1415
#endif
1416
			goto nosign;
1416
			goto nosign;
1417
		case 'p':
1417
		case 'p':
1418
			/*
1418
			/*
1419
			 * ``The argument shall be a pointer to void.  The
1419
			 * ``The argument shall be a pointer to void.  The
1420
			 * value of the pointer is converted to a sequence
1420
			 * value of the pointer is converted to a sequence
1421
			 * of printable characters, in an implementation-
1421
			 * of printable characters, in an implementation-
1422
			 * defined manner.''
1422
			 * defined manner.''
1423
			 *	-- ANSI X3J11
1423
			 *	-- ANSI X3J11
1424
			 */
1424
			 */
1425
			/* NOSTRICT */
1425
			/* NOSTRICT */
1426
			_uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
1426
			_uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
1427
			base = HEX;
1427
			base = HEX;
1428
			xdigs = "0123456789abcdef";
1428
			xdigs = "0123456789abcdef";
1429
			flags |= HEXPREFIX;
1429
			flags |= HEXPREFIX;
1430
			ox[0] = '0';
1430
			ox[0] = '0';
1431
			ox[1] = ch = 'x';
1431
			ox[1] = ch = 'x';
1432
			goto nosign;
1432
			goto nosign;
1433
		case 's':
1433
		case 's':
1434
#ifdef _WANT_IO_C99_FORMATS
1434
#ifdef _WANT_IO_C99_FORMATS
1435
		case 'S':
1435
		case 'S':
1436
#endif
1436
#endif
1437
			cp = GET_ARG (N, ap, char_ptr_t);
1437
			cp = GET_ARG (N, ap, char_ptr_t);
1438
#ifdef _GLIBC_EXTENSION
1438
#ifdef _GLIBC_EXTENSION
1439
string:
1439
string:
1440
#endif
1440
#endif
1441
			sign = '\0';
1441
			sign = '\0';
1442
#ifndef __OPTIMIZE_SIZE__
1442
#ifndef __OPTIMIZE_SIZE__
1443
			/* Behavior is undefined if the user passed a
1443
			/* Behavior is undefined if the user passed a
1444
			   NULL string when precision is not 0.
1444
			   NULL string when precision is not 0.
1445
			   However, if we are not optimizing for size,
1445
			   However, if we are not optimizing for size,
1446
			   we might as well mirror glibc behavior.  */
1446
			   we might as well mirror glibc behavior.  */
1447
			if (cp == NULL) {
1447
			if (cp == NULL) {
1448
				cp = "(null)";
1448
				cp = "(null)";
1449
				size = ((unsigned) prec > 6U) ? 6 : prec;
1449
				size = ((unsigned) prec > 6U) ? 6 : prec;
1450
			}
1450
			}
1451
			else
1451
			else
1452
#endif /* __OPTIMIZE_SIZE__ */
1452
#endif /* __OPTIMIZE_SIZE__ */
1453
#ifdef _MB_CAPABLE
1453
#ifdef _MB_CAPABLE
1454
			if (ch == 'S' || (flags & LONGINT)) {
1454
			if (ch == 'S' || (flags & LONGINT)) {
1455
				mbstate_t ps;
1455
				mbstate_t ps;
1456
				_CONST wchar_t *wcp;
1456
				_CONST wchar_t *wcp;
1457
 
1457
 
1458
				wcp = (_CONST wchar_t *)cp;
1458
				wcp = (_CONST wchar_t *)cp;
1459
				size = m = 0;
1459
				size = m = 0;
1460
				memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1460
				memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1461
 
1461
 
1462
				/* Count number of bytes needed for multibyte
1462
				/* Count number of bytes needed for multibyte
1463
				   string that will be produced from widechar
1463
				   string that will be produced from widechar
1464
				   string.  */
1464
				   string.  */
1465
				if (prec >= 0) {
1465
				if (prec >= 0) {
1466
					while (1) {
1466
					while (1) {
1467
						if (wcp[m] == L'\0')
1467
						if (wcp[m] == L'\0')
1468
							break;
1468
							break;
1469
						if ((n = (int)_wcrtomb_r (data,
1469
						if ((n = (int)_wcrtomb_r (data,
1470
						     buf, wcp[m], &ps)) == -1) {
1470
						     buf, wcp[m], &ps)) == -1) {
1471
							fp->_flags |= __SERR;
1471
							fp->_flags |= __SERR;
1472
							goto error;
1472
							goto error;
1473
						}
1473
						}
1474
						if (n + size > prec)
1474
						if (n + size > prec)
1475
							break;
1475
							break;
1476
						m += 1;
1476
						m += 1;
1477
						size += n;
1477
						size += n;
1478
						if (size == prec)
1478
						if (size == prec)
1479
							break;
1479
							break;
1480
					}
1480
					}
1481
				}
1481
				}
1482
				else {
1482
				else {
1483
					if ((size = (int)_wcsrtombs_r (data,
1483
					if ((size = (int)_wcsrtombs_r (data,
1484
						   NULL, &wcp, 0, &ps)) == -1) {
1484
						   NULL, &wcp, 0, &ps)) == -1) {
1485
						fp->_flags |= __SERR;
1485
						fp->_flags |= __SERR;
1486
						goto error;
1486
						goto error;
1487
					}
1487
					}
1488
					wcp = (_CONST wchar_t *)cp;
1488
					wcp = (_CONST wchar_t *)cp;
1489
				}
1489
				}
1490
 
1490
 
1491
				if (size == 0)
1491
				if (size == 0)
1492
					break;
1492
					break;
1493
 
1493
 
1494
				if (size >= BUF) {
1494
				if (size >= BUF) {
1495
					if ((malloc_buf =
1495
					if ((malloc_buf =
1496
					     (char *)_malloc_r (data, size + 1))
1496
					     (char *)_malloc_r (data, size + 1))
1497
					    == NULL) {
1497
					    == NULL) {
1498
						fp->_flags |= __SERR;
1498
						fp->_flags |= __SERR;
1499
						goto error;
1499
						goto error;
1500
					}
1500
					}
1501
					cp = malloc_buf;
1501
					cp = malloc_buf;
1502
				} else
1502
				} else
1503
					cp = buf;
1503
					cp = buf;
1504
 
1504
 
1505
				/* Convert widechar string to multibyte string. */
1505
				/* Convert widechar string to multibyte string. */
1506
				memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1506
				memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1507
				if (_wcsrtombs_r (data, cp, &wcp, size, &ps)
1507
				if (_wcsrtombs_r (data, cp, &wcp, size, &ps)
1508
				    != size) {
1508
				    != size) {
1509
					fp->_flags |= __SERR;
1509
					fp->_flags |= __SERR;
1510
					goto error;
1510
					goto error;
1511
				}
1511
				}
1512
				cp[size] = '\0';
1512
				cp[size] = '\0';
1513
			}
1513
			}
1514
			else
1514
			else
1515
#endif /* _MB_CAPABLE */
1515
#endif /* _MB_CAPABLE */
1516
			if (prec >= 0) {
1516
			if (prec >= 0) {
1517
				/*
1517
				/*
1518
				 * can't use strlen; can only look for the
1518
				 * can't use strlen; can only look for the
1519
				 * NUL in the first `prec' characters, and
1519
				 * NUL in the first `prec' characters, and
1520
				 * strlen () will go further.
1520
				 * strlen () will go further.
1521
				 */
1521
				 */
1522
				char *p = memchr (cp, 0, prec);
1522
				char *p = memchr (cp, 0, prec);
1523
 
1523
 
1524
				if (p != NULL) {
1524
				if (p != NULL)
1525
					size = p - cp;
-
 
1526
					if (size > prec)
-
 
1527
						size = prec;
1525
					size = p - cp;
1528
				} else
1526
				else
1529
					size = prec;
1527
					size = prec;
1530
			} else
1528
			} else
1531
				size = strlen (cp);
1529
				size = strlen (cp);
1532
 
1530
 
1533
			break;
1531
			break;
1534
		case 'U': /* extension */
1532
		case 'U': /* extension */
1535
			flags |= LONGINT;
1533
			flags |= LONGINT;
1536
			/*FALLTHROUGH*/
1534
			/*FALLTHROUGH*/
1537
		case 'u':
1535
		case 'u':
1538
			_uquad = UARG ();
1536
			_uquad = UARG ();
1539
			base = DEC;
1537
			base = DEC;
1540
			goto nosign;
1538
			goto nosign;
1541
		case 'X':
1539
		case 'X':
1542
			xdigs = "0123456789ABCDEF";
1540
			xdigs = "0123456789ABCDEF";
1543
			goto hex;
1541
			goto hex;
1544
		case 'x':
1542
		case 'x':
1545
			xdigs = "0123456789abcdef";
1543
			xdigs = "0123456789abcdef";
1546
hex:			_uquad = UARG ();
1544
hex:			_uquad = UARG ();
1547
			base = HEX;
1545
			base = HEX;
1548
			/* leading 0x/X only if non-zero */
1546
			/* leading 0x/X only if non-zero */
1549
			if (flags & ALT && _uquad != 0) {
1547
			if (flags & ALT && _uquad != 0) {
1550
				ox[0] = '0';
1548
				ox[0] = '0';
1551
				ox[1] = ch;
1549
				ox[1] = ch;
1552
				flags |= HEXPREFIX;
1550
				flags |= HEXPREFIX;
1553
			}
1551
			}
1554
 
1552
 
1555
#ifdef _WANT_IO_C99_FORMATS
1553
#ifdef _WANT_IO_C99_FORMATS
1556
			flags &= ~GROUPING;
1554
			flags &= ~GROUPING;
1557
#endif
1555
#endif
1558
			/* unsigned conversions */
1556
			/* unsigned conversions */
1559
nosign:			sign = '\0';
1557
nosign:			sign = '\0';
1560
			/*
1558
			/*
1561
			 * ``... diouXx conversions ... if a precision is
1559
			 * ``... diouXx conversions ... if a precision is
1562
			 * specified, the 0 flag will be ignored.''
1560
			 * specified, the 0 flag will be ignored.''
1563
			 *	-- ANSI X3J11
1561
			 *	-- ANSI X3J11
1564
			 */
1562
			 */
1565
number:			if ((dprec = prec) >= 0)
1563
number:			if ((dprec = prec) >= 0)
1566
				flags &= ~ZEROPAD;
1564
				flags &= ~ZEROPAD;
1567
 
1565
 
1568
			/*
1566
			/*
1569
			 * ``The result of converting a zero value with an
1567
			 * ``The result of converting a zero value with an
1570
			 * explicit precision of zero is no characters.''
1568
			 * explicit precision of zero is no characters.''
1571
			 *	-- ANSI X3J11
1569
			 *	-- ANSI X3J11
1572
			 */
1570
			 */
1573
			cp = buf + BUF;
1571
			cp = buf + BUF;
1574
			if (_uquad != 0 || prec != 0) {
1572
			if (_uquad != 0 || prec != 0) {
1575
				/*
1573
				/*
1576
				 * Unsigned mod is hard, and unsigned mod
1574
				 * Unsigned mod is hard, and unsigned mod
1577
				 * by a constant is easier than that by
1575
				 * by a constant is easier than that by
1578
				 * a variable; hence this switch.
1576
				 * a variable; hence this switch.
1579
				 */
1577
				 */
1580
				switch (base) {
1578
				switch (base) {
1581
				case OCT:
1579
				case OCT:
1582
					do {
1580
					do {
1583
						*--cp = to_char (_uquad & 7);
1581
						*--cp = to_char (_uquad & 7);
1584
						_uquad >>= 3;
1582
						_uquad >>= 3;
1585
					} while (_uquad);
1583
					} while (_uquad);
1586
					/* handle octal leading 0 */
1584
					/* handle octal leading 0 */
1587
					if (flags & ALT && *cp != '0')
1585
					if (flags & ALT && *cp != '0')
1588
						*--cp = '0';
1586
						*--cp = '0';
1589
					break;
1587
					break;
1590
 
1588
 
1591
				case DEC:
1589
				case DEC:
1592
					/* many numbers are 1 digit */
1590
					/* many numbers are 1 digit */
1593
					if (_uquad < 10) {
1591
					if (_uquad < 10) {
1594
						*--cp = to_char(_uquad);
1592
						*--cp = to_char(_uquad);
1595
						break;
1593
						break;
1596
					}
1594
					}
1597
#ifdef _WANT_IO_C99_FORMATS
1595
#ifdef _WANT_IO_C99_FORMATS
1598
					ndig = 0;
1596
					ndig = 0;
1599
#endif
1597
#endif
1600
					do {
1598
					do {
1601
						*--cp = to_char (_uquad % 10);
1599
					  *--cp = to_char (_uquad % 10);
1602
#ifdef _WANT_IO_C99_FORMATS
1600
#ifdef _WANT_IO_C99_FORMATS
1603
					  ndig++;
1601
					  ndig++;
1604
					  /* If (*grouping == CHAR_MAX) then no
1602
					  /* If (*grouping == CHAR_MAX) then no
1605
					     more grouping */
1603
					     more grouping */
1606
					  if ((flags & GROUPING)
1604
					  if ((flags & GROUPING)
1607
					      && ndig == *grouping
1605
					      && ndig == *grouping
1608
					      && *grouping != CHAR_MAX
1606
					      && *grouping != CHAR_MAX
1609
					      && _uquad > 9) {
1607
					      && _uquad > 9) {
1610
					    cp -= thsnd_len;
1608
					    cp -= thsnd_len;
1611
					    strncpy (cp, thousands_sep,
1609
					    strncpy (cp, thousands_sep,
1612
						     thsnd_len);
1610
						     thsnd_len);
1613
					    ndig = 0;
1611
					    ndig = 0;
1614
					    /* If (grouping[1] == '\0') then we
1612
					    /* If (grouping[1] == '\0') then we
1615
					       have to use *grouping character
1613
					       have to use *grouping character
1616
					       (last grouping rule) for all
1614
					       (last grouping rule) for all
1617
					       next cases. */
1615
					       next cases. */
1618
					    if (grouping[1] != '\0')
1616
					    if (grouping[1] != '\0')
1619
					      grouping++;
1617
					      grouping++;
1620
					  }
1618
					  }
1621
#endif
1619
#endif
1622
						_uquad /= 10;
1620
					  _uquad /= 10;
1623
					} while (_uquad != 0);
1621
					} while (_uquad != 0);
1624
					break;
1622
					break;
1625
 
1623
 
1626
				case HEX:
1624
				case HEX:
1627
					do {
1625
					do {
1628
						*--cp = xdigs[_uquad & 15];
1626
						*--cp = xdigs[_uquad & 15];
1629
						_uquad >>= 4;
1627
						_uquad >>= 4;
1630
					} while (_uquad);
1628
					} while (_uquad);
1631
					break;
1629
					break;
1632
 
1630
 
1633
				default:
1631
				default:
1634
					cp = "bug in vfprintf: bad base";
1632
					cp = "bug in vfprintf: bad base";
1635
					size = strlen (cp);
1633
					size = strlen (cp);
1636
					goto skipsize;
1634
					goto skipsize;
1637
				}
1635
				}
1638
			}
1636
			}
1639
                       /*
1637
                       /*
1640
			* ...result is to be converted to an 'alternate form'.
1638
			* ...result is to be converted to an 'alternate form'.
1641
			* For o conversion, it increases the precision to force
1639
			* For o conversion, it increases the precision to force
1642
			* the first digit of the result to be a zero."
1640
			* the first digit of the result to be a zero."
1643
			*     -- ANSI X3J11
1641
			*     -- ANSI X3J11
1644
			*
1642
			*
1645
			* To demonstrate this case, compile and run:
1643
			* To demonstrate this case, compile and run:
1646
                        *    printf ("%#.0o",0);
1644
                        *    printf ("%#.0o",0);
1647
			*/
1645
			*/
1648
                       else if (base == OCT && (flags & ALT))
1646
                       else if (base == OCT && (flags & ALT))
1649
                         *--cp = '0';
1647
                         *--cp = '0';
1650
 
1648
 
1651
			size = buf + BUF - cp;
1649
			size = buf + BUF - cp;
1652
		skipsize:
1650
		skipsize:
1653
			break;
1651
			break;
1654
		default:	/* "%?" prints ?, unless ? is NUL */
1652
		default:	/* "%?" prints ?, unless ? is NUL */
1655
			if (ch == '\0')
1653
			if (ch == '\0')
1656
				goto done;
1654
				goto done;
1657
			/* pretend it was %c with argument ch */
1655
			/* pretend it was %c with argument ch */
1658
			cp = buf;
1656
			cp = buf;
1659
			*cp = ch;
1657
			*cp = ch;
1660
			size = 1;
1658
			size = 1;
1661
			sign = '\0';
1659
			sign = '\0';
1662
			break;
1660
			break;
1663
		}
1661
		}
1664
 
1662
 
1665
		/*
1663
		/*
1666
		 * All reasonable formats wind up here.  At this point, `cp'
1664
		 * All reasonable formats wind up here.  At this point, `cp'
1667
		 * points to a string which (if not flags&LADJUST) should be
1665
		 * points to a string which (if not flags&LADJUST) should be
1668
		 * padded out to `width' places.  If flags&ZEROPAD, it should
1666
		 * padded out to `width' places.  If flags&ZEROPAD, it should
1669
		 * first be prefixed by any sign or other prefix; otherwise,
1667
		 * first be prefixed by any sign or other prefix; otherwise,
1670
		 * it should be blank padded before the prefix is emitted.
1668
		 * it should be blank padded before the prefix is emitted.
1671
		 * After any left-hand padding and prefixing, emit zeroes
1669
		 * After any left-hand padding and prefixing, emit zeroes
1672
		 * required by a decimal [diouxX] precision, then print the
1670
		 * required by a decimal [diouxX] precision, then print the
1673
		 * string proper, then emit zeroes required by any leftover
1671
		 * string proper, then emit zeroes required by any leftover
1674
		 * floating precision; finally, if LADJUST, pad with blanks.
1672
		 * floating precision; finally, if LADJUST, pad with blanks.
1675
		 * If flags&FPT, ch must be in [aAeEfg].
1673
		 * If flags&FPT, ch must be in [aAeEfg].
1676
		 *
1674
		 *
1677
		 * Compute actual size, so we know how much to pad.
1675
		 * Compute actual size, so we know how much to pad.
1678
		 * size excludes decimal prec; realsz includes it.
1676
		 * size excludes decimal prec; realsz includes it.
1679
		 */
1677
		 */
1680
		realsz = dprec > size ? dprec : size;
1678
		realsz = dprec > size ? dprec : size;
1681
		if (sign)
1679
		if (sign)
1682
			realsz++;
1680
			realsz++;
1683
		if (flags & HEXPREFIX)
1681
		if (flags & HEXPREFIX)
1684
			realsz+= 2;
1682
			realsz+= 2;
1685
 
1683
 
1686
		/* right-adjusting blank padding */
1684
		/* right-adjusting blank padding */
1687
		if ((flags & (LADJUST|ZEROPAD)) == 0)
1685
		if ((flags & (LADJUST|ZEROPAD)) == 0)
1688
			PAD (width - realsz, blanks);
1686
			PAD (width - realsz, blanks);
1689
 
1687
 
1690
		/* prefix */
1688
		/* prefix */
1691
		if (sign)
1689
		if (sign)
1692
			PRINT (&sign, 1);
1690
			PRINT (&sign, 1);
1693
		if (flags & HEXPREFIX)
1691
		if (flags & HEXPREFIX)
1694
			PRINT (ox, 2);
1692
			PRINT (ox, 2);
1695
 
1693
 
1696
		/* right-adjusting zero padding */
1694
		/* right-adjusting zero padding */
1697
		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1695
		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1698
			PAD (width - realsz, zeroes);
1696
			PAD (width - realsz, zeroes);
1699
 
1697
 
1700
		/* leading zeroes from decimal precision */
1698
		/* leading zeroes from decimal precision */
1701
		PAD (dprec - size, zeroes);
1699
		PAD (dprec - size, zeroes);
1702
 
1700
 
1703
		/* the string or number proper */
1701
		/* the string or number proper */
1704
#ifdef FLOATING_POINT
1702
#ifdef FLOATING_POINT
1705
		if ((flags & FPT) == 0) {
1703
		if ((flags & FPT) == 0) {
1706
			PRINT (cp, size);
1704
			PRINT (cp, size);
1707
		} else {	/* glue together f_p fragments */
1705
		} else {	/* glue together f_p fragments */
1708
			if (ch >= 'f') {	/* 'f' or 'g' */
1706
			if (ch >= 'f') {	/* 'f' or 'g' */
1709
				if (_fpvalue == 0) {
1707
				if (_fpvalue == 0) {
1710
					/* kludge for __dtoa irregularity */
1708
					/* kludge for __dtoa irregularity */
1711
					PRINT ("0", 1);
1709
					PRINT ("0", 1);
1712
					if (expt < ndig || flags & ALT) {
1710
					if (expt < ndig || flags & ALT) {
1713
						PRINT (decimal_point, decp_len);
1711
						PRINT (decimal_point, decp_len);
1714
						PAD (ndig - 1, zeroes);
1712
						PAD (ndig - 1, zeroes);
1715
					}
1713
					}
1716
				} else if (expt <= 0) {
1714
				} else if (expt <= 0) {
1717
					PRINT ("0", 1);
1715
					PRINT ("0", 1);
1718
					if (expt || ndig || flags & ALT) {
1716
					if (expt || ndig || flags & ALT) {
1719
						PRINT (decimal_point, decp_len);
1717
						PRINT (decimal_point, decp_len);
1720
						PAD (-expt, zeroes);
1718
						PAD (-expt, zeroes);
1721
						PRINT (cp, ndig);
1719
						PRINT (cp, ndig);
1722
					}
1720
					}
1723
				} else {
1721
				} else {
1724
					char *convbuf = cp;
1722
					char *convbuf = cp;
1725
					PRINTANDPAD(cp, convbuf + ndig,
1723
					PRINTANDPAD(cp, convbuf + ndig,
1726
						    lead, zeroes);
1724
						    lead, zeroes);
1727
					cp += lead;
1725
					cp += lead;
1728
#ifdef _WANT_IO_C99_FORMATS
1726
#ifdef _WANT_IO_C99_FORMATS
1729
					if (flags & GROUPING) {
1727
					if (flags & GROUPING) {
1730
					    while (nseps > 0 || nrepeats > 0) {
1728
					    while (nseps > 0 || nrepeats > 0) {
1731
						if (nrepeats > 0)
1729
						if (nrepeats > 0)
1732
						    nrepeats--;
1730
						    nrepeats--;
1733
						else {
1731
						else {
1734
						    grouping--;
1732
						    grouping--;
1735
						    nseps--;
1733
						    nseps--;
1736
						}
1734
						}
1737
						PRINT(thousands_sep, thsnd_len);
1735
						PRINT(thousands_sep, thsnd_len);
1738
						PRINTANDPAD (cp, convbuf + ndig,
1736
						PRINTANDPAD (cp, convbuf + ndig,
1739
							     *grouping, zeroes);
1737
							     *grouping, zeroes);
1740
						cp += *grouping;
1738
						cp += *grouping;
1741
					    }
1739
					    }
1742
					    if (cp > convbuf + ndig)
1740
					    if (cp > convbuf + ndig)
1743
						cp = convbuf + ndig;
1741
						cp = convbuf + ndig;
1744
					}
1742
					}
1745
#endif
1743
#endif
1746
					if (expt < ndig || flags & ALT)
1744
					if (expt < ndig || flags & ALT)
1747
					PRINT (decimal_point, decp_len);
1745
					    PRINT (decimal_point, decp_len);
1748
					PRINTANDPAD (cp, convbuf + ndig,
1746
					PRINTANDPAD (cp, convbuf + ndig,
1749
						     ndig - expt, zeroes);
1747
						     ndig - expt, zeroes);
1750
				}
1748
				}
1751
			} else {	/* 'a', 'A', 'e', or 'E' */
1749
			} else {	/* 'a', 'A', 'e', or 'E' */
1752
				if (ndig > 1 || flags & ALT) {
1750
				if (ndig > 1 || flags & ALT) {
1753
					PRINT (cp, 1);
1751
					PRINT (cp, 1);
1754
					cp++;
1752
					cp++;
1755
					PRINT (decimal_point, decp_len);
1753
					PRINT (decimal_point, decp_len);
1756
					if (_fpvalue) {
1754
					if (_fpvalue) {
1757
						PRINT (cp, ndig - 1);
1755
						PRINT (cp, ndig - 1);
1758
					} else	/* 0.[0..] */
1756
					} else	/* 0.[0..] */
1759
						/* __dtoa irregularity */
1757
						/* __dtoa irregularity */
1760
						PAD (ndig - 1, zeroes);
1758
						PAD (ndig - 1, zeroes);
1761
				} else	/* XeYYY */
1759
				} else	/* XeYYY */
1762
					PRINT (cp, 1);
1760
					PRINT (cp, 1);
1763
				PRINT (expstr, expsize);
1761
				PRINT (expstr, expsize);
1764
			}
1762
			}
1765
		}
1763
		}
1766
#else /* !FLOATING_POINT */
1764
#else /* !FLOATING_POINT */
1767
		PRINT (cp, size);
1765
		PRINT (cp, size);
1768
#endif
1766
#endif
1769
		/* left-adjusting padding (always blank) */
1767
		/* left-adjusting padding (always blank) */
1770
		if (flags & LADJUST)
1768
		if (flags & LADJUST)
1771
			PAD (width - realsz, blanks);
1769
			PAD (width - realsz, blanks);
1772
 
1770
 
1773
		/* finally, adjust ret */
1771
		/* finally, adjust ret */
1774
		ret += width > realsz ? width : realsz;
1772
		ret += width > realsz ? width : realsz;
1775
 
1773
 
1776
		FLUSH ();	/* copy out the I/O vectors */
1774
		FLUSH ();	/* copy out the I/O vectors */
1777
 
1775
 
1778
                if (malloc_buf != NULL) {
1776
                if (malloc_buf != NULL) {
1779
			_free_r (data, malloc_buf);
1777
			_free_r (data, malloc_buf);
1780
			malloc_buf = NULL;
1778
			malloc_buf = NULL;
1781
		}
1779
		}
1782
	}
1780
	}
1783
done:
1781
done:
1784
	FLUSH ();
1782
	FLUSH ();
1785
error:
1783
error:
1786
	if (malloc_buf != NULL)
1784
	if (malloc_buf != NULL)
1787
		_free_r (data, malloc_buf);
1785
		_free_r (data, malloc_buf);
1788
#ifndef STRING_ONLY
1786
#ifndef STRING_ONLY
1789
	_newlib_flockfile_end (fp);
1787
	_newlib_flockfile_end (fp);
1790
#endif
1788
#endif
1791
	return (__sferror (fp) ? EOF : ret);
1789
	return (__sferror (fp) ? EOF : ret);
1792
	/* NOTREACHED */
1790
	/* NOTREACHED */
1793
}
1791
}
1794
 
1792
 
1795
#ifdef FLOATING_POINT
1793
#ifdef FLOATING_POINT
1796
 
1794
 
1797
/* Using reentrant DATA, convert finite VALUE into a string of digits
1795
/* Using reentrant DATA, convert finite VALUE into a string of digits
1798
   with no decimal point, using NDIGITS precision and FLAGS as guides
1796
   with no decimal point, using NDIGITS precision and FLAGS as guides
1799
   to whether trailing zeros must be included.  Set *SIGN to nonzero
1797
   to whether trailing zeros must be included.  Set *SIGN to nonzero
1800
   if VALUE was negative.  Set *DECPT to the exponent plus one.  Set
1798
   if VALUE was negative.  Set *DECPT to the exponent plus one.  Set
1801
   *LENGTH to the length of the returned string.  CH must be one of
1799
   *LENGTH to the length of the returned string.  CH must be one of
1802
   [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1800
   [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1803
   otherwise the return value shares the mprec reentrant storage.  */
1801
   otherwise the return value shares the mprec reentrant storage.  */
1804
static char *
1802
static char *
1805
cvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1803
cvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1806
    char *sign, int *decpt, int ch, int *length, char *buf)
1804
    char *sign, int *decpt, int ch, int *length, char *buf)
1807
{
1805
{
1808
	int mode, dsgn;
1806
	int mode, dsgn;
1809
	char *digits, *bp, *rve;
1807
	char *digits, *bp, *rve;
1810
# ifdef _NO_LONGDBL
1808
# ifdef _NO_LONGDBL
1811
	union double_union tmp;
1809
	union double_union tmp;
1812
 
1810
 
1813
	tmp.d = value;
1811
	tmp.d = value;
1814
	if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1812
	if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1815
		value = -value;
1813
		value = -value;
1816
		*sign = '-';
1814
		*sign = '-';
1817
	} else
1815
	} else
1818
		*sign = '\000';
1816
		*sign = '\000';
1819
# else /* !_NO_LONGDBL */
1817
# else /* !_NO_LONGDBL */
1820
	union
1818
	union
1821
	{
1819
	{
1822
	  struct ldieee ieee;
1820
	  struct ldieee ieee;
1823
	  _LONG_DOUBLE val;
1821
	  _LONG_DOUBLE val;
1824
	} ld;
1822
	} ld;
1825
 
1823
 
1826
	ld.val = value;
1824
	ld.val = value;
1827
	if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1825
	if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1828
		value = -value;
1826
		value = -value;
1829
		*sign = '-';
1827
		*sign = '-';
1830
	} else
1828
	} else
1831
		*sign = '\000';
1829
		*sign = '\000';
1832
# endif /* !_NO_LONGDBL */
1830
# endif /* !_NO_LONGDBL */
1833
 
1831
 
1834
# ifdef _WANT_IO_C99_FORMATS
1832
# ifdef _WANT_IO_C99_FORMATS
1835
	if (ch == 'a' || ch == 'A') {
1833
	if (ch == 'a' || ch == 'A') {
1836
		/* This code assumes FLT_RADIX is a power of 2.  The initial
1834
		/* This code assumes FLT_RADIX is a power of 2.  The initial
1837
		   division ensures the digit before the decimal will be less
1835
		   division ensures the digit before the decimal will be less
1838
		   than FLT_RADIX (unless it is rounded later).	 There is no
1836
		   than FLT_RADIX (unless it is rounded later).	 There is no
1839
		   loss of precision in these calculations.  */
1837
		   loss of precision in these calculations.  */
1840
		value = FREXP (value, decpt) / 8;
1838
		value = FREXP (value, decpt) / 8;
1841
		if (!value)
1839
		if (!value)
1842
			*decpt = 1;
1840
			*decpt = 1;
1843
		digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1841
		digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1844
		bp = buf;
1842
		bp = buf;
1845
		do {
1843
		do {
1846
			value *= 16;
1844
			value *= 16;
1847
			mode = (int) value;
1845
			mode = (int) value;
1848
			value -= mode;
1846
			value -= mode;
1849
			*bp++ = digits[mode];
1847
			*bp++ = digits[mode];
1850
		} while (ndigits-- && value);
1848
		} while (ndigits-- && value);
1851
		if (value > 0.5 || (value == 0.5 && mode & 1)) {
1849
		if (value > 0.5 || (value == 0.5 && mode & 1)) {
1852
			/* round to even */
1850
			/* round to even */
1853
			rve = bp;
1851
			rve = bp;
1854
			while (*--rve == digits[0xf]) {
1852
			while (*--rve == digits[0xf]) {
1855
				*rve = '0';
1853
				*rve = '0';
1856
			}
1854
			}
1857
			*rve = *rve == '9' ? digits[0xa] : *rve + 1;
1855
			*rve = *rve == '9' ? digits[0xa] : *rve + 1;
1858
		} else {
1856
		} else {
1859
			while (ndigits-- >= 0) {
1857
			while (ndigits-- >= 0) {
1860
				*bp++ = '0';
1858
				*bp++ = '0';
1861
			}
1859
			}
1862
		}
1860
		}
1863
		*length = bp - buf;
1861
		*length = bp - buf;
1864
		return buf;
1862
		return buf;
1865
	}
1863
	}
1866
# endif /* _WANT_IO_C99_FORMATS */
1864
# endif /* _WANT_IO_C99_FORMATS */
1867
	if (ch == 'f' || ch == 'F') {
1865
	if (ch == 'f' || ch == 'F') {
1868
		mode = 3;		/* ndigits after the decimal point */
1866
		mode = 3;		/* ndigits after the decimal point */
1869
	} else {
1867
	} else {
1870
		/* To obtain ndigits after the decimal point for the 'e'
1868
		/* To obtain ndigits after the decimal point for the 'e'
1871
		 * and 'E' formats, round to ndigits + 1 significant
1869
		 * and 'E' formats, round to ndigits + 1 significant
1872
		 * figures.
1870
		 * figures.
1873
		 */
1871
		 */
1874
		if (ch == 'e' || ch == 'E') {
1872
		if (ch == 'e' || ch == 'E') {
1875
			ndigits++;
1873
			ndigits++;
1876
		}
1874
		}
1877
		mode = 2;		/* ndigits significant digits */
1875
		mode = 2;		/* ndigits significant digits */
1878
	}
1876
	}
1879
 
1877
 
1880
	digits = _DTOA_R (data, value, mode, ndigits, decpt, &dsgn, &rve);
1878
	digits = _DTOA_R (data, value, mode, ndigits, decpt, &dsgn, &rve);
1881
 
1879
 
1882
	if ((ch != 'g' && ch != 'G') || flags & ALT) {	/* Print trailing zeros */
1880
	if ((ch != 'g' && ch != 'G') || flags & ALT) {	/* Print trailing zeros */
1883
		bp = digits + ndigits;
1881
		bp = digits + ndigits;
1884
		if (ch == 'f' || ch == 'F') {
1882
		if (ch == 'f' || ch == 'F') {
1885
			if (*digits == '0' && value)
1883
			if (*digits == '0' && value)
1886
				*decpt = -ndigits + 1;
1884
				*decpt = -ndigits + 1;
1887
			bp += *decpt;
1885
			bp += *decpt;
1888
		}
1886
		}
1889
		if (value == 0)	/* kludge for __dtoa irregularity */
1887
		if (value == 0)	/* kludge for __dtoa irregularity */
1890
			rve = bp;
1888
			rve = bp;
1891
		while (rve < bp)
1889
		while (rve < bp)
1892
			*rve++ = '0';
1890
			*rve++ = '0';
1893
	}
1891
	}
1894
	*length = rve - digits;
1892
	*length = rve - digits;
1895
	return (digits);
1893
	return (digits);
1896
}
1894
}
1897
 
1895
 
1898
static int
1896
static int
1899
exponent(char *p0, int exp, int fmtch)
1897
exponent(char *p0, int exp, int fmtch)
1900
{
1898
{
1901
	register char *p, *t;
1899
	register char *p, *t;
1902
	char expbuf[MAXEXPLEN];
1900
	char expbuf[MAXEXPLEN];
1903
# ifdef _WANT_IO_C99_FORMATS
1901
# ifdef _WANT_IO_C99_FORMATS
1904
	int isa = fmtch == 'a' || fmtch == 'A';
1902
	int isa = fmtch == 'a' || fmtch == 'A';
1905
# else
1903
# else
1906
#  define isa 0
1904
#  define isa 0
1907
# endif
1905
# endif
1908
 
1906
 
1909
	p = p0;
1907
	p = p0;
1910
	*p++ = isa ? 'p' - 'a' + fmtch : fmtch;
1908
	*p++ = isa ? 'p' - 'a' + fmtch : fmtch;
1911
	if (exp < 0) {
1909
	if (exp < 0) {
1912
		exp = -exp;
1910
		exp = -exp;
1913
		*p++ = '-';
1911
		*p++ = '-';
1914
	}
1912
	}
1915
	else
1913
	else
1916
		*p++ = '+';
1914
		*p++ = '+';
1917
	t = expbuf + MAXEXPLEN;
1915
	t = expbuf + MAXEXPLEN;
1918
	if (exp > 9) {
1916
	if (exp > 9) {
1919
		do {
1917
		do {
1920
			*--t = to_char (exp % 10);
1918
			*--t = to_char (exp % 10);
1921
		} while ((exp /= 10) > 9);
1919
		} while ((exp /= 10) > 9);
1922
		*--t = to_char (exp);
1920
		*--t = to_char (exp);
1923
		for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1921
		for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1924
	}
1922
	}
1925
	else {
1923
	else {
1926
		if (!isa)
1924
		if (!isa)
1927
			*p++ = '0';
1925
			*p++ = '0';
1928
		*p++ = to_char (exp);
1926
		*p++ = to_char (exp);
1929
	}
1927
	}
1930
	return (p - p0);
1928
	return (p - p0);
1931
}
1929
}
1932
#endif /* FLOATING_POINT */
1930
#endif /* FLOATING_POINT */
1933
 
1931
 
1934
 
1932
 
1935
#ifndef _NO_POS_ARGS
1933
#ifndef _NO_POS_ARGS
1936
 
1934
 
1937
/* Positional argument support.
1935
/* Positional argument support.
1938
   Written by Jeff Johnston
1936
   Written by Jeff Johnston
1939
 
1937
 
1940
   Copyright (c) 2002 Red Hat Incorporated.
1938
   Copyright (c) 2002 Red Hat Incorporated.
1941
   All rights reserved.
1939
   All rights reserved.
1942
 
1940
 
1943
   Redistribution and use in source and binary forms, with or without
1941
   Redistribution and use in source and binary forms, with or without
1944
   modification, are permitted provided that the following conditions are met:
1942
   modification, are permitted provided that the following conditions are met:
1945
 
1943
 
1946
      Redistributions of source code must retain the above copyright
1944
      Redistributions of source code must retain the above copyright
1947
      notice, this list of conditions and the following disclaimer.
1945
      notice, this list of conditions and the following disclaimer.
1948
 
1946
 
1949
      Redistributions in binary form must reproduce the above copyright
1947
      Redistributions in binary form must reproduce the above copyright
1950
      notice, this list of conditions and the following disclaimer in the
1948
      notice, this list of conditions and the following disclaimer in the
1951
      documentation and/or other materials provided with the distribution.
1949
      documentation and/or other materials provided with the distribution.
1952
 
1950
 
1953
      The name of Red Hat Incorporated may not be used to endorse
1951
      The name of Red Hat Incorporated may not be used to endorse
1954
      or promote products derived from this software without specific
1952
      or promote products derived from this software without specific
1955
      prior written permission.
1953
      prior written permission.
1956
 
1954
 
1957
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1955
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1958
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1956
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1959
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1957
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1960
   DISCLAIMED.  IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1958
   DISCLAIMED.  IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1961
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1959
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1962
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1960
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1963
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1961
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1964
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1962
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1965
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1963
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1966
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1964
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1967
 
1965
 
1968
/* The below constant state tables are shared between all versions of
1966
/* The below constant state tables are shared between all versions of
1969
   vfprintf and vfwprintf.  They must only be defined once, which we do in
1967
   vfprintf and vfwprintf.  They must only be defined once, which we do in
1970
   the STRING_ONLY/INTEGER_ONLY versions here. */
1968
   the STRING_ONLY/INTEGER_ONLY versions here. */
1971
#if defined (STRING_ONLY) && defined(INTEGER_ONLY)
1969
#if defined (STRING_ONLY) && defined(INTEGER_ONLY)
1972
 
1970
 
1973
_CONST __CH_CLASS __chclass[256] = {
1971
_CONST __CH_CLASS __chclass[256] = {
1974
  /* 00-07 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1972
  /* 00-07 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1975
  /* 08-0f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1973
  /* 08-0f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1976
  /* 10-17 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1974
  /* 10-17 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1977
  /* 18-1f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1975
  /* 18-1f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1978
  /* 20-27 */  FLAG,    OTHER,   OTHER,   FLAG,    DOLLAR,  OTHER,   OTHER,   FLAG,
1976
  /* 20-27 */  FLAG,    OTHER,   OTHER,   FLAG,    DOLLAR,  OTHER,   OTHER,   FLAG,
1979
  /* 28-2f */  OTHER,   OTHER,   STAR,    FLAG,    OTHER,   FLAG,    DOT,     OTHER,
1977
  /* 28-2f */  OTHER,   OTHER,   STAR,    FLAG,    OTHER,   FLAG,    DOT,     OTHER,
1980
  /* 30-37 */  ZERO,    DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,
1978
  /* 30-37 */  ZERO,    DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,
1981
  /* 38-3f */  DIGIT,   DIGIT,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1979
  /* 38-3f */  DIGIT,   DIGIT,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1982
  /* 40-47 */  OTHER,   SPEC,    OTHER,   SPEC,    SPEC,    SPEC,    SPEC,    SPEC,
1980
  /* 40-47 */  OTHER,   SPEC,    OTHER,   SPEC,    SPEC,    SPEC,    SPEC,    SPEC,
1983
  /* 48-4f */  OTHER,   OTHER,   OTHER,   OTHER,   MODFR,   OTHER,   OTHER,   SPEC,
1981
  /* 48-4f */  OTHER,   OTHER,   OTHER,   OTHER,   MODFR,   OTHER,   OTHER,   SPEC,
1984
  /* 50-57 */  OTHER,   OTHER,   OTHER,   SPEC,    OTHER,   SPEC,    OTHER,   OTHER,
1982
  /* 50-57 */  OTHER,   OTHER,   OTHER,   SPEC,    OTHER,   SPEC,    OTHER,   OTHER,
1985
  /* 58-5f */  SPEC,    OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1983
  /* 58-5f */  SPEC,    OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1986
  /* 60-67 */  OTHER,   SPEC,    OTHER,   SPEC,    SPEC,    SPEC,    SPEC,    SPEC,
1984
  /* 60-67 */  OTHER,   SPEC,    OTHER,   SPEC,    SPEC,    SPEC,    SPEC,    SPEC,
1987
  /* 68-6f */  MODFR,   SPEC,    MODFR,   OTHER,   MODFR,   OTHER,   SPEC,    SPEC,
1985
  /* 68-6f */  MODFR,   SPEC,    MODFR,   OTHER,   MODFR,   OTHER,   SPEC,    SPEC,
1988
  /* 70-77 */  SPEC,    MODFR,   OTHER,   SPEC,    MODFR,   SPEC,    OTHER,   OTHER,
1986
  /* 70-77 */  SPEC,    MODFR,   OTHER,   SPEC,    MODFR,   SPEC,    OTHER,   OTHER,
1989
  /* 78-7f */  SPEC,    OTHER,   MODFR,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1987
  /* 78-7f */  SPEC,    OTHER,   MODFR,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1990
  /* 80-87 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1988
  /* 80-87 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1991
  /* 88-8f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1989
  /* 88-8f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1992
  /* 90-97 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1990
  /* 90-97 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1993
  /* 98-9f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1991
  /* 98-9f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1994
  /* a0-a7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1992
  /* a0-a7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1995
  /* a8-af */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1993
  /* a8-af */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1996
  /* b0-b7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1994
  /* b0-b7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1997
  /* b8-bf */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1995
  /* b8-bf */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1998
  /* c0-c7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1996
  /* c0-c7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1999
  /* c8-cf */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1997
  /* c8-cf */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2000
  /* d0-d7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1998
  /* d0-d7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2001
  /* d8-df */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1999
  /* d8-df */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2002
  /* e0-e7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2000
  /* e0-e7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2003
  /* e8-ef */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2001
  /* e8-ef */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2004
  /* f0-f7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2002
  /* f0-f7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2005
  /* f8-ff */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2003
  /* f8-ff */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2006
};
2004
};
2007
 
2005
 
2008
_CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS] = {
2006
_CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS] = {
2009
  /*             '0'     '1-9'     '$'     MODFR    SPEC    '.'     '*'    FLAG    OTHER */
2007
  /*             '0'     '1-9'     '$'     MODFR    SPEC    '.'     '*'    FLAG    OTHER */
2010
  /* START */  { SFLAG,   WDIG,    DONE,   SMOD,    DONE,   SDOT,  VARW,   SFLAG,  DONE },
2008
  /* START */  { SFLAG,   WDIG,    DONE,   SMOD,    DONE,   SDOT,  VARW,   SFLAG,  DONE },
2011
  /* SFLAG */  { SFLAG,   WDIG,    DONE,   SMOD,    DONE,   SDOT,  VARW,   SFLAG,  DONE },
2009
  /* SFLAG */  { SFLAG,   WDIG,    DONE,   SMOD,    DONE,   SDOT,  VARW,   SFLAG,  DONE },
2012
  /* WDIG  */  { DONE,    DONE,    WIDTH,  SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2010
  /* WDIG  */  { DONE,    DONE,    WIDTH,  SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2013
  /* WIDTH */  { DONE,    DONE,    DONE,   SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2011
  /* WIDTH */  { DONE,    DONE,    DONE,   SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2014
  /* SMOD  */  { DONE,    DONE,    DONE,   DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2012
  /* SMOD  */  { DONE,    DONE,    DONE,   DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2015
  /* SDOT  */  { SDOT,    PREC,    DONE,   SMOD,    DONE,   DONE,  VARP,   DONE,   DONE },
2013
  /* SDOT  */  { SDOT,    PREC,    DONE,   SMOD,    DONE,   DONE,  VARP,   DONE,   DONE },
2016
  /* VARW  */  { DONE,    VWDIG,   DONE,   SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2014
  /* VARW  */  { DONE,    VWDIG,   DONE,   SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2017
  /* VARP  */  { DONE,    VPDIG,   DONE,   SMOD,    DONE,   DONE,  DONE,   DONE,   DONE },
2015
  /* VARP  */  { DONE,    VPDIG,   DONE,   SMOD,    DONE,   DONE,  DONE,   DONE,   DONE },
2018
  /* PREC  */  { DONE,    DONE,    DONE,   SMOD,    DONE,   DONE,  DONE,   DONE,   DONE },
2016
  /* PREC  */  { DONE,    DONE,    DONE,   SMOD,    DONE,   DONE,  DONE,   DONE,   DONE },
2019
  /* VWDIG */  { DONE,    DONE,    WIDTH,  DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2017
  /* VWDIG */  { DONE,    DONE,    WIDTH,  DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2020
  /* VPDIG */  { DONE,    DONE,    PREC,   DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2018
  /* VPDIG */  { DONE,    DONE,    PREC,   DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2021
};
2019
};
2022
 
2020
 
2023
_CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS] = {
2021
_CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS] = {
2024
  /*             '0'     '1-9'     '$'     MODFR    SPEC    '.'     '*'    FLAG    OTHER */
2022
  /*             '0'     '1-9'     '$'     MODFR    SPEC    '.'     '*'    FLAG    OTHER */
2025
  /* START */  { NOOP,    NUMBER,  NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2023
  /* START */  { NOOP,    NUMBER,  NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2026
  /* SFLAG */  { NOOP,    NUMBER,  NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2024
  /* SFLAG */  { NOOP,    NUMBER,  NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2027
  /* WDIG  */  { NOOP,    NOOP,    GETPOS, GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2025
  /* WDIG  */  { NOOP,    NOOP,    GETPOS, GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2028
  /* WIDTH */  { NOOP,    NOOP,    NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2026
  /* WIDTH */  { NOOP,    NOOP,    NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2029
  /* SMOD  */  { NOOP,    NOOP,    NOOP,   NOOP,    GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2027
  /* SMOD  */  { NOOP,    NOOP,    NOOP,   NOOP,    GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2030
  /* SDOT  */  { NOOP,    SKIPNUM, NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2028
  /* SDOT  */  { NOOP,    SKIPNUM, NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2031
  /* VARW  */  { NOOP,    NUMBER,  NOOP,   GETPW,   GETPWB, GETPW, NOOP,   NOOP,   NOOP },
2029
  /* VARW  */  { NOOP,    NUMBER,  NOOP,   GETPW,   GETPWB, GETPW, NOOP,   NOOP,   NOOP },
2032
  /* VARP  */  { NOOP,    NUMBER,  NOOP,   GETPW,   GETPWB, NOOP,  NOOP,   NOOP,   NOOP },
2030
  /* VARP  */  { NOOP,    NUMBER,  NOOP,   GETPW,   GETPWB, NOOP,  NOOP,   NOOP,   NOOP },
2033
  /* PREC  */  { NOOP,    NOOP,    NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2031
  /* PREC  */  { NOOP,    NOOP,    NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2034
  /* VWDIG */  { NOOP,    NOOP,    PWPOS,  NOOP,    NOOP,   NOOP,  NOOP,   NOOP,   NOOP },
2032
  /* VWDIG */  { NOOP,    NOOP,    PWPOS,  NOOP,    NOOP,   NOOP,  NOOP,   NOOP,   NOOP },
2035
  /* VPDIG */  { NOOP,    NOOP,    PWPOS,  NOOP,    NOOP,   NOOP,  NOOP,   NOOP,   NOOP },
2033
  /* VPDIG */  { NOOP,    NOOP,    PWPOS,  NOOP,    NOOP,   NOOP,  NOOP,   NOOP,   NOOP },
2036
};
2034
};
2037
 
2035
 
2038
#endif /* STRING_ONLY && INTEGER_ONLY */
2036
#endif /* STRING_ONLY && INTEGER_ONLY */
2039
 
2037
 
2040
/* function to get positional parameter N where n = N - 1 */
2038
/* function to get positional parameter N where n = N - 1 */
2041
static union arg_val *
2039
static union arg_val *
2042
_DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
2040
_DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
2043
       struct _reent *data _AND
2041
       struct _reent *data _AND
2044
       int n               _AND
2042
       int n               _AND
2045
       char *fmt           _AND
2043
       char *fmt           _AND
2046
       va_list *ap         _AND
2044
       va_list *ap         _AND
2047
       int *numargs_p      _AND
2045
       int *numargs_p      _AND
2048
       union arg_val *args _AND
2046
       union arg_val *args _AND
2049
       int *arg_type       _AND
2047
       int *arg_type       _AND
2050
       char **last_fmt)
2048
       char **last_fmt)
2051
{
2049
{
2052
  int ch;
2050
  int ch;
2053
  int number, flags;
2051
  int number, flags;
2054
  int spec_type;
2052
  int spec_type;
2055
  int numargs = *numargs_p;
2053
  int numargs = *numargs_p;
2056
  __CH_CLASS chtype;
2054
  __CH_CLASS chtype;
2057
  __STATE state, next_state;
2055
  __STATE state, next_state;
2058
  __ACTION action;
2056
  __ACTION action;
2059
  int pos, last_arg;
2057
  int pos, last_arg;
2060
  int max_pos_arg = n;
2058
  int max_pos_arg = n;
2061
  /* Only need types that can be reached via vararg promotions.  */
2059
  /* Only need types that can be reached via vararg promotions.  */
2062
  enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
2060
  enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
2063
# ifdef _MB_CAPABLE
2061
# ifdef _MB_CAPABLE
2064
  wchar_t wc;
2062
  wchar_t wc;
2065
  mbstate_t wc_state;
2063
  mbstate_t wc_state;
2066
  int nbytes;
2064
  int nbytes;
2067
# endif
2065
# endif
2068
 
2066
 
2069
  /* if this isn't the first call, pick up where we left off last time */
2067
  /* if this isn't the first call, pick up where we left off last time */
2070
  if (*last_fmt != NULL)
2068
  if (*last_fmt != NULL)
2071
    fmt = *last_fmt;
2069
    fmt = *last_fmt;
2072
 
2070
 
2073
# ifdef _MB_CAPABLE
2071
# ifdef _MB_CAPABLE
2074
  memset (&wc_state, '\0', sizeof (wc_state));
2072
  memset (&wc_state, '\0', sizeof (wc_state));
2075
# endif
2073
# endif
2076
 
2074
 
2077
  /* we need to process either to end of fmt string or until we have actually
2075
  /* we need to process either to end of fmt string or until we have actually
2078
     read the desired parameter from the vararg list. */
2076
     read the desired parameter from the vararg list. */
2079
  while (*fmt && n >= numargs)
2077
  while (*fmt && n >= numargs)
2080
    {
2078
    {
2081
# ifdef _MB_CAPABLE
2079
# ifdef _MB_CAPABLE
2082
      while ((nbytes = __mbtowc (data, &wc, fmt, MB_CUR_MAX,
2080
      while ((nbytes = __mbtowc (data, &wc, fmt, MB_CUR_MAX,
2083
				 __locale_charset (), &wc_state)) > 0)
2081
				 __locale_charset (), &wc_state)) > 0)
2084
	{
2082
	{
2085
	  fmt += nbytes;
2083
	  fmt += nbytes;
2086
	  if (wc == '%')
2084
	  if (wc == '%')
2087
	    break;
2085
	    break;
2088
	}
2086
	}
2089
 
2087
 
2090
      if (nbytes <= 0)
2088
      if (nbytes <= 0)
2091
	break;
2089
	break;
2092
# else
2090
# else
2093
      while (*fmt != '\0' && *fmt != '%')
2091
      while (*fmt != '\0' && *fmt != '%')
2094
	fmt += 1;
2092
	fmt += 1;
2095
 
2093
 
2096
      if (*fmt == '\0')
2094
      if (*fmt == '\0')
2097
	break;
2095
	break;
2098
# endif /* ! _MB_CAPABLE */
2096
# endif /* ! _MB_CAPABLE */
2099
      state = START;
2097
      state = START;
2100
      flags = 0;
2098
      flags = 0;
2101
      pos = -1;
2099
      pos = -1;
2102
      number = 0;
2100
      number = 0;
2103
      spec_type = INT;
2101
      spec_type = INT;
2104
 
2102
 
2105
      /* Use state/action table to process format specifiers.  We ignore invalid
2103
      /* Use state/action table to process format specifiers.  We ignore invalid
2106
         formats and we are only interested in information that tells us how to
2104
         formats and we are only interested in information that tells us how to
2107
         read the vararg list. */
2105
         read the vararg list. */
2108
      while (state != DONE)
2106
      while (state != DONE)
2109
	{
2107
	{
2110
	  ch = *fmt++;
2108
	  ch = *fmt++;
2111
	  chtype = __chclass[ch];
2109
	  chtype = __chclass[ch];
2112
	  next_state = __state_table[state][chtype];
2110
	  next_state = __state_table[state][chtype];
2113
	  action = __action_table[state][chtype];
2111
	  action = __action_table[state][chtype];
2114
	  state = next_state;
2112
	  state = next_state;
2115
 
2113
 
2116
	  switch (action)
2114
	  switch (action)
2117
	    {
2115
	    {
2118
	    case GETMOD:  /* we have format modifier */
2116
	    case GETMOD:  /* we have format modifier */
2119
	      switch (ch)
2117
	      switch (ch)
2120
		{
2118
		{
2121
		case 'h':
2119
		case 'h':
2122
		  /* No flag needed, since short and char promote to int.  */
2120
		  /* No flag needed, since short and char promote to int.  */
2123
		  break;
2121
		  break;
2124
		case 'L':
2122
		case 'L':
2125
		  flags |= LONGDBL;
2123
		  flags |= LONGDBL;
2126
		  break;
2124
		  break;
2127
		case 'q':
2125
		case 'q':
2128
		  flags |= QUADINT;
2126
		  flags |= QUADINT;
2129
		  break;
2127
		  break;
2130
# ifdef _WANT_IO_C99_FORMATS
2128
# ifdef _WANT_IO_C99_FORMATS
2131
		case 'j':
2129
		case 'j':
2132
		  if (sizeof (intmax_t) == sizeof (long))
2130
		  if (sizeof (intmax_t) == sizeof (long))
2133
		    flags |= LONGINT;
2131
		    flags |= LONGINT;
2134
		  else
2132
		  else
2135
		    flags |= QUADINT;
2133
		    flags |= QUADINT;
2136
		  break;
2134
		  break;
2137
		case 'z':
2135
		case 'z':
2138
		  if (sizeof (size_t) <= sizeof (int))
2136
		  if (sizeof (size_t) <= sizeof (int))
2139
		    /* no flag needed */;
2137
		    /* no flag needed */;
2140
		  else if (sizeof (size_t) <= sizeof (long))
2138
		  else if (sizeof (size_t) <= sizeof (long))
2141
		    flags |= LONGINT;
2139
		    flags |= LONGINT;
2142
		  else
2140
		  else
2143
		    /* POSIX states that at least one programming
2141
		    /* POSIX states that at least one programming
2144
		       environment must support size_t no wider than
2142
		       environment must support size_t no wider than
2145
		       long, but that means other environments can
2143
		       long, but that means other environments can
2146
		       have size_t as wide as long long.  */
2144
		       have size_t as wide as long long.  */
2147
		    flags |= QUADINT;
2145
		    flags |= QUADINT;
2148
		  break;
2146
		  break;
2149
		case 't':
2147
		case 't':
2150
		  if (sizeof (ptrdiff_t) <= sizeof (int))
2148
		  if (sizeof (ptrdiff_t) <= sizeof (int))
2151
		    /* no flag needed */;
2149
		    /* no flag needed */;
2152
		  else if (sizeof (ptrdiff_t) <= sizeof (long))
2150
		  else if (sizeof (ptrdiff_t) <= sizeof (long))
2153
		    flags |= LONGINT;
2151
		    flags |= LONGINT;
2154
		  else
2152
		  else
2155
		    /* POSIX states that at least one programming
2153
		    /* POSIX states that at least one programming
2156
		       environment must support ptrdiff_t no wider than
2154
		       environment must support ptrdiff_t no wider than
2157
		       long, but that means other environments can
2155
		       long, but that means other environments can
2158
		       have ptrdiff_t as wide as long long.  */
2156
		       have ptrdiff_t as wide as long long.  */
2159
		    flags |= QUADINT;
2157
		    flags |= QUADINT;
2160
		  break;
2158
		  break;
2161
# endif /* _WANT_IO_C99_FORMATS */
2159
# endif /* _WANT_IO_C99_FORMATS */
2162
		case 'l':
2160
		case 'l':
2163
		default:
2161
		default:
2164
# if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
2162
# if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
2165
		  if (*fmt == 'l')
2163
		  if (*fmt == 'l')
2166
		    {
2164
		    {
2167
		      flags |= QUADINT;
2165
		      flags |= QUADINT;
2168
		      ++fmt;
2166
		      ++fmt;
2169
		    }
2167
		    }
2170
		  else
2168
		  else
2171
# endif
2169
# endif
2172
		    flags |= LONGINT;
2170
		    flags |= LONGINT;
2173
		  break;
2171
		  break;
2174
		}
2172
		}
2175
	      break;
2173
	      break;
2176
	    case GETARG: /* we have format specifier */
2174
	    case GETARG: /* we have format specifier */
2177
	      {
2175
	      {
2178
		numargs &= (MAX_POS_ARGS - 1);
2176
		numargs &= (MAX_POS_ARGS - 1);
2179
		/* process the specifier and translate it to a type to fetch from varargs */
2177
		/* process the specifier and translate it to a type to fetch from varargs */
2180
		switch (ch)
2178
		switch (ch)
2181
		  {
2179
		  {
2182
		  case 'd':
2180
		  case 'd':
2183
		  case 'i':
2181
		  case 'i':
2184
		  case 'o':
2182
		  case 'o':
2185
		  case 'x':
2183
		  case 'x':
2186
		  case 'X':
2184
		  case 'X':
2187
		  case 'u':
2185
		  case 'u':
2188
		    if (flags & LONGINT)
2186
		    if (flags & LONGINT)
2189
		      spec_type = LONG_INT;
2187
		      spec_type = LONG_INT;
2190
# ifndef _NO_LONGLONG
2188
# ifndef _NO_LONGLONG
2191
		    else if (flags & QUADINT)
2189
		    else if (flags & QUADINT)
2192
		      spec_type = QUAD_INT;
2190
		      spec_type = QUAD_INT;
2193
# endif
2191
# endif
2194
		    else
2192
		    else
2195
		      spec_type = INT;
2193
		      spec_type = INT;
2196
		    break;
2194
		    break;
2197
		  case 'D':
2195
		  case 'D':
2198
		  case 'U':
2196
		  case 'U':
2199
		  case 'O':
2197
		  case 'O':
2200
		    spec_type = LONG_INT;
2198
		    spec_type = LONG_INT;
2201
		    break;
2199
		    break;
2202
# ifdef _WANT_IO_C99_FORMATS
2200
# ifdef _WANT_IO_C99_FORMATS
2203
		  case 'a':
2201
		  case 'a':
2204
		  case 'A':
2202
		  case 'A':
2205
		  case 'F':
2203
		  case 'F':
2206
# endif
2204
# endif
2207
		  case 'f':
2205
		  case 'f':
2208
		  case 'g':
2206
		  case 'g':
2209
		  case 'G':
2207
		  case 'G':
2210
		  case 'E':
2208
		  case 'E':
2211
		  case 'e':
2209
		  case 'e':
2212
# ifndef _NO_LONGDBL
2210
# ifndef _NO_LONGDBL
2213
		    if (flags & LONGDBL)
2211
		    if (flags & LONGDBL)
2214
		      spec_type = LONG_DOUBLE;
2212
		      spec_type = LONG_DOUBLE;
2215
		    else
2213
		    else
2216
# endif
2214
# endif
2217
		      spec_type = DOUBLE;
2215
		      spec_type = DOUBLE;
2218
		    break;
2216
		    break;
2219
		  case 's':
2217
		  case 's':
2220
# ifdef _WANT_IO_C99_FORMATS
2218
# ifdef _WANT_IO_C99_FORMATS
2221
		  case 'S':
2219
		  case 'S':
2222
# endif
2220
# endif
2223
		  case 'p':
2221
		  case 'p':
2224
		  case 'n':
2222
		  case 'n':
2225
		    spec_type = CHAR_PTR;
2223
		    spec_type = CHAR_PTR;
2226
		    break;
2224
		    break;
2227
		  case 'c':
2225
		  case 'c':
2228
# ifdef _WANT_IO_C99_FORMATS
2226
# ifdef _WANT_IO_C99_FORMATS
2229
		    if (flags & LONGINT)
2227
		    if (flags & LONGINT)
2230
		      spec_type = WIDE_CHAR;
2228
		      spec_type = WIDE_CHAR;
2231
		    else
2229
		    else
2232
# endif
2230
# endif
2233
		      spec_type = INT;
2231
		      spec_type = INT;
2234
		    break;
2232
		    break;
2235
# ifdef _WANT_IO_C99_FORMATS
2233
# ifdef _WANT_IO_C99_FORMATS
2236
		  case 'C':
2234
		  case 'C':
2237
		    spec_type = WIDE_CHAR;
2235
		    spec_type = WIDE_CHAR;
2238
		    break;
2236
		    break;
2239
# endif
2237
# endif
2240
		  }
2238
		  }
2241
 
2239
 
2242
		/* if we have a positional parameter, just store the type, otherwise
2240
		/* if we have a positional parameter, just store the type, otherwise
2243
		   fetch the parameter from the vararg list */
2241
		   fetch the parameter from the vararg list */
2244
		if (pos != -1)
2242
		if (pos != -1)
2245
		  arg_type[pos] = spec_type;
2243
		  arg_type[pos] = spec_type;
2246
		else
2244
		else
2247
		  {
2245
		  {
2248
		    switch (spec_type)
2246
		    switch (spec_type)
2249
		      {
2247
		      {
2250
		      case LONG_INT:
2248
		      case LONG_INT:
2251
			args[numargs++].val_long = va_arg (*ap, long);
2249
			args[numargs++].val_long = va_arg (*ap, long);
2252
			break;
2250
			break;
2253
		      case QUAD_INT:
2251
		      case QUAD_INT:
2254
			args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2252
			args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2255
			break;
2253
			break;
2256
		      case WIDE_CHAR:
2254
		      case WIDE_CHAR:
2257
			args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2255
			args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2258
			break;
2256
			break;
2259
		      case INT:
2257
		      case INT:
2260
			args[numargs++].val_int = va_arg (*ap, int);
2258
			args[numargs++].val_int = va_arg (*ap, int);
2261
			break;
2259
			break;
2262
		      case CHAR_PTR:
2260
		      case CHAR_PTR:
2263
			args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2261
			args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2264
			break;
2262
			break;
2265
		      case DOUBLE:
2263
		      case DOUBLE:
2266
			args[numargs++].val_double = va_arg (*ap, double);
2264
			args[numargs++].val_double = va_arg (*ap, double);
2267
			break;
2265
			break;
2268
		      case LONG_DOUBLE:
2266
		      case LONG_DOUBLE:
2269
			args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2267
			args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2270
			break;
2268
			break;
2271
		      }
2269
		      }
2272
		  }
2270
		  }
2273
	      }
2271
	      }
2274
	      break;
2272
	      break;
2275
	    case GETPOS: /* we have positional specifier */
2273
	    case GETPOS: /* we have positional specifier */
2276
	      if (arg_type[0] == -1)
2274
	      if (arg_type[0] == -1)
2277
		memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2275
		memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2278
	      pos = number - 1;
2276
	      pos = number - 1;
2279
	      max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
2277
	      max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
2280
	      break;
2278
	      break;
2281
	    case PWPOS:  /* we have positional specifier for width or precision */
2279
	    case PWPOS:  /* we have positional specifier for width or precision */
2282
	      if (arg_type[0] == -1)
2280
	      if (arg_type[0] == -1)
2283
		memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2281
		memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2284
	      number -= 1;
2282
	      number -= 1;
2285
	      arg_type[number] = INT;
2283
	      arg_type[number] = INT;
2286
	      max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
2284
	      max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
2287
	      break;
2285
	      break;
2288
	    case GETPWB: /* we require format pushback */
2286
	    case GETPWB: /* we require format pushback */
2289
	      --fmt;
2287
	      --fmt;
2290
	      /* fallthrough */
2288
	      /* fallthrough */
2291
	    case GETPW:  /* we have a variable precision or width to acquire */
2289
	    case GETPW:  /* we have a variable precision or width to acquire */
2292
	      args[numargs++].val_int = va_arg (*ap, int);
2290
	      args[numargs++].val_int = va_arg (*ap, int);
2293
	      break;
2291
	      break;
2294
	    case NUMBER: /* we have a number to process */
2292
	    case NUMBER: /* we have a number to process */
2295
	      number = (ch - '0');
2293
	      number = (ch - '0');
2296
	      while ((ch = *fmt) != '\0' && is_digit (ch))
2294
	      while ((ch = *fmt) != '\0' && is_digit (ch))
2297
		{
2295
		{
2298
		  number = number * 10 + (ch - '0');
2296
		  number = number * 10 + (ch - '0');
2299
		  ++fmt;
2297
		  ++fmt;
2300
		}
2298
		}
2301
	      break;
2299
	      break;
2302
	    case SKIPNUM: /* we have a number to skip */
2300
	    case SKIPNUM: /* we have a number to skip */
2303
	      while ((ch = *fmt) != '\0' && is_digit (ch))
2301
	      while ((ch = *fmt) != '\0' && is_digit (ch))
2304
		++fmt;
2302
		++fmt;
2305
	      break;
2303
	      break;
2306
	    case NOOP:
2304
	    case NOOP:
2307
	    default:
2305
	    default:
2308
	      break; /* do nothing */
2306
	      break; /* do nothing */
2309
	    }
2307
	    }
2310
	}
2308
	}
2311
    }
2309
    }
2312
 
2310
 
2313
  /* process all arguments up to at least the one we are looking for and if we
2311
  /* process all arguments up to at least the one we are looking for and if we
2314
     have seen the end of the string, then process up to the max argument needed */
2312
     have seen the end of the string, then process up to the max argument needed */
2315
  if (*fmt == '\0')
2313
  if (*fmt == '\0')
2316
    last_arg = max_pos_arg;
2314
    last_arg = max_pos_arg;
2317
  else
2315
  else
2318
    last_arg = n;
2316
    last_arg = n;
2319
 
2317
 
2320
  while (numargs <= last_arg)
2318
  while (numargs <= last_arg)
2321
    {
2319
    {
2322
      switch (arg_type[numargs])
2320
      switch (arg_type[numargs])
2323
	{
2321
	{
2324
	case LONG_INT:
2322
	case LONG_INT:
2325
	  args[numargs++].val_long = va_arg (*ap, long);
2323
	  args[numargs++].val_long = va_arg (*ap, long);
2326
	  break;
2324
	  break;
2327
	case QUAD_INT:
2325
	case QUAD_INT:
2328
	  args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2326
	  args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2329
	  break;
2327
	  break;
2330
	case CHAR_PTR:
2328
	case CHAR_PTR:
2331
	  args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2329
	  args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2332
	  break;
2330
	  break;
2333
	case DOUBLE:
2331
	case DOUBLE:
2334
	  args[numargs++].val_double = va_arg (*ap, double);
2332
	  args[numargs++].val_double = va_arg (*ap, double);
2335
	  break;
2333
	  break;
2336
	case LONG_DOUBLE:
2334
	case LONG_DOUBLE:
2337
	  args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2335
	  args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2338
	  break;
2336
	  break;
2339
	case WIDE_CHAR:
2337
	case WIDE_CHAR:
2340
	  args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2338
	  args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2341
	  break;
2339
	  break;
2342
	case INT:
2340
	case INT:
2343
	default:
2341
	default:
2344
	  args[numargs++].val_int = va_arg (*ap, int);
2342
	  args[numargs++].val_int = va_arg (*ap, int);
2345
	  break;
2343
	  break;
2346
	}
2344
	}
2347
    }
2345
    }
2348
 
2346
 
2349
  /* alter the global numargs value and keep a reference to the last bit of the fmt
2347
  /* alter the global numargs value and keep a reference to the last bit of the fmt
2350
     string we processed here because the caller will continue processing where we started */
2348
     string we processed here because the caller will continue processing where we started */
2351
  *numargs_p = numargs;
2349
  *numargs_p = numargs;
2352
  *last_fmt = fmt;
2350
  *last_fmt = fmt;
2353
  return &args[n];
2351
  return &args[n];
2354
}
2352
}
2355
#endif /* !_NO_POS_ARGS */
2353
#endif /* !_NO_POS_ARGS */