Subversion Repositories Kolibri OS

Rev

Rev 4874 | Rev 6099 | 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
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);
4921 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;
967
		  goto rflag;
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 */
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 */
1350
				size = expt;
1351
				if (flags & ALT)
1352
					++size;
1353
			} else
1354
				size = ndig + (expt > 0 ?
1355
					1 : 2 - expt);
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
 
1524
				if (p != NULL) {
1525
					size = p - cp;
1526
					if (size > prec)
1527
						size = prec;
1528
				} else
1529
					size = prec;
1530
			} else
1531
				size = strlen (cp);
1532
 
1533
			break;
1534
		case 'U': /* extension */
1535
			flags |= LONGINT;
1536
			/*FALLTHROUGH*/
1537
		case 'u':
1538
			_uquad = UARG ();
1539
			base = DEC;
1540
			goto nosign;
1541
		case 'X':
1542
			xdigs = "0123456789ABCDEF";
1543
			goto hex;
1544
		case 'x':
1545
			xdigs = "0123456789abcdef";
1546
hex:			_uquad = UARG ();
1547
			base = HEX;
1548
			/* leading 0x/X only if non-zero */
1549
			if (flags & ALT && _uquad != 0) {
1550
				ox[0] = '0';
1551
				ox[1] = ch;
1552
				flags |= HEXPREFIX;
1553
			}
1554
 
1555
#ifdef _WANT_IO_C99_FORMATS
1556
			flags &= ~GROUPING;
1557
#endif
1558
			/* unsigned conversions */
1559
nosign:			sign = '\0';
1560
			/*
1561
			 * ``... diouXx conversions ... if a precision is
1562
			 * specified, the 0 flag will be ignored.''
1563
			 *	-- ANSI X3J11
1564
			 */
1565
number:			if ((dprec = prec) >= 0)
1566
				flags &= ~ZEROPAD;
1567
 
1568
			/*
1569
			 * ``The result of converting a zero value with an
1570
			 * explicit precision of zero is no characters.''
1571
			 *	-- ANSI X3J11
1572
			 */
1573
			cp = buf + BUF;
1574
			if (_uquad != 0 || prec != 0) {
1575
				/*
1576
				 * Unsigned mod is hard, and unsigned mod
1577
				 * by a constant is easier than that by
1578
				 * a variable; hence this switch.
1579
				 */
1580
				switch (base) {
1581
				case OCT:
1582
					do {
1583
						*--cp = to_char (_uquad & 7);
1584
						_uquad >>= 3;
1585
					} while (_uquad);
1586
					/* handle octal leading 0 */
1587
					if (flags & ALT && *cp != '0')
1588
						*--cp = '0';
1589
					break;
1590
 
1591
				case DEC:
1592
					/* many numbers are 1 digit */
1593
					if (_uquad < 10) {
1594
						*--cp = to_char(_uquad);
1595
						break;
1596
					}
1597
#ifdef _WANT_IO_C99_FORMATS
1598
					ndig = 0;
1599
#endif
1600
					do {
1601
						*--cp = to_char (_uquad % 10);
1602
#ifdef _WANT_IO_C99_FORMATS
1603
					  ndig++;
1604
					  /* If (*grouping == CHAR_MAX) then no
1605
					     more grouping */
1606
					  if ((flags & GROUPING)
1607
					      && ndig == *grouping
1608
					      && *grouping != CHAR_MAX
1609
					      && _uquad > 9) {
1610
					    cp -= thsnd_len;
1611
					    strncpy (cp, thousands_sep,
1612
						     thsnd_len);
1613
					    ndig = 0;
1614
					    /* If (grouping[1] == '\0') then we
1615
					       have to use *grouping character
1616
					       (last grouping rule) for all
1617
					       next cases. */
1618
					    if (grouping[1] != '\0')
1619
					      grouping++;
1620
					  }
1621
#endif
1622
						_uquad /= 10;
1623
					} while (_uquad != 0);
1624
					break;
1625
 
1626
				case HEX:
1627
					do {
1628
						*--cp = xdigs[_uquad & 15];
1629
						_uquad >>= 4;
1630
					} while (_uquad);
1631
					break;
1632
 
1633
				default:
1634
					cp = "bug in vfprintf: bad base";
1635
					size = strlen (cp);
1636
					goto skipsize;
1637
				}
1638
			}
1639
                       /*
1640
			* ...result is to be converted to an 'alternate form'.
1641
			* For o conversion, it increases the precision to force
1642
			* the first digit of the result to be a zero."
1643
			*     -- ANSI X3J11
1644
			*
1645
			* To demonstrate this case, compile and run:
1646
                        *    printf ("%#.0o",0);
1647
			*/
1648
                       else if (base == OCT && (flags & ALT))
1649
                         *--cp = '0';
1650
 
1651
			size = buf + BUF - cp;
1652
		skipsize:
1653
			break;
1654
		default:	/* "%?" prints ?, unless ? is NUL */
1655
			if (ch == '\0')
1656
				goto done;
1657
			/* pretend it was %c with argument ch */
1658
			cp = buf;
1659
			*cp = ch;
1660
			size = 1;
1661
			sign = '\0';
1662
			break;
1663
		}
1664
 
1665
		/*
1666
		 * All reasonable formats wind up here.  At this point, `cp'
1667
		 * points to a string which (if not flags&LADJUST) should be
1668
		 * padded out to `width' places.  If flags&ZEROPAD, it should
1669
		 * first be prefixed by any sign or other prefix; otherwise,
1670
		 * it should be blank padded before the prefix is emitted.
1671
		 * After any left-hand padding and prefixing, emit zeroes
1672
		 * required by a decimal [diouxX] precision, then print the
1673
		 * string proper, then emit zeroes required by any leftover
1674
		 * floating precision; finally, if LADJUST, pad with blanks.
1675
		 * If flags&FPT, ch must be in [aAeEfg].
1676
		 *
1677
		 * Compute actual size, so we know how much to pad.
1678
		 * size excludes decimal prec; realsz includes it.
1679
		 */
1680
		realsz = dprec > size ? dprec : size;
1681
		if (sign)
1682
			realsz++;
1683
		if (flags & HEXPREFIX)
1684
			realsz+= 2;
1685
 
1686
		/* right-adjusting blank padding */
1687
		if ((flags & (LADJUST|ZEROPAD)) == 0)
1688
			PAD (width - realsz, blanks);
1689
 
1690
		/* prefix */
1691
		if (sign)
1692
			PRINT (&sign, 1);
1693
		if (flags & HEXPREFIX)
1694
			PRINT (ox, 2);
1695
 
1696
		/* right-adjusting zero padding */
1697
		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1698
			PAD (width - realsz, zeroes);
1699
 
1700
		/* leading zeroes from decimal precision */
1701
		PAD (dprec - size, zeroes);
1702
 
1703
		/* the string or number proper */
1704
#ifdef FLOATING_POINT
1705
		if ((flags & FPT) == 0) {
1706
			PRINT (cp, size);
1707
		} else {	/* glue together f_p fragments */
1708
			if (ch >= 'f') {	/* 'f' or 'g' */
1709
				if (_fpvalue == 0) {
1710
					/* kludge for __dtoa irregularity */
1711
					PRINT ("0", 1);
1712
					if (expt < ndig || flags & ALT) {
1713
						PRINT (decimal_point, decp_len);
1714
						PAD (ndig - 1, zeroes);
1715
					}
1716
				} else if (expt <= 0) {
1717
					PRINT ("0", 1);
1718
					if (expt || ndig || flags & ALT) {
1719
						PRINT (decimal_point, decp_len);
1720
						PAD (-expt, zeroes);
1721
						PRINT (cp, ndig);
1722
					}
1723
				} else {
1724
					char *convbuf = cp;
1725
					PRINTANDPAD(cp, convbuf + ndig,
1726
						    lead, zeroes);
1727
					cp += lead;
1728
#ifdef _WANT_IO_C99_FORMATS
1729
					if (flags & GROUPING) {
1730
					    while (nseps > 0 || nrepeats > 0) {
1731
						if (nrepeats > 0)
1732
						    nrepeats--;
1733
						else {
1734
						    grouping--;
1735
						    nseps--;
1736
						}
1737
						PRINT(thousands_sep, thsnd_len);
1738
						PRINTANDPAD (cp, convbuf + ndig,
1739
							     *grouping, zeroes);
1740
						cp += *grouping;
1741
					    }
1742
					    if (cp > convbuf + ndig)
1743
						cp = convbuf + ndig;
1744
					}
1745
#endif
1746
					if (expt < ndig || flags & ALT)
1747
					PRINT (decimal_point, decp_len);
1748
					PRINTANDPAD (cp, convbuf + ndig,
1749
						     ndig - expt, zeroes);
1750
				}
1751
			} else {	/* 'a', 'A', 'e', or 'E' */
1752
				if (ndig > 1 || flags & ALT) {
1753
					PRINT (cp, 1);
1754
					cp++;
1755
					PRINT (decimal_point, decp_len);
1756
					if (_fpvalue) {
1757
						PRINT (cp, ndig - 1);
1758
					} else	/* 0.[0..] */
1759
						/* __dtoa irregularity */
1760
						PAD (ndig - 1, zeroes);
1761
				} else	/* XeYYY */
1762
					PRINT (cp, 1);
1763
				PRINT (expstr, expsize);
1764
			}
1765
		}
1766
#else /* !FLOATING_POINT */
1767
		PRINT (cp, size);
1768
#endif
1769
		/* left-adjusting padding (always blank) */
1770
		if (flags & LADJUST)
1771
			PAD (width - realsz, blanks);
1772
 
1773
		/* finally, adjust ret */
1774
		ret += width > realsz ? width : realsz;
1775
 
1776
		FLUSH ();	/* copy out the I/O vectors */
1777
 
1778
                if (malloc_buf != NULL) {
1779
			_free_r (data, malloc_buf);
1780
			malloc_buf = NULL;
1781
		}
1782
	}
1783
done:
1784
	FLUSH ();
1785
error:
1786
	if (malloc_buf != NULL)
1787
		_free_r (data, malloc_buf);
1788
#ifndef STRING_ONLY
4921 Serge 1789
	_newlib_flockfile_end (fp);
4349 Serge 1790
#endif
1791
	return (__sferror (fp) ? EOF : ret);
1792
	/* NOTREACHED */
1793
}
1794
 
1795
#ifdef FLOATING_POINT
1796
 
1797
/* Using reentrant DATA, convert finite VALUE into a string of digits
1798
   with no decimal point, using NDIGITS precision and FLAGS as guides
1799
   to whether trailing zeros must be included.  Set *SIGN to nonzero
1800
   if VALUE was negative.  Set *DECPT to the exponent plus one.  Set
1801
   *LENGTH to the length of the returned string.  CH must be one of
1802
   [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1803
   otherwise the return value shares the mprec reentrant storage.  */
1804
static char *
1805
cvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1806
    char *sign, int *decpt, int ch, int *length, char *buf)
1807
{
1808
	int mode, dsgn;
1809
	char *digits, *bp, *rve;
1810
# ifdef _NO_LONGDBL
1811
	union double_union tmp;
1812
 
1813
	tmp.d = value;
1814
	if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1815
		value = -value;
1816
		*sign = '-';
1817
	} else
1818
		*sign = '\000';
1819
# else /* !_NO_LONGDBL */
1820
	union
1821
	{
1822
	  struct ldieee ieee;
1823
	  _LONG_DOUBLE val;
1824
	} ld;
1825
 
1826
	ld.val = value;
1827
	if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1828
		value = -value;
1829
		*sign = '-';
1830
	} else
1831
		*sign = '\000';
1832
# endif /* !_NO_LONGDBL */
1833
 
1834
# ifdef _WANT_IO_C99_FORMATS
1835
	if (ch == 'a' || ch == 'A') {
1836
		/* This code assumes FLT_RADIX is a power of 2.  The initial
1837
		   division ensures the digit before the decimal will be less
1838
		   than FLT_RADIX (unless it is rounded later).	 There is no
1839
		   loss of precision in these calculations.  */
1840
		value = FREXP (value, decpt) / 8;
1841
		if (!value)
1842
			*decpt = 1;
1843
		digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1844
		bp = buf;
1845
		do {
1846
			value *= 16;
1847
			mode = (int) value;
1848
			value -= mode;
1849
			*bp++ = digits[mode];
1850
		} while (ndigits-- && value);
1851
		if (value > 0.5 || (value == 0.5 && mode & 1)) {
1852
			/* round to even */
1853
			rve = bp;
1854
			while (*--rve == digits[0xf]) {
1855
				*rve = '0';
1856
			}
1857
			*rve = *rve == '9' ? digits[0xa] : *rve + 1;
1858
		} else {
1859
			while (ndigits-- >= 0) {
1860
				*bp++ = '0';
1861
			}
1862
		}
1863
		*length = bp - buf;
1864
		return buf;
1865
	}
1866
# endif /* _WANT_IO_C99_FORMATS */
1867
	if (ch == 'f' || ch == 'F') {
1868
		mode = 3;		/* ndigits after the decimal point */
1869
	} else {
1870
		/* To obtain ndigits after the decimal point for the 'e'
1871
		 * and 'E' formats, round to ndigits + 1 significant
1872
		 * figures.
1873
		 */
1874
		if (ch == 'e' || ch == 'E') {
1875
			ndigits++;
1876
		}
1877
		mode = 2;		/* ndigits significant digits */
1878
	}
1879
 
1880
	digits = _DTOA_R (data, value, mode, ndigits, decpt, &dsgn, &rve);
1881
 
1882
	if ((ch != 'g' && ch != 'G') || flags & ALT) {	/* Print trailing zeros */
1883
		bp = digits + ndigits;
1884
		if (ch == 'f' || ch == 'F') {
1885
			if (*digits == '0' && value)
1886
				*decpt = -ndigits + 1;
1887
			bp += *decpt;
1888
		}
1889
		if (value == 0)	/* kludge for __dtoa irregularity */
1890
			rve = bp;
1891
		while (rve < bp)
1892
			*rve++ = '0';
1893
	}
1894
	*length = rve - digits;
1895
	return (digits);
1896
}
1897
 
1898
static int
1899
exponent(char *p0, int exp, int fmtch)
1900
{
1901
	register char *p, *t;
1902
	char expbuf[MAXEXPLEN];
1903
# ifdef _WANT_IO_C99_FORMATS
1904
	int isa = fmtch == 'a' || fmtch == 'A';
1905
# else
1906
#  define isa 0
1907
# endif
1908
 
1909
	p = p0;
1910
	*p++ = isa ? 'p' - 'a' + fmtch : fmtch;
1911
	if (exp < 0) {
1912
		exp = -exp;
1913
		*p++ = '-';
1914
	}
1915
	else
1916
		*p++ = '+';
1917
	t = expbuf + MAXEXPLEN;
1918
	if (exp > 9) {
1919
		do {
1920
			*--t = to_char (exp % 10);
1921
		} while ((exp /= 10) > 9);
1922
		*--t = to_char (exp);
1923
		for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1924
	}
1925
	else {
1926
		if (!isa)
1927
			*p++ = '0';
1928
		*p++ = to_char (exp);
1929
	}
1930
	return (p - p0);
1931
}
1932
#endif /* FLOATING_POINT */
1933
 
1934
 
1935
#ifndef _NO_POS_ARGS
1936
 
1937
/* Positional argument support.
1938
   Written by Jeff Johnston
1939
 
1940
   Copyright (c) 2002 Red Hat Incorporated.
1941
   All rights reserved.
1942
 
1943
   Redistribution and use in source and binary forms, with or without
1944
   modification, are permitted provided that the following conditions are met:
1945
 
1946
      Redistributions of source code must retain the above copyright
1947
      notice, this list of conditions and the following disclaimer.
1948
 
1949
      Redistributions in binary form must reproduce the above copyright
1950
      notice, this list of conditions and the following disclaimer in the
1951
      documentation and/or other materials provided with the distribution.
1952
 
1953
      The name of Red Hat Incorporated may not be used to endorse
1954
      or promote products derived from this software without specific
1955
      prior written permission.
1956
 
1957
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1958
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1959
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1960
   DISCLAIMED.  IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1961
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1962
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1963
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1964
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1965
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1966
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1967
 
1968
/* The below constant state tables are shared between all versions of
1969
   vfprintf and vfwprintf.  They must only be defined once, which we do in
1970
   the STRING_ONLY/INTEGER_ONLY versions here. */
1971
#if defined (STRING_ONLY) && defined(INTEGER_ONLY)
1972
 
1973
_CONST __CH_CLASS __chclass[256] = {
1974
  /* 00-07 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1975
  /* 08-0f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1976
  /* 10-17 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1977
  /* 18-1f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1978
  /* 20-27 */  FLAG,    OTHER,   OTHER,   FLAG,    DOLLAR,  OTHER,   OTHER,   FLAG,
1979
  /* 28-2f */  OTHER,   OTHER,   STAR,    FLAG,    OTHER,   FLAG,    DOT,     OTHER,
1980
  /* 30-37 */  ZERO,    DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,
1981
  /* 38-3f */  DIGIT,   DIGIT,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1982
  /* 40-47 */  OTHER,   SPEC,    OTHER,   SPEC,    SPEC,    SPEC,    SPEC,    SPEC,
1983
  /* 48-4f */  OTHER,   OTHER,   OTHER,   OTHER,   MODFR,   OTHER,   OTHER,   SPEC,
1984
  /* 50-57 */  OTHER,   OTHER,   OTHER,   SPEC,    OTHER,   SPEC,    OTHER,   OTHER,
1985
  /* 58-5f */  SPEC,    OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1986
  /* 60-67 */  OTHER,   SPEC,    OTHER,   SPEC,    SPEC,    SPEC,    SPEC,    SPEC,
1987
  /* 68-6f */  MODFR,   SPEC,    MODFR,   OTHER,   MODFR,   OTHER,   SPEC,    SPEC,
1988
  /* 70-77 */  SPEC,    MODFR,   OTHER,   SPEC,    MODFR,   SPEC,    OTHER,   OTHER,
1989
  /* 78-7f */  SPEC,    OTHER,   MODFR,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1990
  /* 80-87 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1991
  /* 88-8f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1992
  /* 90-97 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1993
  /* 98-9f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1994
  /* a0-a7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1995
  /* a8-af */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1996
  /* b0-b7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1997
  /* b8-bf */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1998
  /* c0-c7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1999
  /* c8-cf */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2000
  /* d0-d7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2001
  /* d8-df */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2002
  /* e0-e7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2003
  /* e8-ef */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2004
  /* f0-f7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2005
  /* f8-ff */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
2006
};
2007
 
2008
_CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS] = {
2009
  /*             '0'     '1-9'     '$'     MODFR    SPEC    '.'     '*'    FLAG    OTHER */
2010
  /* START */  { SFLAG,   WDIG,    DONE,   SMOD,    DONE,   SDOT,  VARW,   SFLAG,  DONE },
2011
  /* SFLAG */  { SFLAG,   WDIG,    DONE,   SMOD,    DONE,   SDOT,  VARW,   SFLAG,  DONE },
2012
  /* WDIG  */  { DONE,    DONE,    WIDTH,  SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2013
  /* WIDTH */  { DONE,    DONE,    DONE,   SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2014
  /* SMOD  */  { DONE,    DONE,    DONE,   DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2015
  /* SDOT  */  { SDOT,    PREC,    DONE,   SMOD,    DONE,   DONE,  VARP,   DONE,   DONE },
2016
  /* VARW  */  { DONE,    VWDIG,   DONE,   SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
2017
  /* VARP  */  { DONE,    VPDIG,   DONE,   SMOD,    DONE,   DONE,  DONE,   DONE,   DONE },
2018
  /* PREC  */  { DONE,    DONE,    DONE,   SMOD,    DONE,   DONE,  DONE,   DONE,   DONE },
2019
  /* VWDIG */  { DONE,    DONE,    WIDTH,  DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2020
  /* VPDIG */  { DONE,    DONE,    PREC,   DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
2021
};
2022
 
2023
_CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS] = {
2024
  /*             '0'     '1-9'     '$'     MODFR    SPEC    '.'     '*'    FLAG    OTHER */
2025
  /* START */  { NOOP,    NUMBER,  NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2026
  /* SFLAG */  { NOOP,    NUMBER,  NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2027
  /* WDIG  */  { NOOP,    NOOP,    GETPOS, GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2028
  /* WIDTH */  { NOOP,    NOOP,    NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2029
  /* SMOD  */  { NOOP,    NOOP,    NOOP,   NOOP,    GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2030
  /* SDOT  */  { NOOP,    SKIPNUM, NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2031
  /* VARW  */  { NOOP,    NUMBER,  NOOP,   GETPW,   GETPWB, GETPW, NOOP,   NOOP,   NOOP },
2032
  /* VARP  */  { NOOP,    NUMBER,  NOOP,   GETPW,   GETPWB, NOOP,  NOOP,   NOOP,   NOOP },
2033
  /* PREC  */  { NOOP,    NOOP,    NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
2034
  /* VWDIG */  { NOOP,    NOOP,    PWPOS,  NOOP,    NOOP,   NOOP,  NOOP,   NOOP,   NOOP },
2035
  /* VPDIG */  { NOOP,    NOOP,    PWPOS,  NOOP,    NOOP,   NOOP,  NOOP,   NOOP,   NOOP },
2036
};
2037
 
2038
#endif /* STRING_ONLY && INTEGER_ONLY */
2039
 
2040
/* function to get positional parameter N where n = N - 1 */
2041
static union arg_val *
2042
_DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
2043
       struct _reent *data _AND
2044
       int n               _AND
2045
       char *fmt           _AND
2046
       va_list *ap         _AND
2047
       int *numargs_p      _AND
2048
       union arg_val *args _AND
2049
       int *arg_type       _AND
2050
       char **last_fmt)
2051
{
2052
  int ch;
2053
  int number, flags;
2054
  int spec_type;
2055
  int numargs = *numargs_p;
2056
  __CH_CLASS chtype;
2057
  __STATE state, next_state;
2058
  __ACTION action;
2059
  int pos, last_arg;
2060
  int max_pos_arg = n;
2061
  /* Only need types that can be reached via vararg promotions.  */
2062
  enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
2063
# ifdef _MB_CAPABLE
2064
  wchar_t wc;
2065
  mbstate_t wc_state;
2066
  int nbytes;
2067
# endif
2068
 
2069
  /* if this isn't the first call, pick up where we left off last time */
2070
  if (*last_fmt != NULL)
2071
    fmt = *last_fmt;
2072
 
2073
# ifdef _MB_CAPABLE
2074
  memset (&wc_state, '\0', sizeof (wc_state));
2075
# endif
2076
 
2077
  /* we need to process either to end of fmt string or until we have actually
2078
     read the desired parameter from the vararg list. */
2079
  while (*fmt && n >= numargs)
2080
    {
2081
# ifdef _MB_CAPABLE
2082
      while ((nbytes = __mbtowc (data, &wc, fmt, MB_CUR_MAX,
2083
				 __locale_charset (), &wc_state)) > 0)
2084
	{
2085
	  fmt += nbytes;
2086
	  if (wc == '%')
2087
	    break;
2088
	}
2089
 
2090
      if (nbytes <= 0)
2091
	break;
2092
# else
2093
      while (*fmt != '\0' && *fmt != '%')
2094
	fmt += 1;
2095
 
2096
      if (*fmt == '\0')
2097
	break;
2098
# endif /* ! _MB_CAPABLE */
2099
      state = START;
2100
      flags = 0;
2101
      pos = -1;
2102
      number = 0;
2103
      spec_type = INT;
2104
 
2105
      /* Use state/action table to process format specifiers.  We ignore invalid
2106
         formats and we are only interested in information that tells us how to
2107
         read the vararg list. */
2108
      while (state != DONE)
2109
	{
2110
	  ch = *fmt++;
2111
	  chtype = __chclass[ch];
2112
	  next_state = __state_table[state][chtype];
2113
	  action = __action_table[state][chtype];
2114
	  state = next_state;
2115
 
2116
	  switch (action)
2117
	    {
2118
	    case GETMOD:  /* we have format modifier */
2119
	      switch (ch)
2120
		{
2121
		case 'h':
2122
		  /* No flag needed, since short and char promote to int.  */
2123
		  break;
2124
		case 'L':
2125
		  flags |= LONGDBL;
2126
		  break;
2127
		case 'q':
2128
		  flags |= QUADINT;
2129
		  break;
2130
# ifdef _WANT_IO_C99_FORMATS
2131
		case 'j':
2132
		  if (sizeof (intmax_t) == sizeof (long))
2133
		    flags |= LONGINT;
2134
		  else
2135
		    flags |= QUADINT;
2136
		  break;
2137
		case 'z':
2138
		  if (sizeof (size_t) <= sizeof (int))
2139
		    /* no flag needed */;
2140
		  else if (sizeof (size_t) <= sizeof (long))
2141
		    flags |= LONGINT;
2142
		  else
2143
		    /* POSIX states that at least one programming
2144
		       environment must support size_t no wider than
2145
		       long, but that means other environments can
2146
		       have size_t as wide as long long.  */
2147
		    flags |= QUADINT;
2148
		  break;
2149
		case 't':
2150
		  if (sizeof (ptrdiff_t) <= sizeof (int))
2151
		    /* no flag needed */;
2152
		  else if (sizeof (ptrdiff_t) <= sizeof (long))
2153
		    flags |= LONGINT;
2154
		  else
2155
		    /* POSIX states that at least one programming
2156
		       environment must support ptrdiff_t no wider than
2157
		       long, but that means other environments can
2158
		       have ptrdiff_t as wide as long long.  */
2159
		    flags |= QUADINT;
2160
		  break;
2161
# endif /* _WANT_IO_C99_FORMATS */
2162
		case 'l':
2163
		default:
2164
# if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
2165
		  if (*fmt == 'l')
2166
		    {
2167
		      flags |= QUADINT;
2168
		      ++fmt;
2169
		    }
2170
		  else
2171
# endif
2172
		    flags |= LONGINT;
2173
		  break;
2174
		}
2175
	      break;
2176
	    case GETARG: /* we have format specifier */
2177
	      {
2178
		numargs &= (MAX_POS_ARGS - 1);
2179
		/* process the specifier and translate it to a type to fetch from varargs */
2180
		switch (ch)
2181
		  {
2182
		  case 'd':
2183
		  case 'i':
2184
		  case 'o':
2185
		  case 'x':
2186
		  case 'X':
2187
		  case 'u':
2188
		    if (flags & LONGINT)
2189
		      spec_type = LONG_INT;
2190
# ifndef _NO_LONGLONG
2191
		    else if (flags & QUADINT)
2192
		      spec_type = QUAD_INT;
2193
# endif
2194
		    else
2195
		      spec_type = INT;
2196
		    break;
2197
		  case 'D':
2198
		  case 'U':
2199
		  case 'O':
2200
		    spec_type = LONG_INT;
2201
		    break;
2202
# ifdef _WANT_IO_C99_FORMATS
2203
		  case 'a':
2204
		  case 'A':
2205
		  case 'F':
2206
# endif
2207
		  case 'f':
2208
		  case 'g':
2209
		  case 'G':
2210
		  case 'E':
2211
		  case 'e':
2212
# ifndef _NO_LONGDBL
2213
		    if (flags & LONGDBL)
2214
		      spec_type = LONG_DOUBLE;
2215
		    else
2216
# endif
2217
		      spec_type = DOUBLE;
2218
		    break;
2219
		  case 's':
2220
# ifdef _WANT_IO_C99_FORMATS
2221
		  case 'S':
2222
# endif
2223
		  case 'p':
2224
		  case 'n':
2225
		    spec_type = CHAR_PTR;
2226
		    break;
2227
		  case 'c':
2228
# ifdef _WANT_IO_C99_FORMATS
2229
		    if (flags & LONGINT)
2230
		      spec_type = WIDE_CHAR;
2231
		    else
2232
# endif
2233
		      spec_type = INT;
2234
		    break;
2235
# ifdef _WANT_IO_C99_FORMATS
2236
		  case 'C':
2237
		    spec_type = WIDE_CHAR;
2238
		    break;
2239
# endif
2240
		  }
2241
 
2242
		/* if we have a positional parameter, just store the type, otherwise
2243
		   fetch the parameter from the vararg list */
2244
		if (pos != -1)
2245
		  arg_type[pos] = spec_type;
2246
		else
2247
		  {
2248
		    switch (spec_type)
2249
		      {
2250
		      case LONG_INT:
2251
			args[numargs++].val_long = va_arg (*ap, long);
2252
			break;
2253
		      case QUAD_INT:
2254
			args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2255
			break;
2256
		      case WIDE_CHAR:
2257
			args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2258
			break;
2259
		      case INT:
2260
			args[numargs++].val_int = va_arg (*ap, int);
2261
			break;
2262
		      case CHAR_PTR:
2263
			args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2264
			break;
2265
		      case DOUBLE:
2266
			args[numargs++].val_double = va_arg (*ap, double);
2267
			break;
2268
		      case LONG_DOUBLE:
2269
			args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2270
			break;
2271
		      }
2272
		  }
2273
	      }
2274
	      break;
2275
	    case GETPOS: /* we have positional specifier */
2276
	      if (arg_type[0] == -1)
2277
		memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2278
	      pos = number - 1;
2279
	      max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
2280
	      break;
2281
	    case PWPOS:  /* we have positional specifier for width or precision */
2282
	      if (arg_type[0] == -1)
2283
		memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2284
	      number -= 1;
2285
	      arg_type[number] = INT;
2286
	      max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
2287
	      break;
2288
	    case GETPWB: /* we require format pushback */
2289
	      --fmt;
2290
	      /* fallthrough */
2291
	    case GETPW:  /* we have a variable precision or width to acquire */
2292
	      args[numargs++].val_int = va_arg (*ap, int);
2293
	      break;
2294
	    case NUMBER: /* we have a number to process */
2295
	      number = (ch - '0');
2296
	      while ((ch = *fmt) != '\0' && is_digit (ch))
2297
		{
2298
		  number = number * 10 + (ch - '0');
2299
		  ++fmt;
2300
		}
2301
	      break;
2302
	    case SKIPNUM: /* we have a number to skip */
2303
	      while ((ch = *fmt) != '\0' && is_digit (ch))
2304
		++fmt;
2305
	      break;
2306
	    case NOOP:
2307
	    default:
2308
	      break; /* do nothing */
2309
	    }
2310
	}
2311
    }
2312
 
2313
  /* process all arguments up to at least the one we are looking for and if we
2314
     have seen the end of the string, then process up to the max argument needed */
2315
  if (*fmt == '\0')
2316
    last_arg = max_pos_arg;
2317
  else
2318
    last_arg = n;
2319
 
2320
  while (numargs <= last_arg)
2321
    {
2322
      switch (arg_type[numargs])
2323
	{
2324
	case LONG_INT:
2325
	  args[numargs++].val_long = va_arg (*ap, long);
2326
	  break;
2327
	case QUAD_INT:
2328
	  args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2329
	  break;
2330
	case CHAR_PTR:
2331
	  args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2332
	  break;
2333
	case DOUBLE:
2334
	  args[numargs++].val_double = va_arg (*ap, double);
2335
	  break;
2336
	case LONG_DOUBLE:
2337
	  args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2338
	  break;
2339
	case WIDE_CHAR:
2340
	  args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2341
	  break;
2342
	case INT:
2343
	default:
2344
	  args[numargs++].val_int = va_arg (*ap, int);
2345
	  break;
2346
	}
2347
    }
2348
 
2349
  /* alter the global numargs value and keep a reference to the last bit of the fmt
2350
     string we processed here because the caller will continue processing where we started */
2351
  *numargs_p = numargs;
2352
  *last_fmt = fmt;
2353
  return &args[n];
2354
}
2355
#endif /* !_NO_POS_ARGS */