Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5563 serge 1
/*
2
 * Copyright (c) 1995 Patrick Powell.
3
 *
4
 * This code is based on code written by Patrick Powell .
5
 * It may be used for any purpose as long as this notice remains intact on all
6
 * source code distributions.
7
 */
8
 
9
/*
10
 * Copyright (c) 2008 Holger Weiss.
11
 *
12
 * This version of the code is maintained by Holger Weiss .
13
 * My changes to the code may freely be used, modified and/or redistributed for
14
 * any purpose.  It would be nice if additions and fixes to this file (including
15
 * trivial code cleanups) would be sent back in order to let me include them in
16
 * the version available at .
17
 * However, this is not a requirement for using or redistributing (possibly
18
 * modified) versions of this file, nor is leaving this notice intact mandatory.
19
 */
20
 
21
/*
22
 * History
23
 *
24
 * 2008-01-20 Holger Weiss  for C99-snprintf 1.1:
25
 *
26
 * 	Fixed the detection of infinite floating point values on IRIX (and
27
 * 	possibly other systems) and applied another few minor cleanups.
28
 *
29
 * 2008-01-06 Holger Weiss  for C99-snprintf 1.0:
30
 *
31
 * 	Added a lot of new features, fixed many bugs, and incorporated various
32
 * 	improvements done by Andrew Tridgell , Russ Allbery
33
 * 	, Hrvoje Niksic , Damien Miller
34
 * 	, and others for the Samba, INN, Wget, and OpenSSH
35
 * 	projects.  The additions include: support the "e", "E", "g", "G", and
36
 * 	"F" conversion specifiers (and use conversion style "f" or "F" for the
37
 * 	still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
38
 * 	"t", and "z" length modifiers; support the "#" flag and the (non-C99)
39
 * 	"'" flag; use localeconv(3) (if available) to get both the current
40
 * 	locale's decimal point character and the separator between groups of
41
 * 	digits; fix the handling of various corner cases of field width and
42
 * 	precision specifications; fix various floating point conversion bugs;
43
 * 	handle infinite and NaN floating point values; don't attempt to write to
44
 * 	the output buffer (which may be NULL) if a size of zero was specified;
45
 * 	check for integer overflow of the field width, precision, and return
46
 * 	values and during the floating point conversion; use the OUTCHAR() macro
47
 * 	instead of a function for better performance; provide asprintf(3) and
48
 * 	vasprintf(3) functions; add new test cases.  The replacement functions
49
 * 	have been renamed to use an "rpl_" prefix, the function calls in the
50
 * 	main project (and in this file) must be redefined accordingly for each
51
 * 	replacement function which is needed (by using Autoconf or other means).
52
 * 	Various other minor improvements have been applied and the coding style
53
 * 	was cleaned up for consistency.
54
 *
55
 * 2007-07-23 Holger Weiss  for Mutt 1.5.13:
56
 *
57
 * 	C99 compliant snprintf(3) and vsnprintf(3) functions return the number
58
 * 	of characters that would have been written to a sufficiently sized
59
 * 	buffer (excluding the '\0').  The original code simply returned the
60
 * 	length of the resulting output string, so that's been fixed.
61
 *
62
 * 1998-03-05 Michael Elkins  for Mutt 0.90.8:
63
 *
64
 * 	The original code assumed that both snprintf(3) and vsnprintf(3) were
65
 * 	missing.  Some systems only have snprintf(3) but not vsnprintf(3), so
66
 * 	the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
67
 *
68
 * 1998-01-27 Thomas Roessler  for Mutt 0.89i:
69
 *
70
 * 	The PGP code was using unsigned hexadecimal formats.  Unfortunately,
71
 * 	unsigned formats simply didn't work.
72
 *
73
 * 1997-10-22 Brandon Long  for Mutt 0.87.1:
74
 *
75
 * 	Ok, added some minimal floating point support, which means this probably
76
 * 	requires libm on most operating systems.  Don't yet support the exponent
77
 * 	(e,E) and sigfig (g,G).  Also, fmtint() was pretty badly broken, it just
78
 * 	wasn't being exercised in ways which showed it, so that's been fixed.
79
 * 	Also, formatted the code to Mutt conventions, and removed dead code left
80
 * 	over from the original.  Also, there is now a builtin-test, run with:
81
 * 	gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
82
 *
83
 * 2996-09-15 Brandon Long  for Mutt 0.43:
84
 *
85
 * 	This was ugly.  It is still ugly.  I opted out of floating point
86
 * 	numbers, but the formatter understands just about everything from the
87
 * 	normal C string format, at least as far as I can tell from the Solaris
88
 * 	2.5 printf(3S) man page.
89
 */
90
 
91
/*
92
 * ToDo
93
 *
94
 * - Add wide character support.
95
 * - Add support for "%a" and "%A" conversions.
96
 * - Create test routines which predefine the expected results.  Our test cases
97
 *   usually expose bugs in system implementations rather than in ours :-)
98
 */
99
 
100
/*
101
 * Usage
102
 *
103
 * 1) The following preprocessor macros should be defined to 1 if the feature or
104
 *    file in question is available on the target system (by using Autoconf or
105
 *    other means), though basic functionality should be available as long as
106
 *    HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
107
 *
108
 *    	HAVE_VSNPRINTF
109
 *    	HAVE_SNPRINTF
110
 *    	HAVE_VASPRINTF
111
 *    	HAVE_ASPRINTF
112
 *    	HAVE_STDARG_H
113
 *    	HAVE_STDDEF_H
114
 *    	HAVE_STDINT_H
115
 *    	HAVE_STDLIB_H
116
 *    	HAVE_INTTYPES_H
117
 *    	HAVE_LOCALE_H
118
 *    	HAVE_LOCALECONV
119
 *    	HAVE_LCONV_DECIMAL_POINT
120
 *    	HAVE_LCONV_THOUSANDS_SEP
121
 *    	HAVE_LONG_DOUBLE
122
 *    	HAVE_LONG_LONG_INT
123
 *    	HAVE_UNSIGNED_LONG_LONG_INT
124
 *    	HAVE_INTMAX_T
125
 *    	HAVE_UINTMAX_T
126
 *    	HAVE_UINTPTR_T
127
 *    	HAVE_PTRDIFF_T
128
 *    	HAVE_VA_COPY
129
 *    	HAVE___VA_COPY
130
 *
131
 * 2) The calls to the functions which should be replaced must be redefined
132
 *    throughout the project files (by using Autoconf or other means):
133
 *
134
 *    	#define vsnprintf rpl_vsnprintf
135
 *    	#define snprintf rpl_snprintf
136
 *    	#define vasprintf rpl_vasprintf
137
 *    	#define asprintf rpl_asprintf
138
 *
139
 * 3) The required replacement functions should be declared in some header file
140
 *    included throughout the project files:
141
 *
142
 *    	#if HAVE_CONFIG_H
143
 *    	#include 
144
 *    	#endif
145
 *    	#if HAVE_STDARG_H
146
 *    	#include 
147
 *    	#if !HAVE_VSNPRINTF
148
 *    	int rpl_vsnprintf(char *, size_t, const char *, va_list);
149
 *    	#endif
150
 *    	#if !HAVE_SNPRINTF
151
 *    	int rpl_snprintf(char *, size_t, const char *, ...);
152
 *    	#endif
153
 *    	#if !HAVE_VASPRINTF
154
 *    	int rpl_vasprintf(char **, const char *, va_list);
155
 *    	#endif
156
 *    	#if !HAVE_ASPRINTF
157
 *    	int rpl_asprintf(char **, const char *, ...);
158
 *    	#endif
159
 *    	#endif
160
 *
161
 * Autoconf macros for handling step 1 and step 2 are available at
162
 * .
163
 */
164
 
165
#include "pipe/p_config.h"
166
 
167
#if HAVE_CONFIG_H
168
#include 
169
#else
170
#ifdef _MSC_VER
171
#define vsnprintf util_vsnprintf
172
#define snprintf util_snprintf
173
#define HAVE_VSNPRINTF 0
174
#define HAVE_SNPRINTF 0
175
#define HAVE_VASPRINTF 1 /* not needed */
176
#define HAVE_ASPRINTF 1 /* not needed */
177
#define HAVE_STDARG_H 1
178
#define HAVE_STDDEF_H 1
179
#define HAVE_STDINT_H 0
180
#define HAVE_STDLIB_H 1
181
#define HAVE_INTTYPES_H 0
182
#define HAVE_LOCALE_H 0
183
#define HAVE_LOCALECONV 0
184
#define HAVE_LCONV_DECIMAL_POINT 0
185
#define HAVE_LCONV_THOUSANDS_SEP 0
186
#define HAVE_LONG_DOUBLE 0
187
#define HAVE_LONG_LONG_INT 1
188
#define HAVE_UNSIGNED_LONG_LONG_INT 1
189
#define HAVE_INTMAX_T 0
190
#define HAVE_UINTMAX_T 0
191
#define HAVE_UINTPTR_T 1
192
#define HAVE_PTRDIFF_T 1
193
#define HAVE_VA_COPY 0
194
#define HAVE___VA_COPY 0
195
#else
196
#define HAVE_VSNPRINTF 1
197
#define HAVE_SNPRINTF 1
198
#define HAVE_VASPRINTF 1
199
#define HAVE_ASPRINTF 1
200
#endif
201
#endif	/* HAVE_CONFIG_H */
202
 
203
#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
204
#include 	/* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
205
#ifdef VA_START
206
#undef VA_START
207
#endif	/* defined(VA_START) */
208
#ifdef VA_SHIFT
209
#undef VA_SHIFT
210
#endif	/* defined(VA_SHIFT) */
211
#if HAVE_STDARG_H
212
#include 
213
#define VA_START(ap, last) va_start(ap, last)
214
#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
215
#else	/* Assume  is available. */
216
#include 
217
#define VA_START(ap, last) va_start(ap)	/* "last" is ignored. */
218
#define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
219
#endif	/* HAVE_STDARG_H */
220
 
221
#if !HAVE_VASPRINTF
222
#if HAVE_STDLIB_H
223
#include 	/* For malloc(3). */
224
#endif	/* HAVE_STDLIB_H */
225
#ifdef VA_COPY
226
#undef VA_COPY
227
#endif	/* defined(VA_COPY) */
228
#ifdef VA_END_COPY
229
#undef VA_END_COPY
230
#endif	/* defined(VA_END_COPY) */
231
#if HAVE_VA_COPY
232
#define VA_COPY(dest, src) va_copy(dest, src)
233
#define VA_END_COPY(ap) va_end(ap)
234
#elif HAVE___VA_COPY
235
#define VA_COPY(dest, src) __va_copy(dest, src)
236
#define VA_END_COPY(ap) va_end(ap)
237
#else
238
#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
239
#define VA_END_COPY(ap) /* No-op. */
240
#define NEED_MYMEMCPY 1
241
static void *mymemcpy(void *, void *, size_t);
242
#endif	/* HAVE_VA_COPY */
243
#endif	/* !HAVE_VASPRINTF */
244
 
245
#if !HAVE_VSNPRINTF
246
#include 	/* For *_MAX. */
247
#if HAVE_INTTYPES_H
248
#include 	/* For intmax_t (if not defined in ). */
249
#endif	/* HAVE_INTTYPES_H */
250
#if HAVE_LOCALE_H
251
#include 	/* For localeconv(3). */
252
#endif	/* HAVE_LOCALE_H */
253
#if HAVE_STDDEF_H
254
#include 	/* For ptrdiff_t. */
255
#endif	/* HAVE_STDDEF_H */
256
#if HAVE_STDINT_H
257
#include 	/* For intmax_t. */
258
#endif	/* HAVE_STDINT_H */
259
 
260
/* Support for unsigned long long int.  We may also need ULLONG_MAX. */
261
#ifndef ULONG_MAX	/* We may need ULONG_MAX as a fallback. */
262
#ifdef UINT_MAX
263
#define ULONG_MAX UINT_MAX
264
#else
265
#define ULONG_MAX INT_MAX
266
#endif	/* defined(UINT_MAX) */
267
#endif	/* !defined(ULONG_MAX) */
268
#ifdef ULLONG
269
#undef ULLONG
270
#endif	/* defined(ULLONG) */
271
#if HAVE_UNSIGNED_LONG_LONG_INT
272
#define ULLONG unsigned long long int
273
#ifndef ULLONG_MAX
274
#define ULLONG_MAX ULONG_MAX
275
#endif	/* !defined(ULLONG_MAX) */
276
#else
277
#define ULLONG unsigned long int
278
#ifdef ULLONG_MAX
279
#undef ULLONG_MAX
280
#endif	/* defined(ULLONG_MAX) */
281
#define ULLONG_MAX ULONG_MAX
282
#endif	/* HAVE_LONG_LONG_INT */
283
 
284
/* Support for uintmax_t.  We also need UINTMAX_MAX. */
285
#ifdef UINTMAX_T
286
#undef UINTMAX_T
287
#endif	/* defined(UINTMAX_T) */
288
#if HAVE_UINTMAX_T || defined(uintmax_t)
289
#define UINTMAX_T uintmax_t
290
#ifndef UINTMAX_MAX
291
#define UINTMAX_MAX ULLONG_MAX
292
#endif	/* !defined(UINTMAX_MAX) */
293
#else
294
#define UINTMAX_T ULLONG
295
#ifdef UINTMAX_MAX
296
#undef UINTMAX_MAX
297
#endif	/* defined(UINTMAX_MAX) */
298
#define UINTMAX_MAX ULLONG_MAX
299
#endif	/* HAVE_UINTMAX_T || defined(uintmax_t) */
300
 
301
/* Support for long double. */
302
#ifndef LDOUBLE
303
#if HAVE_LONG_DOUBLE
304
#define LDOUBLE long double
305
#else
306
#define LDOUBLE double
307
#endif	/* HAVE_LONG_DOUBLE */
308
#endif	/* !defined(LDOUBLE) */
309
 
310
/* Support for long long int. */
311
#ifndef LLONG
312
#if HAVE_LONG_LONG_INT
313
#define LLONG long long int
314
#else
315
#define LLONG long int
316
#endif	/* HAVE_LONG_LONG_INT */
317
#endif	/* !defined(LLONG) */
318
 
319
/* Support for intmax_t. */
320
#ifndef INTMAX_T
321
#if HAVE_INTMAX_T || defined(intmax_t)
322
#define INTMAX_T intmax_t
323
#else
324
#define INTMAX_T LLONG
325
#endif	/* HAVE_INTMAX_T || defined(intmax_t) */
326
#endif	/* !defined(INTMAX_T) */
327
 
328
/* Support for uintptr_t. */
329
#ifndef UINTPTR_T
330
#if HAVE_UINTPTR_T || defined(uintptr_t)
331
#define UINTPTR_T uintptr_t
332
#else
333
#define UINTPTR_T unsigned long int
334
#endif	/* HAVE_UINTPTR_T || defined(uintptr_t) */
335
#endif	/* !defined(UINTPTR_T) */
336
 
337
/* WinCE5.0 does not have uintptr_t defined */
338
#if (_WIN32_WCE < 600)
339
#ifdef UINTPTR_T
340
#undef UINTPTR_T
341
#endif
342
#define UINTPTR_T unsigned long int
343
#endif
344
 
345
 
346
/* Support for ptrdiff_t. */
347
#ifndef PTRDIFF_T
348
#if HAVE_PTRDIFF_T || defined(ptrdiff_t)
349
#define PTRDIFF_T ptrdiff_t
350
#else
351
#define PTRDIFF_T long int
352
#endif	/* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
353
#endif	/* !defined(PTRDIFF_T) */
354
 
355
/*
356
 * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
357
 * 7.19.6.1, 7).  However, we'll simply use PTRDIFF_T and convert it to an
358
 * unsigned type if necessary.  This should work just fine in practice.
359
 */
360
#ifndef UPTRDIFF_T
361
#define UPTRDIFF_T PTRDIFF_T
362
#endif	/* !defined(UPTRDIFF_T) */
363
 
364
/*
365
 * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
366
 * However, we'll simply use size_t and convert it to a signed type if
367
 * necessary.  This should work just fine in practice.
368
 */
369
#ifndef SSIZE_T
370
#define SSIZE_T size_t
371
#endif	/* !defined(SSIZE_T) */
372
 
373
/* Either ERANGE or E2BIG should be available everywhere. */
374
#ifndef ERANGE
375
#define ERANGE E2BIG
376
#endif	/* !defined(ERANGE) */
377
#ifndef EOVERFLOW
378
#define EOVERFLOW ERANGE
379
#endif	/* !defined(EOVERFLOW) */
380
 
381
/*
382
 * Buffer size to hold the octal string representation of UINT128_MAX without
383
 * nul-termination ("3777777777777777777777777777777777777777777").
384
 */
385
#ifdef MAX_CONVERT_LENGTH
386
#undef MAX_CONVERT_LENGTH
387
#endif	/* defined(MAX_CONVERT_LENGTH) */
388
#define MAX_CONVERT_LENGTH      43
389
 
390
/* Format read states. */
391
#define PRINT_S_DEFAULT         0
392
#define PRINT_S_FLAGS           1
393
#define PRINT_S_WIDTH           2
394
#define PRINT_S_DOT             3
395
#define PRINT_S_PRECISION       4
396
#define PRINT_S_MOD             5
397
#define PRINT_S_CONV            6
398
 
399
/* Format flags. */
400
#define PRINT_F_MINUS           (1 << 0)
401
#define PRINT_F_PLUS            (1 << 1)
402
#define PRINT_F_SPACE           (1 << 2)
403
#define PRINT_F_NUM             (1 << 3)
404
#define PRINT_F_ZERO            (1 << 4)
405
#define PRINT_F_QUOTE           (1 << 5)
406
#define PRINT_F_UP              (1 << 6)
407
#define PRINT_F_UNSIGNED        (1 << 7)
408
#define PRINT_F_TYPE_G          (1 << 8)
409
#define PRINT_F_TYPE_E          (1 << 9)
410
 
411
/* Conversion flags. */
412
#define PRINT_C_CHAR            1
413
#define PRINT_C_SHORT           2
414
#define PRINT_C_LONG            3
415
#define PRINT_C_LLONG           4
416
#define PRINT_C_LDOUBLE         5
417
#define PRINT_C_SIZE            6
418
#define PRINT_C_PTRDIFF         7
419
#define PRINT_C_INTMAX          8
420
 
421
#ifndef MAX
422
#define MAX(x, y) ((x >= y) ? x : y)
423
#endif	/* !defined(MAX) */
424
#ifndef CHARTOINT
425
#define CHARTOINT(ch) (ch - '0')
426
#endif	/* !defined(CHARTOINT) */
427
#ifndef ISDIGIT
428
#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
429
#endif	/* !defined(ISDIGIT) */
430
#ifndef ISNAN
431
#define ISNAN(x) (x != x)
432
#endif	/* !defined(ISNAN) */
433
#ifndef ISINF
434
#define ISINF(x) (x != 0.0 && x + x == x)
435
#endif	/* !defined(ISINF) */
436
 
437
#ifdef OUTCHAR
438
#undef OUTCHAR
439
#endif	/* defined(OUTCHAR) */
440
#define OUTCHAR(str, len, size, ch)                                          \
441
do {                                                                         \
442
	if (len + 1 < size)                                                  \
443
		str[len] = ch;                                               \
444
	(len)++;                                                             \
445
} while (/* CONSTCOND */ 0)
446
 
447
static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
448
static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
449
static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
450
static void printsep(char *, size_t *, size_t);
451
static int getnumsep(int);
452
static int getexponent(LDOUBLE);
453
static int convert(UINTMAX_T, char *, size_t, int, int);
454
static UINTMAX_T cast(LDOUBLE);
455
static UINTMAX_T myround(LDOUBLE);
456
static LDOUBLE mypow10(int);
457
 
458
int
459
util_vsnprintf(char *str, size_t size, const char *format, va_list args)
460
{
461
	LDOUBLE fvalue;
462
	INTMAX_T value;
463
	unsigned char cvalue;
464
	const char *strvalue;
465
	INTMAX_T *intmaxptr;
466
	PTRDIFF_T *ptrdiffptr;
467
	SSIZE_T *sizeptr;
468
	LLONG *llongptr;
469
	long int *longptr;
470
	int *intptr;
471
	short int *shortptr;
472
	signed char *charptr;
473
	size_t len = 0;
474
	int overflow = 0;
475
	int base = 0;
476
	int cflags = 0;
477
	int flags = 0;
478
	int width = 0;
479
	int precision = -1;
480
	int state = PRINT_S_DEFAULT;
481
	char ch = *format++;
482
 
483
	/*
484
	 * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
485
	 * pointer." (7.19.6.5, 2)  We're forgiving and allow a NULL pointer
486
	 * even if a size larger than zero was specified.  At least NetBSD's
487
	 * snprintf(3) does the same, as well as other versions of this file.
488
	 * (Though some of these versions will write to a non-NULL buffer even
489
	 * if a size of zero was specified, which violates the standard.)
490
	 */
491
	if (str == NULL && size != 0)
492
		size = 0;
493
 
494
	while (ch != '\0')
495
		switch (state) {
496
		case PRINT_S_DEFAULT:
497
			if (ch == '%')
498
				state = PRINT_S_FLAGS;
499
			else
500
				OUTCHAR(str, len, size, ch);
501
			ch = *format++;
502
			break;
503
		case PRINT_S_FLAGS:
504
			switch (ch) {
505
			case '-':
506
				flags |= PRINT_F_MINUS;
507
				ch = *format++;
508
				break;
509
			case '+':
510
				flags |= PRINT_F_PLUS;
511
				ch = *format++;
512
				break;
513
			case ' ':
514
				flags |= PRINT_F_SPACE;
515
				ch = *format++;
516
				break;
517
			case '#':
518
				flags |= PRINT_F_NUM;
519
				ch = *format++;
520
				break;
521
			case '0':
522
				flags |= PRINT_F_ZERO;
523
				ch = *format++;
524
				break;
525
			case '\'':	/* SUSv2 flag (not in C99). */
526
				flags |= PRINT_F_QUOTE;
527
				ch = *format++;
528
				break;
529
			default:
530
				state = PRINT_S_WIDTH;
531
				break;
532
			}
533
			break;
534
		case PRINT_S_WIDTH:
535
			if (ISDIGIT(ch)) {
536
				ch = CHARTOINT(ch);
537
				if (width > (INT_MAX - ch) / 10) {
538
					overflow = 1;
539
					goto out;
540
				}
541
				width = 10 * width + ch;
542
				ch = *format++;
543
			} else if (ch == '*') {
544
				/*
545
				 * C99 says: "A negative field width argument is
546
				 * taken as a `-' flag followed by a positive
547
				 * field width." (7.19.6.1, 5)
548
				 */
549
				if ((width = va_arg(args, int)) < 0) {
550
					flags |= PRINT_F_MINUS;
551
					width = -width;
552
				}
553
				ch = *format++;
554
				state = PRINT_S_DOT;
555
			} else
556
				state = PRINT_S_DOT;
557
			break;
558
		case PRINT_S_DOT:
559
			if (ch == '.') {
560
				state = PRINT_S_PRECISION;
561
				ch = *format++;
562
			} else
563
				state = PRINT_S_MOD;
564
			break;
565
		case PRINT_S_PRECISION:
566
			if (precision == -1)
567
				precision = 0;
568
			if (ISDIGIT(ch)) {
569
				ch = CHARTOINT(ch);
570
				if (precision > (INT_MAX - ch) / 10) {
571
					overflow = 1;
572
					goto out;
573
				}
574
				precision = 10 * precision + ch;
575
				ch = *format++;
576
			} else if (ch == '*') {
577
				/*
578
				 * C99 says: "A negative precision argument is
579
				 * taken as if the precision were omitted."
580
				 * (7.19.6.1, 5)
581
				 */
582
				if ((precision = va_arg(args, int)) < 0)
583
					precision = -1;
584
				ch = *format++;
585
				state = PRINT_S_MOD;
586
			} else
587
				state = PRINT_S_MOD;
588
			break;
589
		case PRINT_S_MOD:
590
			switch (ch) {
591
			case 'h':
592
				ch = *format++;
593
				if (ch == 'h') {	/* It's a char. */
594
					ch = *format++;
595
					cflags = PRINT_C_CHAR;
596
				} else
597
					cflags = PRINT_C_SHORT;
598
				break;
599
			case 'l':
600
				ch = *format++;
601
				if (ch == 'l') {	/* It's a long long. */
602
					ch = *format++;
603
					cflags = PRINT_C_LLONG;
604
				} else
605
					cflags = PRINT_C_LONG;
606
				break;
607
			case 'L':
608
				cflags = PRINT_C_LDOUBLE;
609
				ch = *format++;
610
				break;
611
			case 'j':
612
				cflags = PRINT_C_INTMAX;
613
				ch = *format++;
614
				break;
615
			case 't':
616
				cflags = PRINT_C_PTRDIFF;
617
				ch = *format++;
618
				break;
619
			case 'z':
620
				cflags = PRINT_C_SIZE;
621
				ch = *format++;
622
				break;
623
			}
624
			state = PRINT_S_CONV;
625
			break;
626
		case PRINT_S_CONV:
627
			switch (ch) {
628
			case 'd':
629
				/* FALLTHROUGH */
630
			case 'i':
631
				switch (cflags) {
632
				case PRINT_C_CHAR:
633
					value = (signed char)va_arg(args, int);
634
					break;
635
				case PRINT_C_SHORT:
636
					value = (short int)va_arg(args, int);
637
					break;
638
				case PRINT_C_LONG:
639
					value = va_arg(args, long int);
640
					break;
641
				case PRINT_C_LLONG:
642
					value = va_arg(args, LLONG);
643
					break;
644
				case PRINT_C_SIZE:
645
					value = va_arg(args, SSIZE_T);
646
					break;
647
				case PRINT_C_INTMAX:
648
					value = va_arg(args, INTMAX_T);
649
					break;
650
				case PRINT_C_PTRDIFF:
651
					value = va_arg(args, PTRDIFF_T);
652
					break;
653
				default:
654
					value = va_arg(args, int);
655
					break;
656
				}
657
				fmtint(str, &len, size, value, 10, width,
658
				    precision, flags);
659
				break;
660
			case 'X':
661
				flags |= PRINT_F_UP;
662
				/* FALLTHROUGH */
663
			case 'x':
664
				base = 16;
665
				/* FALLTHROUGH */
666
			case 'o':
667
				if (base == 0)
668
					base = 8;
669
				/* FALLTHROUGH */
670
			case 'u':
671
				if (base == 0)
672
					base = 10;
673
				flags |= PRINT_F_UNSIGNED;
674
				switch (cflags) {
675
				case PRINT_C_CHAR:
676
					value = (unsigned char)va_arg(args,
677
					    unsigned int);
678
					break;
679
				case PRINT_C_SHORT:
680
					value = (unsigned short int)va_arg(args,
681
					    unsigned int);
682
					break;
683
				case PRINT_C_LONG:
684
					value = va_arg(args, unsigned long int);
685
					break;
686
				case PRINT_C_LLONG:
687
					value = va_arg(args, ULLONG);
688
					break;
689
				case PRINT_C_SIZE:
690
					value = va_arg(args, size_t);
691
					break;
692
				case PRINT_C_INTMAX:
693
					value = va_arg(args, UINTMAX_T);
694
					break;
695
				case PRINT_C_PTRDIFF:
696
					value = va_arg(args, UPTRDIFF_T);
697
					break;
698
				default:
699
					value = va_arg(args, unsigned int);
700
					break;
701
				}
702
				fmtint(str, &len, size, value, base, width,
703
				    precision, flags);
704
				break;
705
			case 'A':
706
				/* Not yet supported, we'll use "%F". */
707
				/* FALLTHROUGH */
708
			case 'F':
709
				flags |= PRINT_F_UP;
710
			case 'a':
711
				/* Not yet supported, we'll use "%f". */
712
				/* FALLTHROUGH */
713
			case 'f':
714
				if (cflags == PRINT_C_LDOUBLE)
715
					fvalue = va_arg(args, LDOUBLE);
716
				else
717
					fvalue = va_arg(args, double);
718
				fmtflt(str, &len, size, fvalue, width,
719
				    precision, flags, &overflow);
720
				if (overflow)
721
					goto out;
722
				break;
723
			case 'E':
724
				flags |= PRINT_F_UP;
725
				/* FALLTHROUGH */
726
			case 'e':
727
				flags |= PRINT_F_TYPE_E;
728
				if (cflags == PRINT_C_LDOUBLE)
729
					fvalue = va_arg(args, LDOUBLE);
730
				else
731
					fvalue = va_arg(args, double);
732
				fmtflt(str, &len, size, fvalue, width,
733
				    precision, flags, &overflow);
734
				if (overflow)
735
					goto out;
736
				break;
737
			case 'G':
738
				flags |= PRINT_F_UP;
739
				/* FALLTHROUGH */
740
			case 'g':
741
				flags |= PRINT_F_TYPE_G;
742
				if (cflags == PRINT_C_LDOUBLE)
743
					fvalue = va_arg(args, LDOUBLE);
744
				else
745
					fvalue = va_arg(args, double);
746
				/*
747
				 * If the precision is zero, it is treated as
748
				 * one (cf. C99: 7.19.6.1, 8).
749
				 */
750
				if (precision == 0)
751
					precision = 1;
752
				fmtflt(str, &len, size, fvalue, width,
753
				    precision, flags, &overflow);
754
				if (overflow)
755
					goto out;
756
				break;
757
			case 'c':
758
				cvalue = (unsigned char)va_arg(args, int);
759
				OUTCHAR(str, len, size, cvalue);
760
				break;
761
			case 's':
762
				strvalue = va_arg(args, char *);
763
				fmtstr(str, &len, size, strvalue, width,
764
				    precision, flags);
765
				break;
766
			case 'p':
767
				/*
768
				 * C99 says: "The value of the pointer is
769
				 * converted to a sequence of printing
770
				 * characters, in an implementation-defined
771
				 * manner." (C99: 7.19.6.1, 8)
772
				 */
773
				if ((strvalue = va_arg(args, void *)) == NULL)
774
					/*
775
					 * We use the glibc format.  BSD prints
776
					 * "0x0", SysV "0".
777
					 */
778
					fmtstr(str, &len, size, "(nil)", width,
779
					    -1, flags);
780
				else {
781
					/*
782
					 * We use the BSD/glibc format.  SysV
783
					 * omits the "0x" prefix (which we emit
784
					 * using the PRINT_F_NUM flag).
785
					 */
786
					flags |= PRINT_F_NUM;
787
					flags |= PRINT_F_UNSIGNED;
788
					fmtint(str, &len, size,
789
					    (UINTPTR_T)strvalue, 16, width,
790
					    precision, flags);
791
				}
792
				break;
793
			case 'n':
794
				switch (cflags) {
795
				case PRINT_C_CHAR:
796
					charptr = va_arg(args, signed char *);
797
					*charptr = (signed char)len;
798
					break;
799
				case PRINT_C_SHORT:
800
					shortptr = va_arg(args, short int *);
801
					*shortptr = (short int)len;
802
					break;
803
				case PRINT_C_LONG:
804
					longptr = va_arg(args, long int *);
805
					*longptr = (long int)len;
806
					break;
807
				case PRINT_C_LLONG:
808
					llongptr = va_arg(args, LLONG *);
809
					*llongptr = (LLONG)len;
810
					break;
811
				case PRINT_C_SIZE:
812
					/*
813
					 * C99 says that with the "z" length
814
					 * modifier, "a following `n' conversion
815
					 * specifier applies to a pointer to a
816
					 * signed integer type corresponding to
817
					 * size_t argument." (7.19.6.1, 7)
818
					 */
819
					sizeptr = va_arg(args, SSIZE_T *);
820
					*sizeptr = len;
821
					break;
822
				case PRINT_C_INTMAX:
823
					intmaxptr = va_arg(args, INTMAX_T *);
824
					*intmaxptr = len;
825
					break;
826
				case PRINT_C_PTRDIFF:
827
					ptrdiffptr = va_arg(args, PTRDIFF_T *);
828
					*ptrdiffptr = len;
829
					break;
830
				default:
831
					intptr = va_arg(args, int *);
832
					*intptr = (int)len;
833
					break;
834
				}
835
				break;
836
			case '%':	/* Print a "%" character verbatim. */
837
				OUTCHAR(str, len, size, ch);
838
				break;
839
			default:	/* Skip other characters. */
840
				break;
841
			}
842
			ch = *format++;
843
			state = PRINT_S_DEFAULT;
844
			base = cflags = flags = width = 0;
845
			precision = -1;
846
			break;
847
		}
848
out:
849
	if (len < size)
850
		str[len] = '\0';
851
	else if (size > 0)
852
		str[size - 1] = '\0';
853
 
854
	if (overflow || len >= INT_MAX) {
855
		return -1;
856
	}
857
	return (int)len;
858
}
859
 
860
static void
861
fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
862
       int precision, int flags)
863
{
864
	int padlen, strln;	/* Amount to pad. */
865
	int noprecision = (precision == -1);
866
 
867
	if (value == NULL)	/* We're forgiving. */
868
		value = "(null)";
869
 
870
	/* If a precision was specified, don't read the string past it. */
871
	for (strln = 0; value[strln] != '\0' &&
872
	    (noprecision || strln < precision); strln++)
873
		continue;
874
 
875
	if ((padlen = width - strln) < 0)
876
		padlen = 0;
877
	if (flags & PRINT_F_MINUS)	/* Left justify. */
878
		padlen = -padlen;
879
 
880
	while (padlen > 0) {	/* Leading spaces. */
881
		OUTCHAR(str, *len, size, ' ');
882
		padlen--;
883
	}
884
	while (*value != '\0' && (noprecision || precision-- > 0)) {
885
		OUTCHAR(str, *len, size, *value);
886
		value++;
887
	}
888
	while (padlen < 0) {	/* Trailing spaces. */
889
		OUTCHAR(str, *len, size, ' ');
890
		padlen++;
891
	}
892
}
893
 
894
static void
895
fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
896
       int precision, int flags)
897
{
898
	UINTMAX_T uvalue;
899
	char iconvert[MAX_CONVERT_LENGTH];
900
	char sign = 0;
901
	char hexprefix = 0;
902
	int spadlen = 0;	/* Amount to space pad. */
903
	int zpadlen = 0;	/* Amount to zero pad. */
904
	int pos;
905
	int separators = (flags & PRINT_F_QUOTE);
906
	int noprecision = (precision == -1);
907
 
908
	if (flags & PRINT_F_UNSIGNED)
909
		uvalue = value;
910
	else {
911
		uvalue = (value >= 0) ? value : -value;
912
		if (value < 0)
913
			sign = '-';
914
		else if (flags & PRINT_F_PLUS)	/* Do a sign. */
915
			sign = '+';
916
		else if (flags & PRINT_F_SPACE)
917
			sign = ' ';
918
	}
919
 
920
	pos = convert(uvalue, iconvert, sizeof(iconvert), base,
921
	    flags & PRINT_F_UP);
922
 
923
	if (flags & PRINT_F_NUM && uvalue != 0) {
924
		/*
925
		 * C99 says: "The result is converted to an `alternative form'.
926
		 * For `o' conversion, it increases the precision, if and only
927
		 * if necessary, to force the first digit of the result to be a
928
		 * zero (if the value and precision are both 0, a single 0 is
929
		 * printed).  For `x' (or `X') conversion, a nonzero result has
930
		 * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
931
		 */
932
		switch (base) {
933
		case 8:
934
			if (precision <= pos)
935
				precision = pos + 1;
936
			break;
937
		case 16:
938
			hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
939
			break;
940
		}
941
	}
942
 
943
	if (separators)	/* Get the number of group separators we'll print. */
944
		separators = getnumsep(pos);
945
 
946
	zpadlen = precision - pos - separators;
947
	spadlen = width                         /* Minimum field width. */
948
	    - separators                        /* Number of separators. */
949
	    - MAX(precision, pos)               /* Number of integer digits. */
950
	    - ((sign != 0) ? 1 : 0)             /* Will we print a sign? */
951
	    - ((hexprefix != 0) ? 2 : 0);       /* Will we print a prefix? */
952
 
953
	if (zpadlen < 0)
954
		zpadlen = 0;
955
	if (spadlen < 0)
956
		spadlen = 0;
957
 
958
	/*
959
	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
960
	 * ignored.  For `d', `i', `o', `u', `x', and `X' conversions, if a
961
	 * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
962
	 */
963
	if (flags & PRINT_F_MINUS)	/* Left justify. */
964
		spadlen = -spadlen;
965
	else if (flags & PRINT_F_ZERO && noprecision) {
966
		zpadlen += spadlen;
967
		spadlen = 0;
968
	}
969
	while (spadlen > 0) {	/* Leading spaces. */
970
		OUTCHAR(str, *len, size, ' ');
971
		spadlen--;
972
	}
973
	if (sign != 0)	/* Sign. */
974
		OUTCHAR(str, *len, size, sign);
975
	if (hexprefix != 0) {	/* A "0x" or "0X" prefix. */
976
		OUTCHAR(str, *len, size, '0');
977
		OUTCHAR(str, *len, size, hexprefix);
978
	}
979
	while (zpadlen > 0) {	/* Leading zeros. */
980
		OUTCHAR(str, *len, size, '0');
981
		zpadlen--;
982
	}
983
	while (pos > 0) {	/* The actual digits. */
984
		pos--;
985
		OUTCHAR(str, *len, size, iconvert[pos]);
986
		if (separators > 0 && pos > 0 && pos % 3 == 0)
987
			printsep(str, len, size);
988
	}
989
	while (spadlen < 0) {	/* Trailing spaces. */
990
		OUTCHAR(str, *len, size, ' ');
991
		spadlen++;
992
	}
993
}
994
 
995
static void
996
fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
997
       int precision, int flags, int *overflow)
998
{
999
	LDOUBLE ufvalue;
1000
	UINTMAX_T intpart;
1001
	UINTMAX_T fracpart;
1002
	UINTMAX_T mask;
1003
	const char *infnan = NULL;
1004
	char iconvert[MAX_CONVERT_LENGTH];
1005
	char fconvert[MAX_CONVERT_LENGTH];
1006
	char econvert[4];	/* "e-12" (without nul-termination). */
1007
	char esign = 0;
1008
	char sign = 0;
1009
	int leadfraczeros = 0;
1010
	int exponent = 0;
1011
	int emitpoint = 0;
1012
	int omitzeros = 0;
1013
	int omitcount = 0;
1014
	int padlen = 0;
1015
	int epos = 0;
1016
	int fpos = 0;
1017
	int ipos = 0;
1018
	int separators = (flags & PRINT_F_QUOTE);
1019
	int estyle = (flags & PRINT_F_TYPE_E);
1020
#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1021
	struct lconv *lc = localeconv();
1022
#endif	/* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1023
 
1024
	/*
1025
	 * AIX' man page says the default is 0, but C99 and at least Solaris'
1026
	 * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
1027
	 * defaults to 6.
1028
	 */
1029
	if (precision == -1)
1030
		precision = 6;
1031
 
1032
	if (fvalue < 0.0)
1033
		sign = '-';
1034
	else if (flags & PRINT_F_PLUS)	/* Do a sign. */
1035
		sign = '+';
1036
	else if (flags & PRINT_F_SPACE)
1037
		sign = ' ';
1038
 
1039
	if (ISNAN(fvalue))
1040
		infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
1041
	else if (ISINF(fvalue))
1042
		infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
1043
 
1044
	if (infnan != NULL) {
1045
		if (sign != 0)
1046
			iconvert[ipos++] = sign;
1047
		while (*infnan != '\0')
1048
			iconvert[ipos++] = *infnan++;
1049
		fmtstr(str, len, size, iconvert, width, ipos, flags);
1050
		return;
1051
	}
1052
 
1053
	/* "%e" (or "%E") or "%g" (or "%G") conversion. */
1054
	if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
1055
		if (flags & PRINT_F_TYPE_G) {
1056
			/*
1057
			 * For "%g" (and "%G") conversions, the precision
1058
			 * specifies the number of significant digits, which
1059
			 * includes the digits in the integer part.  The
1060
			 * conversion will or will not be using "e-style" (like
1061
			 * "%e" or "%E" conversions) depending on the precision
1062
			 * and on the exponent.  However, the exponent can be
1063
			 * affected by rounding the converted value, so we'll
1064
			 * leave this decision for later.  Until then, we'll
1065
			 * assume that we're going to do an "e-style" conversion
1066
			 * (in order to get the exponent calculated).  For
1067
			 * "e-style", the precision must be decremented by one.
1068
			 */
1069
			precision--;
1070
			/*
1071
			 * For "%g" (and "%G") conversions, trailing zeros are
1072
			 * removed from the fractional portion of the result
1073
			 * unless the "#" flag was specified.
1074
			 */
1075
			if (!(flags & PRINT_F_NUM))
1076
				omitzeros = 1;
1077
		}
1078
		exponent = getexponent(fvalue);
1079
		estyle = 1;
1080
	}
1081
 
1082
again:
1083
	/*
1084
	 * Sorry, we only support 9, 19, or 38 digits (that is, the number of
1085
	 * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
1086
	 * minus one) past the decimal point due to our conversion method.
1087
	 */
1088
	switch (sizeof(UINTMAX_T)) {
1089
	case 16:
1090
		if (precision > 38)
1091
			precision = 38;
1092
		break;
1093
	case 8:
1094
		if (precision > 19)
1095
			precision = 19;
1096
		break;
1097
	default:
1098
		if (precision > 9)
1099
			precision = 9;
1100
		break;
1101
	}
1102
 
1103
	ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
1104
	if (estyle)	/* We want exactly one integer digit. */
1105
		ufvalue /= mypow10(exponent);
1106
 
1107
	if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
1108
		*overflow = 1;
1109
		return;
1110
	}
1111
 
1112
	/*
1113
	 * Factor of ten with the number of digits needed for the fractional
1114
	 * part.  For example, if the precision is 3, the mask will be 1000.
1115
	 */
1116
	mask = (UINTMAX_T)mypow10(precision);
1117
	/*
1118
	 * We "cheat" by converting the fractional part to integer by
1119
	 * multiplying by a factor of ten.
1120
	 */
1121
	if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
1122
		/*
1123
		 * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
1124
		 * (because precision = 3).  Now, myround(1000 * 0.99962) will
1125
		 * return 1000.  So, the integer part must be incremented by one
1126
		 * and the fractional part must be set to zero.
1127
		 */
1128
		intpart++;
1129
		fracpart = 0;
1130
		if (estyle && intpart == 10) {
1131
			/*
1132
			 * The value was rounded up to ten, but we only want one
1133
			 * integer digit if using "e-style".  So, the integer
1134
			 * part must be set to one and the exponent must be
1135
			 * incremented by one.
1136
			 */
1137
			intpart = 1;
1138
			exponent++;
1139
		}
1140
	}
1141
 
1142
	/*
1143
	 * Now that we know the real exponent, we can check whether or not to
1144
	 * use "e-style" for "%g" (and "%G") conversions.  If we don't need
1145
	 * "e-style", the precision must be adjusted and the integer and
1146
	 * fractional parts must be recalculated from the original value.
1147
	 *
1148
	 * C99 says: "Let P equal the precision if nonzero, 6 if the precision
1149
	 * is omitted, or 1 if the precision is zero.  Then, if a conversion
1150
	 * with style `E' would have an exponent of X:
1151
	 *
1152
	 * - if P > X >= -4, the conversion is with style `f' (or `F') and
1153
	 *   precision P - (X + 1).
1154
	 *
1155
	 * - otherwise, the conversion is with style `e' (or `E') and precision
1156
	 *   P - 1." (7.19.6.1, 8)
1157
	 *
1158
	 * Note that we had decremented the precision by one.
1159
	 */
1160
	if (flags & PRINT_F_TYPE_G && estyle &&
1161
	    precision + 1 > exponent && exponent >= -4) {
1162
		precision -= exponent;
1163
		estyle = 0;
1164
		goto again;
1165
	}
1166
 
1167
	if (estyle) {
1168
		if (exponent < 0) {
1169
			exponent = -exponent;
1170
			esign = '-';
1171
		} else
1172
			esign = '+';
1173
 
1174
		/*
1175
		 * Convert the exponent.  The sizeof(econvert) is 4.  So, the
1176
		 * econvert buffer can hold e.g. "e+99" and "e-99".  We don't
1177
		 * support an exponent which contains more than two digits.
1178
		 * Therefore, the following stores are safe.
1179
		 */
1180
		epos = convert(exponent, econvert, 2, 10, 0);
1181
		/*
1182
		 * C99 says: "The exponent always contains at least two digits,
1183
		 * and only as many more digits as necessary to represent the
1184
		 * exponent." (7.19.6.1, 8)
1185
		 */
1186
		if (epos == 1)
1187
			econvert[epos++] = '0';
1188
		econvert[epos++] = esign;
1189
		econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
1190
	}
1191
 
1192
	/* Convert the integer part and the fractional part. */
1193
	ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
1194
	if (fracpart != 0)	/* convert() would return 1 if fracpart == 0. */
1195
		fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
1196
 
1197
	leadfraczeros = precision - fpos;
1198
 
1199
	if (omitzeros) {
1200
		if (fpos > 0)	/* Omit trailing fractional part zeros. */
1201
			while (omitcount < fpos && fconvert[omitcount] == '0')
1202
				omitcount++;
1203
		else {	/* The fractional part is zero, omit it completely. */
1204
			omitcount = precision;
1205
			leadfraczeros = 0;
1206
		}
1207
		precision -= omitcount;
1208
	}
1209
 
1210
	/*
1211
	 * Print a decimal point if either the fractional part is non-zero
1212
	 * and/or the "#" flag was specified.
1213
	 */
1214
	if (precision > 0 || flags & PRINT_F_NUM)
1215
		emitpoint = 1;
1216
	if (separators)	/* Get the number of group separators we'll print. */
1217
		separators = getnumsep(ipos);
1218
 
1219
	padlen = width                  /* Minimum field width. */
1220
	    - ipos                      /* Number of integer digits. */
1221
	    - epos                      /* Number of exponent characters. */
1222
	    - precision                 /* Number of fractional digits. */
1223
	    - separators                /* Number of group separators. */
1224
	    - (emitpoint ? 1 : 0)       /* Will we print a decimal point? */
1225
	    - ((sign != 0) ? 1 : 0);    /* Will we print a sign character? */
1226
 
1227
	if (padlen < 0)
1228
		padlen = 0;
1229
 
1230
	/*
1231
	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
1232
	 * ignored." (7.19.6.1, 6)
1233
	 */
1234
	if (flags & PRINT_F_MINUS)	/* Left justifty. */
1235
		padlen = -padlen;
1236
	else if (flags & PRINT_F_ZERO && padlen > 0) {
1237
		if (sign != 0) {	/* Sign. */
1238
			OUTCHAR(str, *len, size, sign);
1239
			sign = 0;
1240
		}
1241
		while (padlen > 0) {	/* Leading zeros. */
1242
			OUTCHAR(str, *len, size, '0');
1243
			padlen--;
1244
		}
1245
	}
1246
	while (padlen > 0) {	/* Leading spaces. */
1247
		OUTCHAR(str, *len, size, ' ');
1248
		padlen--;
1249
	}
1250
	if (sign != 0)	/* Sign. */
1251
		OUTCHAR(str, *len, size, sign);
1252
	while (ipos > 0) {	/* Integer part. */
1253
		ipos--;
1254
		OUTCHAR(str, *len, size, iconvert[ipos]);
1255
		if (separators > 0 && ipos > 0 && ipos % 3 == 0)
1256
			printsep(str, len, size);
1257
	}
1258
	if (emitpoint) {	/* Decimal point. */
1259
#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1260
		if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
1261
			OUTCHAR(str, *len, size, *lc->decimal_point);
1262
		else	/* We'll always print some decimal point character. */
1263
#endif	/* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1264
			OUTCHAR(str, *len, size, '.');
1265
	}
1266
	while (leadfraczeros > 0) {	/* Leading fractional part zeros. */
1267
		OUTCHAR(str, *len, size, '0');
1268
		leadfraczeros--;
1269
	}
1270
	while (fpos > omitcount) {	/* The remaining fractional part. */
1271
		fpos--;
1272
		OUTCHAR(str, *len, size, fconvert[fpos]);
1273
	}
1274
	while (epos > 0) {	/* Exponent. */
1275
		epos--;
1276
		OUTCHAR(str, *len, size, econvert[epos]);
1277
	}
1278
	while (padlen < 0) {	/* Trailing spaces. */
1279
		OUTCHAR(str, *len, size, ' ');
1280
		padlen++;
1281
	}
1282
}
1283
 
1284
static void
1285
printsep(char *str, size_t *len, size_t size)
1286
{
1287
#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1288
	struct lconv *lc = localeconv();
1289
	int i;
1290
 
1291
	if (lc->thousands_sep != NULL)
1292
		for (i = 0; lc->thousands_sep[i] != '\0'; i++)
1293
			OUTCHAR(str, *len, size, lc->thousands_sep[i]);
1294
	else
1295
#endif	/* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1296
		OUTCHAR(str, *len, size, ',');
1297
}
1298
 
1299
static int
1300
getnumsep(int digits)
1301
{
1302
	int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
1303
#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1304
	int strln;
1305
	struct lconv *lc = localeconv();
1306
 
1307
	/* We support an arbitrary separator length (including zero). */
1308
	if (lc->thousands_sep != NULL) {
1309
		for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
1310
			continue;
1311
		separators *= strln;
1312
	}
1313
#endif	/* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1314
	return separators;
1315
}
1316
 
1317
static int
1318
getexponent(LDOUBLE value)
1319
{
1320
	LDOUBLE tmp = (value >= 0.0) ? value : -value;
1321
	int exponent = 0;
1322
 
1323
	/*
1324
	 * We check for 99 > exponent > -99 in order to work around possible
1325
	 * endless loops which could happen (at least) in the second loop (at
1326
	 * least) if we're called with an infinite value.  However, we checked
1327
	 * for infinity before calling this function using our ISINF() macro, so
1328
	 * this might be somewhat paranoid.
1329
	 */
1330
	while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
1331
		tmp *= 10;
1332
	while (tmp >= 10.0 && ++exponent < 99)
1333
		tmp /= 10;
1334
 
1335
	return exponent;
1336
}
1337
 
1338
static int
1339
convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
1340
{
1341
	const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
1342
	size_t pos = 0;
1343
 
1344
	/* We return an unterminated buffer with the digits in reverse order. */
1345
	do {
1346
		buf[pos++] = digits[value % base];
1347
		value /= base;
1348
	} while (value != 0 && pos < size);
1349
 
1350
	return (int)pos;
1351
}
1352
 
1353
static UINTMAX_T
1354
cast(LDOUBLE value)
1355
{
1356
	UINTMAX_T result;
1357
 
1358
	/*
1359
	 * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
1360
	 * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
1361
	 * it may be increased to the nearest higher representable value for the
1362
	 * comparison (cf. C99: 6.3.1.4, 2).  It might then equal the LDOUBLE
1363
	 * value although converting the latter to UINTMAX_T would overflow.
1364
	 */
1365
	if (value >= UINTMAX_MAX)
1366
		return UINTMAX_MAX;
1367
 
1368
	result = (UINTMAX_T)value;
1369
	/*
1370
	 * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
1371
	 * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
1372
	 * the standard).  Sigh.
1373
	 */
1374
	return (result <= value) ? result : result - 1;
1375
}
1376
 
1377
static UINTMAX_T
1378
myround(LDOUBLE value)
1379
{
1380
	UINTMAX_T intpart = cast(value);
1381
 
1382
	return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
1383
}
1384
 
1385
static LDOUBLE
1386
mypow10(int exponent)
1387
{
1388
	LDOUBLE result = 1;
1389
 
1390
	while (exponent > 0) {
1391
		result *= 10;
1392
		exponent--;
1393
	}
1394
	while (exponent < 0) {
1395
		result /= 10;
1396
		exponent++;
1397
	}
1398
	return result;
1399
}
1400
#endif	/* !HAVE_VSNPRINTF */
1401
 
1402
#if !HAVE_VASPRINTF
1403
#if NEED_MYMEMCPY
1404
void *
1405
mymemcpy(void *dst, void *src, size_t len)
1406
{
1407
	const char *from = src;
1408
	char *to = dst;
1409
 
1410
	/* No need for optimization, we use this only to replace va_copy(3). */
1411
	while (len-- > 0)
1412
		*to++ = *from++;
1413
	return dst;
1414
}
1415
#endif	/* NEED_MYMEMCPY */
1416
 
1417
int
1418
util_vasprintf(char **ret, const char *format, va_list ap)
1419
{
1420
	size_t size;
1421
	int len;
1422
	va_list aq;
1423
 
1424
	VA_COPY(aq, ap);
1425
	len = vsnprintf(NULL, 0, format, aq);
1426
	VA_END_COPY(aq);
1427
	if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
1428
		return -1;
1429
	return vsnprintf(*ret, size, format, ap);
1430
}
1431
#endif	/* !HAVE_VASPRINTF */
1432
 
1433
#if !HAVE_SNPRINTF
1434
#if HAVE_STDARG_H
1435
int
1436
util_snprintf(char *str, size_t size, const char *format, ...)
1437
#else
1438
int
1439
util_snprintf(va_alist) va_dcl
1440
#endif	/* HAVE_STDARG_H */
1441
{
1442
#if !HAVE_STDARG_H
1443
	char *str;
1444
	size_t size;
1445
	char *format;
1446
#endif	/* HAVE_STDARG_H */
1447
	va_list ap;
1448
	int len;
1449
 
1450
	VA_START(ap, format);
1451
	VA_SHIFT(ap, str, char *);
1452
	VA_SHIFT(ap, size, size_t);
1453
	VA_SHIFT(ap, format, const char *);
1454
	len = vsnprintf(str, size, format, ap);
1455
	va_end(ap);
1456
	return len;
1457
}
1458
#endif	/* !HAVE_SNPRINTF */
1459
 
1460
#if !HAVE_ASPRINTF
1461
#if HAVE_STDARG_H
1462
int
1463
util_asprintf(char **ret, const char *format, ...)
1464
#else
1465
int
1466
util_asprintf(va_alist) va_dcl
1467
#endif	/* HAVE_STDARG_H */
1468
{
1469
#if !HAVE_STDARG_H
1470
	char **ret;
1471
	char *format;
1472
#endif	/* HAVE_STDARG_H */
1473
	va_list ap;
1474
	int len;
1475
 
1476
	VA_START(ap, format);
1477
	VA_SHIFT(ap, ret, char **);
1478
	VA_SHIFT(ap, format, const char *);
1479
	len = vasprintf(ret, format, ap);
1480
	va_end(ap);
1481
	return len;
1482
}
1483
#endif	/* !HAVE_ASPRINTF */
1484
#else	/* Dummy declaration to avoid empty translation unit warnings. */
1485
int main(void);
1486
#endif	/* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
1487
 
1488
 
1489
/* vim: set joinspaces textwidth=80: */