Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 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 1
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
/* Support for ptrdiff_t. */
338
#ifndef PTRDIFF_T
339
#if HAVE_PTRDIFF_T || defined(ptrdiff_t)
340
#define PTRDIFF_T ptrdiff_t
341
#else
342
#define PTRDIFF_T long int
343
#endif	/* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
344
#endif	/* !defined(PTRDIFF_T) */
345
 
346
/*
347
 * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
348
 * 7.19.6.1, 7).  However, we'll simply use PTRDIFF_T and convert it to an
349
 * unsigned type if necessary.  This should work just fine in practice.
350
 */
351
#ifndef UPTRDIFF_T
352
#define UPTRDIFF_T PTRDIFF_T
353
#endif	/* !defined(UPTRDIFF_T) */
354
 
355
/*
356
 * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
357
 * However, we'll simply use size_t and convert it to a signed type if
358
 * necessary.  This should work just fine in practice.
359
 */
360
#ifndef SSIZE_T
361
#define SSIZE_T size_t
362
#endif	/* !defined(SSIZE_T) */
363
 
364
/* Either ERANGE or E2BIG should be available everywhere. */
365
#ifndef ERANGE
366
#define ERANGE E2BIG
367
#endif	/* !defined(ERANGE) */
368
#ifndef EOVERFLOW
369
#define EOVERFLOW ERANGE
370
#endif	/* !defined(EOVERFLOW) */
371
 
372
/*
373
 * Buffer size to hold the octal string representation of UINT128_MAX without
374
 * nul-termination ("3777777777777777777777777777777777777777777").
375
 */
376
#ifdef MAX_CONVERT_LENGTH
377
#undef MAX_CONVERT_LENGTH
378
#endif	/* defined(MAX_CONVERT_LENGTH) */
379
#define MAX_CONVERT_LENGTH      43
380
 
381
/* Format read states. */
382
#define PRINT_S_DEFAULT         0
383
#define PRINT_S_FLAGS           1
384
#define PRINT_S_WIDTH           2
385
#define PRINT_S_DOT             3
386
#define PRINT_S_PRECISION       4
387
#define PRINT_S_MOD             5
388
#define PRINT_S_CONV            6
389
 
390
/* Format flags. */
391
#define PRINT_F_MINUS           (1 << 0)
392
#define PRINT_F_PLUS            (1 << 1)
393
#define PRINT_F_SPACE           (1 << 2)
394
#define PRINT_F_NUM             (1 << 3)
395
#define PRINT_F_ZERO            (1 << 4)
396
#define PRINT_F_QUOTE           (1 << 5)
397
#define PRINT_F_UP              (1 << 6)
398
#define PRINT_F_UNSIGNED        (1 << 7)
399
#define PRINT_F_TYPE_G          (1 << 8)
400
#define PRINT_F_TYPE_E          (1 << 9)
401
 
402
/* Conversion flags. */
403
#define PRINT_C_CHAR            1
404
#define PRINT_C_SHORT           2
405
#define PRINT_C_LONG            3
406
#define PRINT_C_LLONG           4
407
#define PRINT_C_LDOUBLE         5
408
#define PRINT_C_SIZE            6
409
#define PRINT_C_PTRDIFF         7
410
#define PRINT_C_INTMAX          8
411
 
412
#ifndef MAX
413
#define MAX(x, y) ((x >= y) ? x : y)
414
#endif	/* !defined(MAX) */
415
#ifndef CHARTOINT
416
#define CHARTOINT(ch) (ch - '0')
417
#endif	/* !defined(CHARTOINT) */
418
#ifndef ISDIGIT
419
#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
420
#endif	/* !defined(ISDIGIT) */
421
#ifndef ISNAN
422
#define ISNAN(x) (x != x)
423
#endif	/* !defined(ISNAN) */
424
#ifndef ISINF
425
#define ISINF(x) (x != 0.0 && x + x == x)
426
#endif	/* !defined(ISINF) */
427
 
428
#ifdef OUTCHAR
429
#undef OUTCHAR
430
#endif	/* defined(OUTCHAR) */
431
#define OUTCHAR(str, len, size, ch)                                          \
432
do {                                                                         \
433
	if (len + 1 < size)                                                  \
434
		str[len] = ch;                                               \
435
	(len)++;                                                             \
436
} while (/* CONSTCOND */ 0)
437
 
438
static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
439
static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
440
static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
441
static void printsep(char *, size_t *, size_t);
442
static int getnumsep(int);
443
static int getexponent(LDOUBLE);
444
static int convert(UINTMAX_T, char *, size_t, int, int);
445
static UINTMAX_T cast(LDOUBLE);
446
static UINTMAX_T myround(LDOUBLE);
447
static LDOUBLE mypow10(int);
448
 
449
int
450
util_vsnprintf(char *str, size_t size, const char *format, va_list args)
451
{
452
	LDOUBLE fvalue;
453
	INTMAX_T value;
454
	unsigned char cvalue;
455
	const char *strvalue;
456
	INTMAX_T *intmaxptr;
457
	PTRDIFF_T *ptrdiffptr;
458
	SSIZE_T *sizeptr;
459
	LLONG *llongptr;
460
	long int *longptr;
461
	int *intptr;
462
	short int *shortptr;
463
	signed char *charptr;
464
	size_t len = 0;
465
	int overflow = 0;
466
	int base = 0;
467
	int cflags = 0;
468
	int flags = 0;
469
	int width = 0;
470
	int precision = -1;
471
	int state = PRINT_S_DEFAULT;
472
	char ch = *format++;
473
 
474
	/*
475
	 * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
476
	 * pointer." (7.19.6.5, 2)  We're forgiving and allow a NULL pointer
477
	 * even if a size larger than zero was specified.  At least NetBSD's
478
	 * snprintf(3) does the same, as well as other versions of this file.
479
	 * (Though some of these versions will write to a non-NULL buffer even
480
	 * if a size of zero was specified, which violates the standard.)
481
	 */
482
	if (str == NULL && size != 0)
483
		size = 0;
484
 
485
	while (ch != '\0')
486
		switch (state) {
487
		case PRINT_S_DEFAULT:
488
			if (ch == '%')
489
				state = PRINT_S_FLAGS;
490
			else
491
				OUTCHAR(str, len, size, ch);
492
			ch = *format++;
493
			break;
494
		case PRINT_S_FLAGS:
495
			switch (ch) {
496
			case '-':
497
				flags |= PRINT_F_MINUS;
498
				ch = *format++;
499
				break;
500
			case '+':
501
				flags |= PRINT_F_PLUS;
502
				ch = *format++;
503
				break;
504
			case ' ':
505
				flags |= PRINT_F_SPACE;
506
				ch = *format++;
507
				break;
508
			case '#':
509
				flags |= PRINT_F_NUM;
510
				ch = *format++;
511
				break;
512
			case '0':
513
				flags |= PRINT_F_ZERO;
514
				ch = *format++;
515
				break;
516
			case '\'':	/* SUSv2 flag (not in C99). */
517
				flags |= PRINT_F_QUOTE;
518
				ch = *format++;
519
				break;
520
			default:
521
				state = PRINT_S_WIDTH;
522
				break;
523
			}
524
			break;
525
		case PRINT_S_WIDTH:
526
			if (ISDIGIT(ch)) {
527
				ch = CHARTOINT(ch);
528
				if (width > (INT_MAX - ch) / 10) {
529
					overflow = 1;
530
					goto out;
531
				}
532
				width = 10 * width + ch;
533
				ch = *format++;
534
			} else if (ch == '*') {
535
				/*
536
				 * C99 says: "A negative field width argument is
537
				 * taken as a `-' flag followed by a positive
538
				 * field width." (7.19.6.1, 5)
539
				 */
540
				if ((width = va_arg(args, int)) < 0) {
541
					flags |= PRINT_F_MINUS;
542
					width = -width;
543
				}
544
				ch = *format++;
545
				state = PRINT_S_DOT;
546
			} else
547
				state = PRINT_S_DOT;
548
			break;
549
		case PRINT_S_DOT:
550
			if (ch == '.') {
551
				state = PRINT_S_PRECISION;
552
				ch = *format++;
553
			} else
554
				state = PRINT_S_MOD;
555
			break;
556
		case PRINT_S_PRECISION:
557
			if (precision == -1)
558
				precision = 0;
559
			if (ISDIGIT(ch)) {
560
				ch = CHARTOINT(ch);
561
				if (precision > (INT_MAX - ch) / 10) {
562
					overflow = 1;
563
					goto out;
564
				}
565
				precision = 10 * precision + ch;
566
				ch = *format++;
567
			} else if (ch == '*') {
568
				/*
569
				 * C99 says: "A negative precision argument is
570
				 * taken as if the precision were omitted."
571
				 * (7.19.6.1, 5)
572
				 */
573
				if ((precision = va_arg(args, int)) < 0)
574
					precision = -1;
575
				ch = *format++;
576
				state = PRINT_S_MOD;
577
			} else
578
				state = PRINT_S_MOD;
579
			break;
580
		case PRINT_S_MOD:
581
			switch (ch) {
582
			case 'h':
583
				ch = *format++;
584
				if (ch == 'h') {	/* It's a char. */
585
					ch = *format++;
586
					cflags = PRINT_C_CHAR;
587
				} else
588
					cflags = PRINT_C_SHORT;
589
				break;
590
			case 'l':
591
				ch = *format++;
592
				if (ch == 'l') {	/* It's a long long. */
593
					ch = *format++;
594
					cflags = PRINT_C_LLONG;
595
				} else
596
					cflags = PRINT_C_LONG;
597
				break;
598
			case 'L':
599
				cflags = PRINT_C_LDOUBLE;
600
				ch = *format++;
601
				break;
602
			case 'j':
603
				cflags = PRINT_C_INTMAX;
604
				ch = *format++;
605
				break;
606
			case 't':
607
				cflags = PRINT_C_PTRDIFF;
608
				ch = *format++;
609
				break;
610
			case 'z':
611
				cflags = PRINT_C_SIZE;
612
				ch = *format++;
613
				break;
614
			}
615
			state = PRINT_S_CONV;
616
			break;
617
		case PRINT_S_CONV:
618
			switch (ch) {
619
			case 'd':
620
				/* FALLTHROUGH */
621
			case 'i':
622
				switch (cflags) {
623
				case PRINT_C_CHAR:
624
					value = (signed char)va_arg(args, int);
625
					break;
626
				case PRINT_C_SHORT:
627
					value = (short int)va_arg(args, int);
628
					break;
629
				case PRINT_C_LONG:
630
					value = va_arg(args, long int);
631
					break;
632
				case PRINT_C_LLONG:
633
					value = va_arg(args, LLONG);
634
					break;
635
				case PRINT_C_SIZE:
636
					value = va_arg(args, SSIZE_T);
637
					break;
638
				case PRINT_C_INTMAX:
639
					value = va_arg(args, INTMAX_T);
640
					break;
641
				case PRINT_C_PTRDIFF:
642
					value = va_arg(args, PTRDIFF_T);
643
					break;
644
				default:
645
					value = va_arg(args, int);
646
					break;
647
				}
648
				fmtint(str, &len, size, value, 10, width,
649
				    precision, flags);
650
				break;
651
			case 'X':
652
				flags |= PRINT_F_UP;
653
				/* FALLTHROUGH */
654
			case 'x':
655
				base = 16;
656
				/* FALLTHROUGH */
657
			case 'o':
658
				if (base == 0)
659
					base = 8;
660
				/* FALLTHROUGH */
661
			case 'u':
662
				if (base == 0)
663
					base = 10;
664
				flags |= PRINT_F_UNSIGNED;
665
				switch (cflags) {
666
				case PRINT_C_CHAR:
667
					value = (unsigned char)va_arg(args,
668
					    unsigned int);
669
					break;
670
				case PRINT_C_SHORT:
671
					value = (unsigned short int)va_arg(args,
672
					    unsigned int);
673
					break;
674
				case PRINT_C_LONG:
675
					value = va_arg(args, unsigned long int);
676
					break;
677
				case PRINT_C_LLONG:
678
					value = va_arg(args, ULLONG);
679
					break;
680
				case PRINT_C_SIZE:
681
					value = va_arg(args, size_t);
682
					break;
683
				case PRINT_C_INTMAX:
684
					value = va_arg(args, UINTMAX_T);
685
					break;
686
				case PRINT_C_PTRDIFF:
687
					value = va_arg(args, UPTRDIFF_T);
688
					break;
689
				default:
690
					value = va_arg(args, unsigned int);
691
					break;
692
				}
693
				fmtint(str, &len, size, value, base, width,
694
				    precision, flags);
695
				break;
696
			case 'A':
697
				/* Not yet supported, we'll use "%F". */
698
				/* FALLTHROUGH */
699
			case 'F':
700
				flags |= PRINT_F_UP;
701
			case 'a':
702
				/* Not yet supported, we'll use "%f". */
703
				/* FALLTHROUGH */
704
			case 'f':
705
				if (cflags == PRINT_C_LDOUBLE)
706
					fvalue = va_arg(args, LDOUBLE);
707
				else
708
					fvalue = va_arg(args, double);
709
				fmtflt(str, &len, size, fvalue, width,
710
				    precision, flags, &overflow);
711
				if (overflow)
712
					goto out;
713
				break;
714
			case 'E':
715
				flags |= PRINT_F_UP;
716
				/* FALLTHROUGH */
717
			case 'e':
718
				flags |= PRINT_F_TYPE_E;
719
				if (cflags == PRINT_C_LDOUBLE)
720
					fvalue = va_arg(args, LDOUBLE);
721
				else
722
					fvalue = va_arg(args, double);
723
				fmtflt(str, &len, size, fvalue, width,
724
				    precision, flags, &overflow);
725
				if (overflow)
726
					goto out;
727
				break;
728
			case 'G':
729
				flags |= PRINT_F_UP;
730
				/* FALLTHROUGH */
731
			case 'g':
732
				flags |= PRINT_F_TYPE_G;
733
				if (cflags == PRINT_C_LDOUBLE)
734
					fvalue = va_arg(args, LDOUBLE);
735
				else
736
					fvalue = va_arg(args, double);
737
				/*
738
				 * If the precision is zero, it is treated as
739
				 * one (cf. C99: 7.19.6.1, 8).
740
				 */
741
				if (precision == 0)
742
					precision = 1;
743
				fmtflt(str, &len, size, fvalue, width,
744
				    precision, flags, &overflow);
745
				if (overflow)
746
					goto out;
747
				break;
748
			case 'c':
749
				cvalue = (unsigned char)va_arg(args, int);
750
				OUTCHAR(str, len, size, cvalue);
751
				break;
752
			case 's':
753
				strvalue = va_arg(args, char *);
754
				fmtstr(str, &len, size, strvalue, width,
755
				    precision, flags);
756
				break;
757
			case 'p':
758
				/*
759
				 * C99 says: "The value of the pointer is
760
				 * converted to a sequence of printing
761
				 * characters, in an implementation-defined
762
				 * manner." (C99: 7.19.6.1, 8)
763
				 */
764
				if ((strvalue = va_arg(args, void *)) == NULL)
765
					/*
766
					 * We use the glibc format.  BSD prints
767
					 * "0x0", SysV "0".
768
					 */
769
					fmtstr(str, &len, size, "(nil)", width,
770
					    -1, flags);
771
				else {
772
					/*
773
					 * We use the BSD/glibc format.  SysV
774
					 * omits the "0x" prefix (which we emit
775
					 * using the PRINT_F_NUM flag).
776
					 */
777
					flags |= PRINT_F_NUM;
778
					flags |= PRINT_F_UNSIGNED;
779
					fmtint(str, &len, size,
780
					    (UINTPTR_T)strvalue, 16, width,
781
					    precision, flags);
782
				}
783
				break;
784
			case 'n':
785
				switch (cflags) {
786
				case PRINT_C_CHAR:
787
					charptr = va_arg(args, signed char *);
788
					*charptr = (signed char)len;
789
					break;
790
				case PRINT_C_SHORT:
791
					shortptr = va_arg(args, short int *);
792
					*shortptr = (short int)len;
793
					break;
794
				case PRINT_C_LONG:
795
					longptr = va_arg(args, long int *);
796
					*longptr = (long int)len;
797
					break;
798
				case PRINT_C_LLONG:
799
					llongptr = va_arg(args, LLONG *);
800
					*llongptr = (LLONG)len;
801
					break;
802
				case PRINT_C_SIZE:
803
					/*
804
					 * C99 says that with the "z" length
805
					 * modifier, "a following `n' conversion
806
					 * specifier applies to a pointer to a
807
					 * signed integer type corresponding to
808
					 * size_t argument." (7.19.6.1, 7)
809
					 */
810
					sizeptr = va_arg(args, SSIZE_T *);
811
					*sizeptr = len;
812
					break;
813
				case PRINT_C_INTMAX:
814
					intmaxptr = va_arg(args, INTMAX_T *);
815
					*intmaxptr = len;
816
					break;
817
				case PRINT_C_PTRDIFF:
818
					ptrdiffptr = va_arg(args, PTRDIFF_T *);
819
					*ptrdiffptr = len;
820
					break;
821
				default:
822
					intptr = va_arg(args, int *);
823
					*intptr = (int)len;
824
					break;
825
				}
826
				break;
827
			case '%':	/* Print a "%" character verbatim. */
828
				OUTCHAR(str, len, size, ch);
829
				break;
830
			default:	/* Skip other characters. */
831
				break;
832
			}
833
			ch = *format++;
834
			state = PRINT_S_DEFAULT;
835
			base = cflags = flags = width = 0;
836
			precision = -1;
837
			break;
838
		}
839
out:
840
	if (len < size)
841
		str[len] = '\0';
842
	else if (size > 0)
843
		str[size - 1] = '\0';
844
 
845
	if (overflow || len >= INT_MAX) {
846
		return -1;
847
	}
848
	return (int)len;
849
}
850
 
851
static void
852
fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
853
       int precision, int flags)
854
{
855
	int padlen, strln;	/* Amount to pad. */
856
	int noprecision = (precision == -1);
857
 
858
	if (value == NULL)	/* We're forgiving. */
859
		value = "(null)";
860
 
861
	/* If a precision was specified, don't read the string past it. */
862
	for (strln = 0; value[strln] != '\0' &&
863
	    (noprecision || strln < precision); strln++)
864
		continue;
865
 
866
	if ((padlen = width - strln) < 0)
867
		padlen = 0;
868
	if (flags & PRINT_F_MINUS)	/* Left justify. */
869
		padlen = -padlen;
870
 
871
	while (padlen > 0) {	/* Leading spaces. */
872
		OUTCHAR(str, *len, size, ' ');
873
		padlen--;
874
	}
875
	while (*value != '\0' && (noprecision || precision-- > 0)) {
876
		OUTCHAR(str, *len, size, *value);
877
		value++;
878
	}
879
	while (padlen < 0) {	/* Trailing spaces. */
880
		OUTCHAR(str, *len, size, ' ');
881
		padlen++;
882
	}
883
}
884
 
885
static void
886
fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
887
       int precision, int flags)
888
{
889
	UINTMAX_T uvalue;
890
	char iconvert[MAX_CONVERT_LENGTH];
891
	char sign = 0;
892
	char hexprefix = 0;
893
	int spadlen = 0;	/* Amount to space pad. */
894
	int zpadlen = 0;	/* Amount to zero pad. */
895
	int pos;
896
	int separators = (flags & PRINT_F_QUOTE);
897
	int noprecision = (precision == -1);
898
 
899
	if (flags & PRINT_F_UNSIGNED)
900
		uvalue = value;
901
	else {
902
		uvalue = (value >= 0) ? value : -value;
903
		if (value < 0)
904
			sign = '-';
905
		else if (flags & PRINT_F_PLUS)	/* Do a sign. */
906
			sign = '+';
907
		else if (flags & PRINT_F_SPACE)
908
			sign = ' ';
909
	}
910
 
911
	pos = convert(uvalue, iconvert, sizeof(iconvert), base,
912
	    flags & PRINT_F_UP);
913
 
914
	if (flags & PRINT_F_NUM && uvalue != 0) {
915
		/*
916
		 * C99 says: "The result is converted to an `alternative form'.
917
		 * For `o' conversion, it increases the precision, if and only
918
		 * if necessary, to force the first digit of the result to be a
919
		 * zero (if the value and precision are both 0, a single 0 is
920
		 * printed).  For `x' (or `X') conversion, a nonzero result has
921
		 * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
922
		 */
923
		switch (base) {
924
		case 8:
925
			if (precision <= pos)
926
				precision = pos + 1;
927
			break;
928
		case 16:
929
			hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
930
			break;
931
		}
932
	}
933
 
934
	if (separators)	/* Get the number of group separators we'll print. */
935
		separators = getnumsep(pos);
936
 
937
	zpadlen = precision - pos - separators;
938
	spadlen = width                         /* Minimum field width. */
939
	    - separators                        /* Number of separators. */
940
	    - MAX(precision, pos)               /* Number of integer digits. */
941
	    - ((sign != 0) ? 1 : 0)             /* Will we print a sign? */
942
	    - ((hexprefix != 0) ? 2 : 0);       /* Will we print a prefix? */
943
 
944
	if (zpadlen < 0)
945
		zpadlen = 0;
946
	if (spadlen < 0)
947
		spadlen = 0;
948
 
949
	/*
950
	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
951
	 * ignored.  For `d', `i', `o', `u', `x', and `X' conversions, if a
952
	 * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
953
	 */
954
	if (flags & PRINT_F_MINUS)	/* Left justify. */
955
		spadlen = -spadlen;
956
	else if (flags & PRINT_F_ZERO && noprecision) {
957
		zpadlen += spadlen;
958
		spadlen = 0;
959
	}
960
	while (spadlen > 0) {	/* Leading spaces. */
961
		OUTCHAR(str, *len, size, ' ');
962
		spadlen--;
963
	}
964
	if (sign != 0)	/* Sign. */
965
		OUTCHAR(str, *len, size, sign);
966
	if (hexprefix != 0) {	/* A "0x" or "0X" prefix. */
967
		OUTCHAR(str, *len, size, '0');
968
		OUTCHAR(str, *len, size, hexprefix);
969
	}
970
	while (zpadlen > 0) {	/* Leading zeros. */
971
		OUTCHAR(str, *len, size, '0');
972
		zpadlen--;
973
	}
974
	while (pos > 0) {	/* The actual digits. */
975
		pos--;
976
		OUTCHAR(str, *len, size, iconvert[pos]);
977
		if (separators > 0 && pos > 0 && pos % 3 == 0)
978
			printsep(str, len, size);
979
	}
980
	while (spadlen < 0) {	/* Trailing spaces. */
981
		OUTCHAR(str, *len, size, ' ');
982
		spadlen++;
983
	}
984
}
985
 
986
static void
987
fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
988
       int precision, int flags, int *overflow)
989
{
990
	LDOUBLE ufvalue;
991
	UINTMAX_T intpart;
992
	UINTMAX_T fracpart;
993
	UINTMAX_T mask;
994
	const char *infnan = NULL;
995
	char iconvert[MAX_CONVERT_LENGTH];
996
	char fconvert[MAX_CONVERT_LENGTH];
997
	char econvert[4];	/* "e-12" (without nul-termination). */
998
	char esign = 0;
999
	char sign = 0;
1000
	int leadfraczeros = 0;
1001
	int exponent = 0;
1002
	int emitpoint = 0;
1003
	int omitzeros = 0;
1004
	int omitcount = 0;
1005
	int padlen = 0;
1006
	int epos = 0;
1007
	int fpos = 0;
1008
	int ipos = 0;
1009
	int separators = (flags & PRINT_F_QUOTE);
1010
	int estyle = (flags & PRINT_F_TYPE_E);
1011
#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1012
	struct lconv *lc = localeconv();
1013
#endif	/* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1014
 
1015
	/*
1016
	 * AIX' man page says the default is 0, but C99 and at least Solaris'
1017
	 * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
1018
	 * defaults to 6.
1019
	 */
1020
	if (precision == -1)
1021
		precision = 6;
1022
 
1023
	if (fvalue < 0.0)
1024
		sign = '-';
1025
	else if (flags & PRINT_F_PLUS)	/* Do a sign. */
1026
		sign = '+';
1027
	else if (flags & PRINT_F_SPACE)
1028
		sign = ' ';
1029
 
1030
	if (ISNAN(fvalue))
1031
		infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
1032
	else if (ISINF(fvalue))
1033
		infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
1034
 
1035
	if (infnan != NULL) {
1036
		if (sign != 0)
1037
			iconvert[ipos++] = sign;
1038
		while (*infnan != '\0')
1039
			iconvert[ipos++] = *infnan++;
1040
		fmtstr(str, len, size, iconvert, width, ipos, flags);
1041
		return;
1042
	}
1043
 
1044
	/* "%e" (or "%E") or "%g" (or "%G") conversion. */
1045
	if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
1046
		if (flags & PRINT_F_TYPE_G) {
1047
			/*
1048
			 * For "%g" (and "%G") conversions, the precision
1049
			 * specifies the number of significant digits, which
1050
			 * includes the digits in the integer part.  The
1051
			 * conversion will or will not be using "e-style" (like
1052
			 * "%e" or "%E" conversions) depending on the precision
1053
			 * and on the exponent.  However, the exponent can be
1054
			 * affected by rounding the converted value, so we'll
1055
			 * leave this decision for later.  Until then, we'll
1056
			 * assume that we're going to do an "e-style" conversion
1057
			 * (in order to get the exponent calculated).  For
1058
			 * "e-style", the precision must be decremented by one.
1059
			 */
1060
			precision--;
1061
			/*
1062
			 * For "%g" (and "%G") conversions, trailing zeros are
1063
			 * removed from the fractional portion of the result
1064
			 * unless the "#" flag was specified.
1065
			 */
1066
			if (!(flags & PRINT_F_NUM))
1067
				omitzeros = 1;
1068
		}
1069
		exponent = getexponent(fvalue);
1070
		estyle = 1;
1071
	}
1072
 
1073
again:
1074
	/*
1075
	 * Sorry, we only support 9, 19, or 38 digits (that is, the number of
1076
	 * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
1077
	 * minus one) past the decimal point due to our conversion method.
1078
	 */
1079
	switch (sizeof(UINTMAX_T)) {
1080
	case 16:
1081
		if (precision > 38)
1082
			precision = 38;
1083
		break;
1084
	case 8:
1085
		if (precision > 19)
1086
			precision = 19;
1087
		break;
1088
	default:
1089
		if (precision > 9)
1090
			precision = 9;
1091
		break;
1092
	}
1093
 
1094
	ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
1095
	if (estyle)	/* We want exactly one integer digit. */
1096
		ufvalue /= mypow10(exponent);
1097
 
1098
	if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
1099
		*overflow = 1;
1100
		return;
1101
	}
1102
 
1103
	/*
1104
	 * Factor of ten with the number of digits needed for the fractional
1105
	 * part.  For example, if the precision is 3, the mask will be 1000.
1106
	 */
1107
	mask = (UINTMAX_T)mypow10(precision);
1108
	/*
1109
	 * We "cheat" by converting the fractional part to integer by
1110
	 * multiplying by a factor of ten.
1111
	 */
1112
	if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
1113
		/*
1114
		 * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
1115
		 * (because precision = 3).  Now, myround(1000 * 0.99962) will
1116
		 * return 1000.  So, the integer part must be incremented by one
1117
		 * and the fractional part must be set to zero.
1118
		 */
1119
		intpart++;
1120
		fracpart = 0;
1121
		if (estyle && intpart == 10) {
1122
			/*
1123
			 * The value was rounded up to ten, but we only want one
1124
			 * integer digit if using "e-style".  So, the integer
1125
			 * part must be set to one and the exponent must be
1126
			 * incremented by one.
1127
			 */
1128
			intpart = 1;
1129
			exponent++;
1130
		}
1131
	}
1132
 
1133
	/*
1134
	 * Now that we know the real exponent, we can check whether or not to
1135
	 * use "e-style" for "%g" (and "%G") conversions.  If we don't need
1136
	 * "e-style", the precision must be adjusted and the integer and
1137
	 * fractional parts must be recalculated from the original value.
1138
	 *
1139
	 * C99 says: "Let P equal the precision if nonzero, 6 if the precision
1140
	 * is omitted, or 1 if the precision is zero.  Then, if a conversion
1141
	 * with style `E' would have an exponent of X:
1142
	 *
1143
	 * - if P > X >= -4, the conversion is with style `f' (or `F') and
1144
	 *   precision P - (X + 1).
1145
	 *
1146
	 * - otherwise, the conversion is with style `e' (or `E') and precision
1147
	 *   P - 1." (7.19.6.1, 8)
1148
	 *
1149
	 * Note that we had decremented the precision by one.
1150
	 */
1151
	if (flags & PRINT_F_TYPE_G && estyle &&
1152
	    precision + 1 > exponent && exponent >= -4) {
1153
		precision -= exponent;
1154
		estyle = 0;
1155
		goto again;
1156
	}
1157
 
1158
	if (estyle) {
1159
		if (exponent < 0) {
1160
			exponent = -exponent;
1161
			esign = '-';
1162
		} else
1163
			esign = '+';
1164
 
1165
		/*
1166
		 * Convert the exponent.  The sizeof(econvert) is 4.  So, the
1167
		 * econvert buffer can hold e.g. "e+99" and "e-99".  We don't
1168
		 * support an exponent which contains more than two digits.
1169
		 * Therefore, the following stores are safe.
1170
		 */
1171
		epos = convert(exponent, econvert, 2, 10, 0);
1172
		/*
1173
		 * C99 says: "The exponent always contains at least two digits,
1174
		 * and only as many more digits as necessary to represent the
1175
		 * exponent." (7.19.6.1, 8)
1176
		 */
1177
		if (epos == 1)
1178
			econvert[epos++] = '0';
1179
		econvert[epos++] = esign;
1180
		econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
1181
	}
1182
 
1183
	/* Convert the integer part and the fractional part. */
1184
	ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
1185
	if (fracpart != 0)	/* convert() would return 1 if fracpart == 0. */
1186
		fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
1187
 
1188
	leadfraczeros = precision - fpos;
1189
 
1190
	if (omitzeros) {
1191
		if (fpos > 0)	/* Omit trailing fractional part zeros. */
1192
			while (omitcount < fpos && fconvert[omitcount] == '0')
1193
				omitcount++;
1194
		else {	/* The fractional part is zero, omit it completely. */
1195
			omitcount = precision;
1196
			leadfraczeros = 0;
1197
		}
1198
		precision -= omitcount;
1199
	}
1200
 
1201
	/*
1202
	 * Print a decimal point if either the fractional part is non-zero
1203
	 * and/or the "#" flag was specified.
1204
	 */
1205
	if (precision > 0 || flags & PRINT_F_NUM)
1206
		emitpoint = 1;
1207
	if (separators)	/* Get the number of group separators we'll print. */
1208
		separators = getnumsep(ipos);
1209
 
1210
	padlen = width                  /* Minimum field width. */
1211
	    - ipos                      /* Number of integer digits. */
1212
	    - epos                      /* Number of exponent characters. */
1213
	    - precision                 /* Number of fractional digits. */
1214
	    - separators                /* Number of group separators. */
1215
	    - (emitpoint ? 1 : 0)       /* Will we print a decimal point? */
1216
	    - ((sign != 0) ? 1 : 0);    /* Will we print a sign character? */
1217
 
1218
	if (padlen < 0)
1219
		padlen = 0;
1220
 
1221
	/*
1222
	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
1223
	 * ignored." (7.19.6.1, 6)
1224
	 */
1225
	if (flags & PRINT_F_MINUS)	/* Left justifty. */
1226
		padlen = -padlen;
1227
	else if (flags & PRINT_F_ZERO && padlen > 0) {
1228
		if (sign != 0) {	/* Sign. */
1229
			OUTCHAR(str, *len, size, sign);
1230
			sign = 0;
1231
		}
1232
		while (padlen > 0) {	/* Leading zeros. */
1233
			OUTCHAR(str, *len, size, '0');
1234
			padlen--;
1235
		}
1236
	}
1237
	while (padlen > 0) {	/* Leading spaces. */
1238
		OUTCHAR(str, *len, size, ' ');
1239
		padlen--;
1240
	}
1241
	if (sign != 0)	/* Sign. */
1242
		OUTCHAR(str, *len, size, sign);
1243
	while (ipos > 0) {	/* Integer part. */
1244
		ipos--;
1245
		OUTCHAR(str, *len, size, iconvert[ipos]);
1246
		if (separators > 0 && ipos > 0 && ipos % 3 == 0)
1247
			printsep(str, len, size);
1248
	}
1249
	if (emitpoint) {	/* Decimal point. */
1250
#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1251
		if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
1252
			OUTCHAR(str, *len, size, *lc->decimal_point);
1253
		else	/* We'll always print some decimal point character. */
1254
#endif	/* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1255
			OUTCHAR(str, *len, size, '.');
1256
	}
1257
	while (leadfraczeros > 0) {	/* Leading fractional part zeros. */
1258
		OUTCHAR(str, *len, size, '0');
1259
		leadfraczeros--;
1260
	}
1261
	while (fpos > omitcount) {	/* The remaining fractional part. */
1262
		fpos--;
1263
		OUTCHAR(str, *len, size, fconvert[fpos]);
1264
	}
1265
	while (epos > 0) {	/* Exponent. */
1266
		epos--;
1267
		OUTCHAR(str, *len, size, econvert[epos]);
1268
	}
1269
	while (padlen < 0) {	/* Trailing spaces. */
1270
		OUTCHAR(str, *len, size, ' ');
1271
		padlen++;
1272
	}
1273
}
1274
 
1275
static void
1276
printsep(char *str, size_t *len, size_t size)
1277
{
1278
#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1279
	struct lconv *lc = localeconv();
1280
	int i;
1281
 
1282
	if (lc->thousands_sep != NULL)
1283
		for (i = 0; lc->thousands_sep[i] != '\0'; i++)
1284
			OUTCHAR(str, *len, size, lc->thousands_sep[i]);
1285
	else
1286
#endif	/* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1287
		OUTCHAR(str, *len, size, ',');
1288
}
1289
 
1290
static int
1291
getnumsep(int digits)
1292
{
1293
	int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
1294
#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1295
	int strln;
1296
	struct lconv *lc = localeconv();
1297
 
1298
	/* We support an arbitrary separator length (including zero). */
1299
	if (lc->thousands_sep != NULL) {
1300
		for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
1301
			continue;
1302
		separators *= strln;
1303
	}
1304
#endif	/* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1305
	return separators;
1306
}
1307
 
1308
static int
1309
getexponent(LDOUBLE value)
1310
{
1311
	LDOUBLE tmp = (value >= 0.0) ? value : -value;
1312
	int exponent = 0;
1313
 
1314
	/*
1315
	 * We check for 99 > exponent > -99 in order to work around possible
1316
	 * endless loops which could happen (at least) in the second loop (at
1317
	 * least) if we're called with an infinite value.  However, we checked
1318
	 * for infinity before calling this function using our ISINF() macro, so
1319
	 * this might be somewhat paranoid.
1320
	 */
1321
	while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
1322
		tmp *= 10;
1323
	while (tmp >= 10.0 && ++exponent < 99)
1324
		tmp /= 10;
1325
 
1326
	return exponent;
1327
}
1328
 
1329
static int
1330
convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
1331
{
1332
	const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
1333
	size_t pos = 0;
1334
 
1335
	/* We return an unterminated buffer with the digits in reverse order. */
1336
	do {
1337
		buf[pos++] = digits[value % base];
1338
		value /= base;
1339
	} while (value != 0 && pos < size);
1340
 
1341
	return (int)pos;
1342
}
1343
 
1344
static UINTMAX_T
1345
cast(LDOUBLE value)
1346
{
1347
	UINTMAX_T result;
1348
 
1349
	/*
1350
	 * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
1351
	 * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
1352
	 * it may be increased to the nearest higher representable value for the
1353
	 * comparison (cf. C99: 6.3.1.4, 2).  It might then equal the LDOUBLE
1354
	 * value although converting the latter to UINTMAX_T would overflow.
1355
	 */
1356
	if (value >= UINTMAX_MAX)
1357
		return UINTMAX_MAX;
1358
 
1359
	result = (UINTMAX_T)value;
1360
	/*
1361
	 * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
1362
	 * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
1363
	 * the standard).  Sigh.
1364
	 */
1365
	return (result <= value) ? result : result - 1;
1366
}
1367
 
1368
static UINTMAX_T
1369
myround(LDOUBLE value)
1370
{
1371
	UINTMAX_T intpart = cast(value);
1372
 
1373
	return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
1374
}
1375
 
1376
static LDOUBLE
1377
mypow10(int exponent)
1378
{
1379
	LDOUBLE result = 1;
1380
 
1381
	while (exponent > 0) {
1382
		result *= 10;
1383
		exponent--;
1384
	}
1385
	while (exponent < 0) {
1386
		result /= 10;
1387
		exponent++;
1388
	}
1389
	return result;
1390
}
1391
#endif	/* !HAVE_VSNPRINTF */
1392
 
1393
#if !HAVE_VASPRINTF
1394
#if NEED_MYMEMCPY
1395
void *
1396
mymemcpy(void *dst, void *src, size_t len)
1397
{
1398
	const char *from = src;
1399
	char *to = dst;
1400
 
1401
	/* No need for optimization, we use this only to replace va_copy(3). */
1402
	while (len-- > 0)
1403
		*to++ = *from++;
1404
	return dst;
1405
}
1406
#endif	/* NEED_MYMEMCPY */
1407
 
1408
int
1409
util_vasprintf(char **ret, const char *format, va_list ap)
1410
{
1411
	size_t size;
1412
	int len;
1413
	va_list aq;
1414
 
1415
	VA_COPY(aq, ap);
1416
	len = vsnprintf(NULL, 0, format, aq);
1417
	VA_END_COPY(aq);
1418
	if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
1419
		return -1;
1420
	return vsnprintf(*ret, size, format, ap);
1421
}
1422
#endif	/* !HAVE_VASPRINTF */
1423
 
1424
#if !HAVE_SNPRINTF
1425
#if HAVE_STDARG_H
1426
int
1427
util_snprintf(char *str, size_t size, const char *format, ...)
1428
#else
1429
int
1430
util_snprintf(va_alist) va_dcl
1431
#endif	/* HAVE_STDARG_H */
1432
{
1433
#if !HAVE_STDARG_H
1434
	char *str;
1435
	size_t size;
1436
	char *format;
1437
#endif	/* HAVE_STDARG_H */
1438
	va_list ap;
1439
	int len;
1440
 
1441
	VA_START(ap, format);
1442
	VA_SHIFT(ap, str, char *);
1443
	VA_SHIFT(ap, size, size_t);
1444
	VA_SHIFT(ap, format, const char *);
1445
	len = vsnprintf(str, size, format, ap);
1446
	va_end(ap);
1447
	return len;
1448
}
1449
#endif	/* !HAVE_SNPRINTF */
1450
 
1451
#if !HAVE_ASPRINTF
1452
#if HAVE_STDARG_H
1453
int
1454
util_asprintf(char **ret, const char *format, ...)
1455
#else
1456
int
1457
util_asprintf(va_alist) va_dcl
1458
#endif	/* HAVE_STDARG_H */
1459
{
1460
#if !HAVE_STDARG_H
1461
	char **ret;
1462
	char *format;
1463
#endif	/* HAVE_STDARG_H */
1464
	va_list ap;
1465
	int len;
1466
 
1467
	VA_START(ap, format);
1468
	VA_SHIFT(ap, ret, char **);
1469
	VA_SHIFT(ap, format, const char *);
1470
	len = vasprintf(ret, format, ap);
1471
	va_end(ap);
1472
	return len;
1473
}
1474
#endif	/* !HAVE_ASPRINTF */
1475
#else	/* Dummy declaration to avoid empty translation unit warnings. */
1476
int main(void);
1477
#endif	/* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
1478
 
1479
 
1480
/* vim: set joinspaces textwidth=80: */