Subversion Repositories Kolibri OS

Rev

Rev 4872 | Rev 4921 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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