Subversion Repositories Kolibri OS

Rev

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