]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/sh/snprintf.c
bash-5.2 distribution sources and documentation
[thirdparty/bash.git] / lib / sh / snprintf.c
CommitLineData
3185942a
JA
1/* snprintf - formatted output to strings, with bounds checking and allocation */
2
f73dda09
JA
3/*
4 build a test version with
5 gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o
6*/
7
8/*
9 Unix snprintf implementation.
10 derived from inetutils/libinetutils/snprintf.c Version 1.1
11
8868edaf 12 Copyright (C) 2001-2020 Free Software Foundation, Inc.
3185942a
JA
13
14 This file is part of GNU Bash, the Bourne Again SHell.
f73dda09 15
3185942a
JA
16 Bash is free software: you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation, either version 3 of the License, or
f73dda09 19 (at your option) any later version.
3185942a
JA
20
21 Bash is distributed in the hope that it will be useful,
f73dda09
JA
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3185942a
JA
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with Bash. If not, see <http://www.gnu.org/licenses/>.
f73dda09 28
ac50fbac 29 Original (pre-bash) Revision History:
f73dda09
JA
30
31 1.1:
32 * added changes from Miles Bader
33 * corrected a bug with %f
34 * added support for %#g
35 * added more comments :-)
36 1.0:
37 * supporting must ANSI syntaxic_sugars
38 0.0:
39 * support %s %c %d
40
41 THANKS(for the patches and ideas):
42 Miles Bader
43 Cyrille Rustom
44 Jacek Slabocewiz
45 Mike Parker(mouse)
46
47*/
48
49/*
50 * Currently doesn't handle (and bash/readline doesn't use):
b80f6443
JA
51 * * *M$ width, precision specifications
52 * * %N$ numbered argument conversions
b80f6443
JA
53 * * support for `F' is imperfect with ldfallback(), since underlying
54 * printf may not handle it -- should ideally have another autoconf test
f73dda09
JA
55 */
56
57#define FLOATING_POINT
58
59#ifdef HAVE_CONFIG_H
60# include <config.h>
61#endif
62
0001803f
CR
63/* GCC 4.2 on Snow Leopard doesn't like the snprintf prototype */
64#if defined(DEBUG) && !defined (MACOSX)
3185942a
JA
65# undef HAVE_SNPRINTF
66# undef HAVE_ASPRINTF
0001803f
CR
67
68# define HAVE_SNPRINTF 0
69# define HAVE_ASPRINTF 0
3185942a
JA
70#endif
71
f73dda09 72#if defined(DRIVER) && !defined(HAVE_CONFIG_H)
74091dd4 73#define HAVE_LONG_LONG_INT
f73dda09
JA
74#define HAVE_LONG_DOUBLE
75#ifdef __linux__
76#define HAVE_PRINTF_A_FORMAT
77#endif
7117c2d2 78#define HAVE_ISINF_IN_LIBC
0628567a 79#define HAVE_ISNAN_IN_LIBC
f73dda09
JA
80#define PREFER_STDARG
81#define HAVE_STRINGIZE
82#define HAVE_LIMITS_H
83#define HAVE_STDDEF_H
7117c2d2 84#define HAVE_LOCALE_H
f73dda09
JA
85#define intmax_t long
86#endif
87
0001803f 88#if !HAVE_SNPRINTF || !HAVE_ASPRINTF
f73dda09
JA
89
90#include <bashtypes.h>
91
92#if defined(PREFER_STDARG)
93# include <stdarg.h>
94#else
95# include <varargs.h>
96#endif
97
98#ifdef HAVE_LIMITS_H
99# include <limits.h>
100#endif
101#include <bashansi.h>
102#ifdef HAVE_STDDEF_H
103# include <stddef.h>
104#endif
105#include <chartypes.h>
106
107#ifdef HAVE_STDINT_H
108# include <stdint.h>
109#endif
110
111#ifdef FLOATING_POINT
7117c2d2 112# include <float.h> /* for manifest constants */
f73dda09
JA
113# include <stdio.h> /* for sprintf */
114#endif
115
116#include <typemax.h>
117
7117c2d2
JA
118#ifdef HAVE_LOCALE_H
119# include <locale.h>
120#endif
121
f73dda09 122#include "stdc.h"
7117c2d2 123#include <shmbutil.h>
f73dda09
JA
124
125#ifndef DRIVER
126# include "shell.h"
127#else
128# define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
129# define FL_ADDBASE 0x02 /* add base# prefix to converted value */
130# define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
131# define FL_UNSIGNED 0x08 /* don't add any sign */
8868edaf
CR
132extern char *fmtulong PARAMS((unsigned long int, int, char *, size_t, int));
133extern char *fmtullong PARAMS((unsigned long long int, int, char *, size_t, int));
f73dda09
JA
134#endif
135
7117c2d2
JA
136#ifndef FREE
137# define FREE(x) if (x) free (x)
138#endif
139
f73dda09
JA
140/* Bound on length of the string representing an integer value of type T.
141 Subtract one for the sign bit if T is signed;
142 302 / 1000 is log10 (2) rounded up;
143 add one for integer division truncation;
144 add one more for a minus sign if t is signed. */
d233b485 145#ifndef INT_STRLEN_BOUND
f73dda09
JA
146#define INT_STRLEN_BOUND(t) \
147 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
148 + 1 + TYPE_SIGNED (t))
d233b485 149#endif
f73dda09
JA
150
151/* conversion flags */
152#define PF_ALTFORM 0x00001 /* # */
153#define PF_HEXPREFIX 0x00002 /* 0[Xx] */
154#define PF_LADJUST 0x00004 /* - */
155#define PF_ZEROPAD 0x00008 /* 0 */
156#define PF_PLUS 0x00010 /* + */
157#define PF_SPACE 0x00020 /* ' ' */
7117c2d2 158#define PF_THOUSANDS 0x00040 /* ' */
f73dda09
JA
159
160#define PF_DOT 0x00080 /* `.precision' */
161#define PF_STAR_P 0x00100 /* `*' after precision */
162#define PF_STAR_W 0x00200 /* `*' before or without precision */
163
164/* length modifiers */
165#define PF_SIGNEDCHAR 0x00400 /* hh */
166#define PF_SHORTINT 0x00800 /* h */
167#define PF_LONGINT 0x01000 /* l */
168#define PF_LONGLONG 0x02000 /* ll */
169#define PF_LONGDBL 0x04000 /* L */
170#define PF_INTMAX_T 0x08000 /* j */
171#define PF_SIZE_T 0x10000 /* z */
172#define PF_PTRDIFF_T 0x20000 /* t */
173
174#define PF_ALLOCBUF 0x40000 /* for asprintf, vasprintf */
175
176#define PFM_SN 0x01 /* snprintf, vsnprintf */
177#define PFM_AS 0x02 /* asprintf, vasprintf */
178
179#define ASBUFSIZE 128
180
181#define x_digs "0123456789abcdef"
182#define X_digs "0123456789ABCDEF"
183
184static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
185
7117c2d2
JA
186static int decpoint;
187static int thoussep;
188static char *grouping;
189
f73dda09
JA
190/*
191 * For the FLOATING POINT FORMAT :
192 * the challenge was finding a way to
193 * manipulate the Real numbers without having
194 * to resort to mathematical function(it
195 * would require to link with -lm) and not
196 * going down to the bit pattern(not portable)
197 *
198 * so a number, a real is:
199
200 real = integral + fraction
201
202 integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
203 fraction = b(1)*10^-1 + b(2)*10^-2 + ...
204
205 where:
206 0 <= a(i) => 9
207 0 <= b(i) => 9
208
209 from then it was simple math
210 */
211
212/*
213 * size of the buffer for the integral part
214 * and the fraction part
215 */
216#define MAX_INT 99 + 1 /* 1 for the null */
217#define MAX_FRACT 307 + 1
218
219/*
220 * These functions use static buffers to store the results,
221 * and so are not reentrant
222 */
223#define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
224#define dtoa(n, p, f) numtoa(n, 10, p, f)
225
226#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
227
7117c2d2
JA
228#define GETARG(type) (va_arg(args, type))
229
f73dda09
JA
230/* Macros that do proper sign extension and handle length modifiers. Used
231 for the integer conversion specifiers. */
232#define GETSIGNED(p) \
233 (((p)->flags & PF_LONGINT) \
7117c2d2
JA
234 ? GETARG (long) \
235 : (((p)->flags & PF_SHORTINT) ? (long)(short)GETARG (int) \
236 : (long)GETARG (int)))
f73dda09
JA
237
238#define GETUNSIGNED(p) \
239 (((p)->flags & PF_LONGINT) \
7117c2d2
JA
240 ? GETARG (unsigned long) \
241 : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)GETARG (int) \
242 : (unsigned long)GETARG (unsigned int)))
f73dda09
JA
243
244
245#ifdef HAVE_LONG_DOUBLE
7117c2d2 246#define GETLDOUBLE(p) GETARG (long double)
f73dda09 247#endif
7117c2d2 248#define GETDOUBLE(p) GETARG (double)
f73dda09
JA
249
250#define SET_SIZE_FLAGS(p, type) \
251 if (sizeof (type) > sizeof (int)) \
252 (p)->flags |= PF_LONGINT; \
253 if (sizeof (type) > sizeof (long)) \
254 (p)->flags |= PF_LONGLONG;
255
256/* this struct holds everything we need */
257struct DATA
258{
259 int length;
260 char *base; /* needed for [v]asprintf */
261 char *holder;
262 int counter;
263 const char *pf;
264
265/* FLAGS */
266 int flags;
267 int justify;
268 int width, precision;
269 char pad;
270};
271
272/* the floating point stuff */
273#ifdef FLOATING_POINT
8868edaf
CR
274static double pow_10 PARAMS((int));
275static int log_10 PARAMS((double));
276static double integral PARAMS((double, double *));
277static char *numtoa PARAMS((double, int, int, char **));
f73dda09
JA
278#endif
279
8868edaf
CR
280static void init_data PARAMS((struct DATA *, char *, size_t, const char *, int));
281static void init_conv_flag PARAMS((struct DATA *));
f73dda09
JA
282
283/* for the format */
284#ifdef FLOATING_POINT
8868edaf
CR
285static void floating PARAMS((struct DATA *, double));
286static void exponent PARAMS((struct DATA *, double));
f73dda09 287#endif
8868edaf 288static void number PARAMS((struct DATA *, unsigned long, int));
74091dd4 289#ifdef HAVE_LONG_LONG_INT
8868edaf 290static void lnumber PARAMS((struct DATA *, unsigned long long, int));
f73dda09 291#endif
8868edaf
CR
292static void pointer PARAMS((struct DATA *, unsigned long));
293static void strings PARAMS((struct DATA *, char *));
f73dda09
JA
294
295#ifdef FLOATING_POINT
296# define FALLBACK_FMTSIZE 32
297# define FALLBACK_BASE 4096
298# define LFALLBACK_BASE 5120
299# ifdef HAVE_LONG_DOUBLE
8868edaf 300static void ldfallback PARAMS((struct DATA *, const char *, const char *, long double));
f73dda09 301# endif
8868edaf 302static void dfallback PARAMS((struct DATA *, const char *, const char *, double));
f73dda09
JA
303#endif
304
8868edaf 305static char *groupnum PARAMS((char *));
7117c2d2 306
ac50fbac
CR
307#if defined (HAVE_LONG_DOUBLE)
308# define LONGDOUBLE long double
309#else
310# define LONGDOUBLE double
311#endif
312
313#ifndef isnan
314 static inline int isnan_f (float x) { return x != x; }
315 static inline int isnan_d (double x) { return x != x; }
316 static inline int isnan_ld (LONGDOUBLE x) { return x != x; }
317 # define isnan(x) \
318 (sizeof (x) == sizeof (LONGDOUBLE) ? isnan_ld (x) \
319 : sizeof (x) == sizeof (double) ? isnan_d (x) \
320 : isnan_f (x))
0001803f 321#endif
ac50fbac
CR
322
323#ifndef isinf
324 static inline int isinf_f (float x) { return !isnan (x) && isnan (x - x); }
325 static inline int isinf_d (double x) { return !isnan (x) && isnan (x - x); }
326 static inline int isinf_ld (LONGDOUBLE x) { return !isnan (x) && isnan (x - x); }
327 # define isinf(x) \
328 (sizeof (x) == sizeof (LONGDOUBLE) ? isinf_ld (x) \
329 : sizeof (x) == sizeof (double) ? isinf_d (x) \
330 : isinf_f (x))
0001803f
CR
331#endif
332
f73dda09
JA
333#ifdef DRIVER
334static void memory_error_and_abort ();
8868edaf
CR
335static void *xmalloc PARAMS((size_t));
336static void *xrealloc PARAMS((void *, size_t));
337static void xfree PARAMS((void *));
f73dda09
JA
338#else
339# include <xmalloc.h>
340#endif
341
342/* those are defines specific to snprintf to hopefully
343 * make the code clearer :-)
344 */
345#define RIGHT 1
346#define LEFT 0
347#define NOT_FOUND -1
348#define FOUND 1
349#define MAX_FIELD 15
350
351/* round off to the precision */
352#define ROUND(d, p) \
353 (d < 0.) ? \
354 d - pow_10(-(p)->precision) * 0.5 : \
355 d + pow_10(-(p)->precision) * 0.5
356
357/* set default precision */
358#define DEF_PREC(p) \
359 if ((p)->precision == NOT_FOUND) \
360 (p)->precision = 6
361
362/* put a char. increment the number of chars written even if we've exceeded
363 the vsnprintf/snprintf buffer size (for the return value) */
364#define PUT_CHAR(c, p) \
365 do \
366 { \
367 if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \
368 { \
369 (p)->length += ASBUFSIZE; \
370 (p)->base = (char *)xrealloc((p)->base, (p)->length); \
371 (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \
372 } \
373 if ((p)->counter < (p)->length) \
374 *(p)->holder++ = (c); \
375 (p)->counter++; \
376 } \
377 while (0)
378
7117c2d2
JA
379/* Output a string. P->WIDTH has already been adjusted for padding. */
380#define PUT_STRING(string, len, p) \
381 do \
382 { \
383 PAD_RIGHT (p); \
384 while ((len)-- > 0) \
385 { \
386 PUT_CHAR (*(string), (p)); \
387 (string)++; \
388 } \
389 PAD_LEFT (p); \
390 } \
391 while (0)
392
f73dda09 393#define PUT_PLUS(d, p, zero) \
ac50fbac 394 if (((p)->flags & PF_PLUS) && (d) > zero) \
f73dda09
JA
395 PUT_CHAR('+', p)
396
397#define PUT_SPACE(d, p, zero) \
398 if (((p)->flags & PF_SPACE) && (d) > zero) \
399 PUT_CHAR(' ', p)
400
401/* pad right */
402#define PAD_RIGHT(p) \
403 if ((p)->width > 0 && (p)->justify != LEFT) \
404 for (; (p)->width > 0; (p)->width--) \
405 PUT_CHAR((p)->pad, p)
406
407/* pad left */
408#define PAD_LEFT(p) \
409 if ((p)->width > 0 && (p)->justify == LEFT) \
410 for (; (p)->width > 0; (p)->width--) \
411 PUT_CHAR((p)->pad, p)
412
0628567a
JA
413/* pad with zeros from decimal precision */
414#define PAD_ZERO(p) \
415 if ((p)->precision > 0) \
416 for (; (p)->precision > 0; (p)->precision--) \
417 PUT_CHAR('0', p)
418
f73dda09
JA
419/* if width and prec. in the args */
420#define STAR_ARGS(p) \
95732b49 421 do { \
f73dda09 422 if ((p)->flags & PF_STAR_W) \
95732b49
JA
423 { \
424 (p)->width = GETARG (int); \
425 if ((p)->width < 0) \
426 { \
427 (p)->flags |= PF_LADJUST; \
428 (p)->justify = LEFT; \
429 (p)->width = -(p)->width; \
430 } \
431 } \
f73dda09 432 if ((p)->flags & PF_STAR_P) \
95732b49
JA
433 { \
434 (p)->precision = GETARG (int); \
435 if ((p)->precision < 0) \
436 { \
437 (p)->flags &= ~PF_STAR_P; \
438 (p)->precision = NOT_FOUND; \
439 } \
440 } \
441 } while (0)
7117c2d2 442
3185942a 443#if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV)
7117c2d2
JA
444# define GETLOCALEDATA(d, t, g) \
445 do \
446 { \
447 struct lconv *lv; \
448 if ((d) == 0) { \
449 (d) = '.'; (t) = -1; (g) = 0; /* defaults */ \
450 lv = localeconv(); \
451 if (lv) \
452 { \
453 if (lv->decimal_point && lv->decimal_point[0]) \
ac50fbac 454 (d) = lv->decimal_point[0]; \
7117c2d2 455 if (lv->thousands_sep && lv->thousands_sep[0]) \
ac50fbac 456 (t) = lv->thousands_sep[0]; \
7117c2d2
JA
457 (g) = lv->grouping ? lv->grouping : ""; \
458 if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
459 } \
460 } \
461 } \
462 while (0);
463#else
464# define GETLOCALEDATA(d, t, g) \
465 ( (d) = '.', (t) = ',', g = "\003" )
466#endif
f73dda09
JA
467
468#ifdef FLOATING_POINT
469/*
470 * Find the nth power of 10
471 */
472static double
473pow_10(n)
474 int n;
475{
476 double P;
477
478 /* handle common cases with fast switch statement. */
479 switch (n)
480 {
481 case -3: return .001;
482 case -2: return .01;
483 case -1: return .1;
484 case 0: return 1.;
485 case 1: return 10.;
486 case 2: return 100.;
487 case 3: return 1000.;
488 }
489
490 if (n < 0)
491 {
492 P = .0001;
493 for (n += 4; n < 0; n++)
494 P /= 10.;
495 }
496 else
497 {
498 P = 10000.;
499 for (n -= 4; n > 0; n--)
500 P *= 10.;
501 }
502
503 return P;
504}
505
506/*
507 * Find the integral part of the log in base 10
508 * Note: this not a real log10()
509 I just need and approximation(integerpart) of x in:
510 10^x ~= r
511 * log_10(200) = 2;
512 * log_10(250) = 2;
f1be666c
JA
513 *
514 * NOTE: do not call this with r == 0 -- an infinite loop results.
f73dda09
JA
515 */
516static int
517log_10(r)
518 double r;
519{
520 int i = 0;
521 double result = 1.;
522
523 if (r < 0.)
524 r = -r;
525
526 if (r < 1.)
527 {
528 while (result >= r)
529 {
530 result /= 10.;
531 i++;
532 }
533 return (-i);
534 }
535 else
536 {
537 while (result <= r)
538 {
539 result *= 10.;
540 i++;
541 }
542 return (i - 1);
543 }
544}
545
546/*
547 * This function return the fraction part of a double
548 * and set in ip the integral part.
549 * In many ways it resemble the modf() found on most Un*x
550 */
551static double
552integral(real, ip)
553 double real;
554 double *ip;
555{
556 int j;
557 double i, s, p;
558 double real_integral = 0.;
559
560 /* take care of the obvious */
561 /* equal to zero ? */
562 if (real == 0.)
563 {
564 *ip = 0.;
565 return (0.);
566 }
567
568 /* negative number ? */
569 if (real < 0.)
570 real = -real;
571
572 /* a fraction ? */
573 if ( real < 1.)
574 {
575 *ip = 0.;
576 return real;
577 }
578
579 /* the real work :-) */
580 for (j = log_10(real); j >= 0; j--)
581 {
582 p = pow_10(j);
583 s = (real - real_integral)/p;
584 i = 0.;
585 while (i + 1. <= s)
586 i++;
587 real_integral += i*p;
588 }
589 *ip = real_integral;
590 return (real - real_integral);
591}
592
593#define PRECISION 1.e-6
594/*
595 * return an ascii representation of the integral part of the number
596 * and set fract to be an ascii representation of the fraction part
ac50fbac 597 * the container for the fraction and the integral part or statically
f73dda09
JA
598 * declare with fix size
599 */
600static char *
601numtoa(number, base, precision, fract)
602 double number;
603 int base, precision;
604 char **fract;
605{
606 register int i, j;
607 double ip, fp; /* integer and fraction part */
608 double fraction;
ac50fbac 609 int digits, sign;
f73dda09
JA
610 static char integral_part[MAX_INT];
611 static char fraction_part[MAX_FRACT];
f73dda09
JA
612 int ch;
613
614 /* taking care of the obvious case: 0.0 */
615 if (number == 0.)
616 {
617 integral_part[0] = '0';
618 integral_part[1] = '\0';
f1be666c
JA
619 /* The fractional part has to take the precision into account */
620 for (ch = 0; ch < precision-1; ch++)
621 fraction_part[ch] = '0';
622 fraction_part[ch] = '0';
623 fraction_part[ch+1] = '\0';
7117c2d2
JA
624 if (fract)
625 *fract = fraction_part;
f73dda09
JA
626 return integral_part;
627 }
628
ac50fbac
CR
629 /* -0 is tricky */
630 sign = (number == -0.) ? '-' : ((number < 0.) ? '-' : '+');
631 digits = MAX_INT - 1;
632
f73dda09 633 /* for negative numbers */
ac50fbac 634 if (sign == '-')
f73dda09
JA
635 {
636 number = -number;
637 digits--; /* sign consume one digit */
638 }
639
640 fraction = integral(number, &ip);
641 number = ip;
642
643 /* do the integral part */
644 if (ip == 0.)
645 {
646 integral_part[0] = '0';
647 i = 1;
648 }
649 else
650 {
651 for ( i = 0; i < digits && number != 0.; ++i)
652 {
653 number /= base;
654 fp = integral(number, &ip);
655 ch = (int)((fp + PRECISION)*base); /* force to round */
656 integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
657 if (! ISXDIGIT((unsigned char)integral_part[i]))
658 break; /* bail out overflow !! */
659 number = ip;
660 }
661 }
662
663 /* Oh No !! out of bound, ho well fill it up ! */
664 if (number != 0.)
665 for (i = 0; i < digits; ++i)
666 integral_part[i] = '9';
667
668 /* put the sign ? */
ac50fbac 669 if (sign == '-')
f73dda09
JA
670 integral_part[i++] = '-';
671
672 integral_part[i] = '\0';
673
674 /* reverse every thing */
675 for ( i--, j = 0; j < i; j++, i--)
676 SWAP_INT(integral_part[i], integral_part[j]);
677
678 /* the fractional part */
679 for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--)
680 {
681 fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
682 if (! DIGIT(fraction_part[i])) /* underflow ? */
683 break;
684 fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
685 }
686 fraction_part[i] = '\0';
687
688 if (fract != (char **)0)
689 *fract = fraction_part;
690
691 return integral_part;
692}
693#endif
694
695/* for %d and friends, it puts in holder
696 * the representation with the right padding
697 */
698static void
699number(p, d, base)
700 struct DATA *p;
701 unsigned long d;
702 int base;
703{
7117c2d2 704 char *tmp, *t;
f73dda09
JA
705 long sd;
706 int flags;
707
ac50fbac
CR
708 /* An explicit precision turns off the zero-padding flag and sets the
709 pad character back to space. */
0628567a 710 if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
ac50fbac
CR
711 {
712 p->flags &= ~PF_ZEROPAD;
713 p->pad = ' ';
714 }
0628567a 715
f73dda09 716 sd = d; /* signed for ' ' padding in base 10 */
f1be666c
JA
717 flags = 0;
718 flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
f73dda09
JA
719 if (*p->pf == 'X')
720 flags |= FL_HEXUPPER;
721
722 tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
7117c2d2
JA
723 t = 0;
724 if ((p->flags & PF_THOUSANDS))
725 {
726 GETLOCALEDATA(decpoint, thoussep, grouping);
727 if (grouping && (t = groupnum (tmp)))
ac50fbac 728 tmp = t;
7117c2d2
JA
729 }
730
ac50fbac
CR
731 /* need to add one for any `+', but we only add one in base 10 */
732 p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
f73dda09
JA
733 PAD_RIGHT(p);
734
0628567a
JA
735 if ((p->flags & PF_DOT) && p->precision > 0)
736 {
737 p->precision -= strlen(tmp);
738 PAD_ZERO(p);
739 }
740
f73dda09
JA
741 switch (base)
742 {
743 case 10:
744 PUT_PLUS(sd, p, 0);
745 PUT_SPACE(sd, p, 0);
746 break;
747 case 8:
748 if (p->flags & PF_ALTFORM)
749 PUT_CHAR('0', p);
750 break;
751 case 16:
752 if (p->flags & PF_ALTFORM)
753 {
754 PUT_CHAR('0', p);
755 PUT_CHAR(*p->pf, p);
756 }
757 break;
758 }
759
760 while (*tmp)
761 {
762 PUT_CHAR(*tmp, p);
763 tmp++;
764 }
765
766 PAD_LEFT(p);
7117c2d2 767 FREE (t);
f73dda09
JA
768}
769
74091dd4 770#ifdef HAVE_LONG_LONG_INT
f73dda09
JA
771/*
772 * identical to number() but works for `long long'
773 */
774static void
775lnumber(p, d, base)
776 struct DATA *p;
777 unsigned long long d;
778 int base;
779{
7117c2d2 780 char *tmp, *t;
f73dda09
JA
781 long long sd;
782 int flags;
783
ac50fbac
CR
784 /* An explicit precision turns off the zero-padding flag and sets the
785 pad character back to space. */
0628567a 786 if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
ac50fbac
CR
787 {
788 p->flags &= ~PF_ZEROPAD;
789 p->pad = ' ';
790 }
0628567a 791
f73dda09 792 sd = d; /* signed for ' ' padding in base 10 */
f1be666c 793 flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
f73dda09
JA
794 if (*p->pf == 'X')
795 flags |= FL_HEXUPPER;
796
797 tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
7117c2d2
JA
798 t = 0;
799 if ((p->flags & PF_THOUSANDS))
800 {
801 GETLOCALEDATA(decpoint, thoussep, grouping);
802 if (grouping && (t = groupnum (tmp)))
ac50fbac 803 tmp = t;
7117c2d2
JA
804 }
805
ac50fbac
CR
806 /* need to add one for any `+', but we only add one in base 10 */
807 p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
f73dda09
JA
808 PAD_RIGHT(p);
809
0628567a
JA
810 if ((p->flags & PF_DOT) && p->precision > 0)
811 {
812 p->precision -= strlen(tmp);
813 PAD_ZERO(p);
814 }
815
f73dda09
JA
816 switch (base)
817 {
818 case 10:
819 PUT_PLUS(sd, p, 0);
820 PUT_SPACE(sd, p, 0);
821 break;
822 case 8:
823 if (p->flags & PF_ALTFORM)
824 PUT_CHAR('0', p);
825 break;
826 case 16:
827 if (p->flags & PF_ALTFORM)
828 {
829 PUT_CHAR('0', p);
830 PUT_CHAR(*p->pf, p);
831 }
832 break;
833 }
834
835 while (*tmp)
836 {
837 PUT_CHAR(*tmp, p);
838 tmp++;
839 }
840
841 PAD_LEFT(p);
7117c2d2 842 FREE (t);
f73dda09
JA
843}
844#endif
845
846static void
847pointer(p, d)
848 struct DATA *p;
849 unsigned long d;
850{
851 char *tmp;
852
853 tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0);
854 p->width -= strlen(tmp);
855 PAD_RIGHT(p);
856
857 /* prefix '0x' for pointers */
858 PUT_CHAR('0', p);
859 PUT_CHAR('x', p);
860
861 while (*tmp)
862 {
863 PUT_CHAR(*tmp, p);
864 tmp++;
865 }
f1be666c 866
f73dda09
JA
867 PAD_LEFT(p);
868}
869
870/* %s strings */
871static void
872strings(p, tmp)
873 struct DATA *p;
874 char *tmp;
875{
7117c2d2 876 size_t len;
f73dda09 877
7117c2d2 878 len = strlen(tmp);
f73dda09 879 if (p->precision != NOT_FOUND) /* the smallest number */
7117c2d2
JA
880 len = (len < p->precision ? len : p->precision);
881 p->width -= len;
882
883 PUT_STRING (tmp, len, p);
884}
885
886#if HANDLE_MULTIBYTE
887/* %ls wide-character strings */
888static void
889wstrings(p, tmp)
890 struct DATA *p;
891 wchar_t *tmp;
892{
893 size_t len;
894 mbstate_t mbs;
895 char *os;
896 const wchar_t *ws;
897
898 memset (&mbs, '\0', sizeof (mbstate_t));
899 ws = (const wchar_t *)tmp;
900
901 os = (char *)NULL;
902 if (p->precision != NOT_FOUND)
903 {
904 os = (char *)xmalloc (p->precision + 1);
905 len = wcsrtombs (os, &ws, p->precision, &mbs);
f73dda09 906 }
7117c2d2
JA
907 else
908 {
909 len = wcsrtombs (NULL, &ws, 0, &mbs);
910 if (len != (size_t)-1)
ac50fbac 911 {
7117c2d2
JA
912 memset (&mbs, '\0', sizeof (mbstate_t));
913 os = (char *)xmalloc (len + 1);
914 (void)wcsrtombs (os, &ws, len + 1, &mbs);
ac50fbac 915 }
7117c2d2
JA
916 }
917 if (len == (size_t)-1)
918 {
919 /* invalid multibyte sequence; bail now. */
920 FREE (os);
921 return;
922 }
923
924 p->width -= len;
925 PUT_STRING (os, len, p);
926 free (os);
f73dda09
JA
927}
928
7117c2d2
JA
929static void
930wchars (p, wc)
931 struct DATA *p;
932 wint_t wc;
933{
934 char *lbuf, *l;
935 mbstate_t mbs;
936 size_t len;
937
938 lbuf = (char *)malloc (MB_CUR_MAX+1);
939 if (lbuf == 0)
940 return;
941 memset (&mbs, '\0', sizeof (mbstate_t));
942 len = wcrtomb (lbuf, wc, &mbs);
943 if (len == (size_t)-1)
944 /* conversion failed; bail now. */
945 return;
946 p->width -= len;
947 l = lbuf;
948 PUT_STRING (l, len, p);
949 free (lbuf);
950}
951#endif /* HANDLE_MULTIBYTE */
952
f73dda09 953#ifdef FLOATING_POINT
7117c2d2 954
7117c2d2
JA
955/* Check for [+-]infinity and NaN. If MODE == 1, we check for Infinity, else
956 (mode == 2) we check for NaN. This does the necessary printing. Returns
957 1 if Inf or Nan, 0 if not. */
958static int
959chkinfnan(p, d, mode)
960 struct DATA *p;
961 double d;
962 int mode; /* == 1 for inf, == 2 for nan */
963{
964 int i;
965 char *tmp;
966 char *big, *small;
967
968 i = (mode == 1) ? isinf(d) : isnan(d);
969 if (i == 0)
970 return 0;
971 big = (mode == 1) ? "INF" : "NAN";
972 small = (mode == 1) ? "inf" : "nan";
973
974 tmp = (*p->pf == 'F' || *p->pf == 'G' || *p->pf == 'E') ? big : small;
975
976 if (i < 0)
977 PUT_CHAR('-', p);
978
979 while (*tmp)
980 {
981 PUT_CHAR (*tmp, p);
982 tmp++;
983 }
984
985 return 1;
986}
987
f73dda09
JA
988/* %f %F %g %G floating point representation */
989static void
990floating(p, d)
991 struct DATA *p;
992 double d;
993{
7117c2d2 994 char *tmp, *tmp2, *t;
f73dda09
JA
995 int i;
996
95732b49 997 if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
7117c2d2
JA
998 return; /* already printed nan or inf */
999
1000 GETLOCALEDATA(decpoint, thoussep, grouping);
f73dda09
JA
1001 DEF_PREC(p);
1002 d = ROUND(d, p);
1003 tmp = dtoa(d, p->precision, &tmp2);
7117c2d2
JA
1004 t = 0;
1005 if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
1006 tmp = t;
1007
f1be666c
JA
1008 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
1009 {
1010 /* smash the trailing zeros unless altform */
1011 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
ac50fbac 1012 tmp2[i] = '\0';
f1be666c
JA
1013 if (tmp2[0] == '\0')
1014 p->precision = 0;
1015 }
1016
f73dda09
JA
1017 /* calculate the padding. 1 for the dot */
1018 p->width = p->width -
ac50fbac
CR
1019 /* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
1020#if 0
f73dda09 1021 ((d > 0. && p->justify == RIGHT) ? 1:0) -
ac50fbac
CR
1022#else
1023 ((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
1024#endif
f73dda09 1025 ((p->flags & PF_SPACE) ? 1:0) -
f1be666c
JA
1026 strlen(tmp) - p->precision -
1027 ((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /* radix char */
ac50fbac
CR
1028
1029 if (p->pad == ' ')
1030 {
1031 PAD_RIGHT(p);
1032 PUT_PLUS(d, p, 0.);
1033 }
1034 else
1035 {
1036 if (*tmp == '-')
1037 PUT_CHAR(*tmp++, p);
1038 PUT_PLUS(d, p, 0.);
1039 PAD_RIGHT(p);
1040 }
f73dda09 1041 PUT_SPACE(d, p, 0.);
7117c2d2 1042
f73dda09 1043 while (*tmp)
95732b49
JA
1044 {
1045 PUT_CHAR(*tmp, p); /* the integral */
f73dda09
JA
1046 tmp++;
1047 }
7117c2d2
JA
1048 FREE (t);
1049
f73dda09 1050 if (p->precision != 0 || (p->flags & PF_ALTFORM))
7117c2d2
JA
1051 PUT_CHAR(decpoint, p); /* put the '.' */
1052
f73dda09
JA
1053 for (; *tmp2; tmp2++)
1054 PUT_CHAR(*tmp2, p); /* the fraction */
1055
1056 PAD_LEFT(p);
1057}
1058
1059/* %e %E %g %G exponent representation */
1060static void
1061exponent(p, d)
1062 struct DATA *p;
1063 double d;
1064{
1065 char *tmp, *tmp2;
7117c2d2 1066 int j, i;
f73dda09 1067
f1be666c 1068 if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
7117c2d2
JA
1069 return; /* already printed nan or inf */
1070
1071 GETLOCALEDATA(decpoint, thoussep, grouping);
f73dda09 1072 DEF_PREC(p);
f1be666c
JA
1073 if (d == 0.)
1074 j = 0;
1075 else
1076 {
1077 j = log_10(d);
1078 d = d / pow_10(j); /* get the Mantissa */
1079 d = ROUND(d, p);
1080 }
f73dda09 1081 tmp = dtoa(d, p->precision, &tmp2);
7117c2d2 1082
f73dda09 1083 /* 1 for unit, 1 for the '.', 1 for 'e|E',
ac50fbac 1084 * 1 for '+|-', 2 for 'exp' (but no `.' if precision == 0 */
f73dda09
JA
1085 /* calculate how much padding need */
1086 p->width = p->width -
ac50fbac
CR
1087 /* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
1088#if 0
f73dda09 1089 ((d > 0. && p->justify == RIGHT) ? 1:0) -
ac50fbac
CR
1090#else
1091 ((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
1092#endif
1093 (p->precision != 0 || (p->flags & PF_ALTFORM)) -
1094 ((p->flags & PF_SPACE) ? 1:0) - p->precision - 5;
7117c2d2 1095
ac50fbac
CR
1096 if (p->pad == ' ')
1097 {
1098 PAD_RIGHT(p);
1099 PUT_PLUS(d, p, 0.);
1100 }
1101 else
1102 {
1103 if (*tmp == '-')
1104 PUT_CHAR(*tmp++, p);
1105 PUT_PLUS(d, p, 0.);
1106 PAD_RIGHT(p);
1107 }
f73dda09 1108 PUT_SPACE(d, p, 0.);
f73dda09
JA
1109
1110 while (*tmp)
1111 {
1112 PUT_CHAR(*tmp, p);
1113 tmp++;
f73dda09
JA
1114 }
1115
7117c2d2
JA
1116 if (p->precision != 0 || (p->flags & PF_ALTFORM))
1117 PUT_CHAR(decpoint, p); /* the '.' */
1118
f73dda09
JA
1119 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
1120 /* smash the trailing zeros unless altform */
1121 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
7117c2d2
JA
1122 tmp2[i] = '\0';
1123
f73dda09 1124 for (; *tmp2; tmp2++)
7117c2d2 1125 PUT_CHAR(*tmp2, p); /* the fraction */
f73dda09
JA
1126
1127 /* the exponent put the 'e|E' */
1128 if (*p->pf == 'g' || *p->pf == 'e')
7117c2d2 1129 PUT_CHAR('e', p);
f73dda09 1130 else
7117c2d2 1131 PUT_CHAR('E', p);
f73dda09
JA
1132
1133 /* the sign of the exp */
95732b49 1134 if (j >= 0)
7117c2d2 1135 PUT_CHAR('+', p);
f73dda09
JA
1136 else
1137 {
1138 PUT_CHAR('-', p);
1139 j = -j;
1140 }
1141
1142 tmp = itoa(j);
1143 /* pad out to at least two spaces. pad with `0' if the exponent is a
1144 single digit. */
1145 if (j <= 9)
7117c2d2 1146 PUT_CHAR('0', p);
f73dda09
JA
1147
1148 /* the exponent */
1149 while (*tmp)
1150 {
1151 PUT_CHAR(*tmp, p);
1152 tmp++;
1153 }
f1be666c 1154
f73dda09
JA
1155 PAD_LEFT(p);
1156}
1157#endif
1158
7117c2d2
JA
1159/* Return a new string with the digits in S grouped according to the locale's
1160 grouping info and thousands separator. If no grouping should be performed,
1161 this returns NULL; the caller needs to check for it. */
1162static char *
1163groupnum (s)
1164 char *s;
1165{
1166 char *se, *ret, *re, *g;
1167 int len, slen;
1168
1169 if (grouping == 0 || *grouping <= 0 || *grouping == CHAR_MAX)
1170 return ((char *)NULL);
1171
1172 /* find min grouping to size returned string */
1173 for (len = *grouping, g = grouping; *g; g++)
1174 if (*g > 0 && *g < len)
1175 len = *g;
1176
1177 slen = strlen (s);
1178 len = slen / len + 1;
1179 ret = (char *)xmalloc (slen + len + 1);
1180 re = ret + slen + len;
1181 *re = '\0';
1182
1183 g = grouping;
1184 se = s + slen;
1185 len = *g;
1186
1187 while (se > s)
1188 {
1189 *--re = *--se;
1190
1191 /* handle `-' inserted by numtoa() and the fmtu* family here. */
1192 if (se > s && se[-1] == '-')
1193 continue;
1194
1195 /* begin new group. */
1196 if (--len == 0 && se > s)
1197 {
1198 *--re = thoussep;
1199 len = *++g; /* was g++, but that uses first char twice (glibc bug, too) */
1200 if (*g == '\0')
1201 len = *--g; /* use previous grouping */
1202 else if (*g == CHAR_MAX)
1203 {
1204 do
ac50fbac 1205 *--re = *--se;
7117c2d2
JA
1206 while (se > s);
1207 break;
1208 }
1209 }
1210 }
1211
1212 if (re > ret)
1213#ifdef HAVE_MEMMOVE
1214 memmove (ret, re, strlen (re) + 1);
1215#else
1216 strcpy (ret, re);
1217#endif
1218
1219 return ret;
1220}
1221
f73dda09
JA
1222/* initialize the conversion specifiers */
1223static void
1224init_conv_flag (p)
1225 struct DATA *p;
1226{
1227 p->flags &= PF_ALLOCBUF; /* preserve PF_ALLOCBUF flag */
1228 p->precision = p->width = NOT_FOUND;
1229 p->justify = NOT_FOUND;
1230 p->pad = ' ';
1231}
1232
1233static void
1234init_data (p, string, length, format, mode)
1235 struct DATA *p;
1236 char *string;
1237 size_t length;
1238 const char *format;
1239 int mode;
1240{
1241 p->length = length - 1; /* leave room for '\0' */
1242 p->holder = p->base = string;
1243 p->pf = format;
1244 p->counter = 0;
1245 p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0;
1246}
1247
1248static int
1249#if defined (__STDC__)
1250vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args)
1251#else
1252vsnprintf_internal(data, string, length, format, args)
1253 struct DATA *data;
1254 char *string;
1255 size_t length;
1256 const char *format;
1257 va_list args;
1258#endif
1259{
1260 double d; /* temporary holder */
1261#ifdef HAVE_LONG_DOUBLE
1262 long double ld; /* for later */
1263#endif
1264 unsigned long ul;
74091dd4 1265#ifdef HAVE_UNSIGNED_LONG_LONG_INT
f73dda09
JA
1266 unsigned long long ull;
1267#endif
1268 int state, i, c, n;
1269 char *s;
7117c2d2
JA
1270#if HANDLE_MULTIBYTE
1271 wchar_t *ws;
1272 wint_t wc;
1273#endif
f73dda09 1274 const char *convstart;
95732b49 1275 int negprec;
f73dda09 1276
7117c2d2
JA
1277 /* Sanity check, the string length must be >= 0. C99 actually says that
1278 LENGTH can be zero here, in the case of snprintf/vsnprintf (it's never
1279 0 in the case of asprintf/vasprintf), and the return value is the number
f73dda09 1280 of characters that would have been written. */
7117c2d2 1281 if (length < 0)
f73dda09
JA
1282 return -1;
1283
1284 if (format == 0)
1285 return 0;
1286
7117c2d2
JA
1287 /* Reset these for each call because the locale might have changed. */
1288 decpoint = thoussep = 0;
1289 grouping = 0;
1290
95732b49 1291 negprec = 0;
f73dda09
JA
1292 for (; c = *(data->pf); data->pf++)
1293 {
1294 if (c != '%')
1295 {
1296 PUT_CHAR (c, data);
1297 continue;
1298 }
1299
1300 convstart = data->pf;
1301 init_conv_flag (data); /* initialise format flags */
1302
1303 state = 1;
1304 for (state = 1; state && *data->pf; )
1305 {
1306 c = *(++data->pf);
1307 /* fmtend = data->pf */
1308#if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1309 if (data->flags & PF_LONGDBL)
1310 {
1311 switch (c)
1312 {
1313 case 'f': case 'F':
1314 case 'e': case 'E':
1315 case 'g': case 'G':
1316# ifdef HAVE_PRINTF_A_FORMAT
1317 case 'a': case 'A':
1318# endif
1319 STAR_ARGS (data);
1320 ld = GETLDOUBLE (data);
1321 ldfallback (data, convstart, data->pf, ld);
1322 goto conv_break;
1323 }
1324 }
1325#endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1326
1327 switch (c)
1328 {
1329 /* Parse format flags */
1330 case '\0': /* a NULL here ? ? bail out */
1331 *data->holder = '\0';
1332 return data->counter;
1333 break;
1334 case '#':
1335 data->flags |= PF_ALTFORM;
1336 continue;
f73dda09
JA
1337 case '*':
1338 if (data->flags & PF_DOT)
1339 data->flags |= PF_STAR_P;
1340 else
1341 data->flags |= PF_STAR_W;
1342 continue;
1343 case '-':
95732b49
JA
1344 if ((data->flags & PF_DOT) == 0)
1345 {
1346 data->flags |= PF_LADJUST;
1347 data->justify = LEFT;
1348 }
1349 else
1350 negprec = 1;
f73dda09
JA
1351 continue;
1352 case ' ':
1353 if ((data->flags & PF_PLUS) == 0)
1354 data->flags |= PF_SPACE;
1355 continue;
1356 case '+':
95732b49
JA
1357 if ((data->flags & PF_DOT) == 0)
1358 {
1359 data->flags |= PF_PLUS;
ac50fbac
CR
1360 if ((data->flags & PF_LADJUST) == 0)
1361 data->justify = RIGHT;
95732b49 1362 }
f73dda09 1363 continue;
7117c2d2
JA
1364 case '\'':
1365 data->flags |= PF_THOUSANDS;
f73dda09
JA
1366 continue;
1367
ac50fbac
CR
1368 case '0':
1369 /* If we're not specifying precision (in which case we've seen
1370 a `.') and we're not performing left-adjustment (in which
1371 case the `0' is ignored), a `0' is taken as the zero-padding
1372 flag. */
1373 if ((data->flags & (PF_DOT|PF_LADJUST)) == 0)
1374 {
1375 data->flags |= PF_ZEROPAD;
1376 data->pad = '0';
1377 continue;
1378 }
f73dda09
JA
1379 case '1': case '2': case '3':
1380 case '4': case '5': case '6':
1381 case '7': case '8': case '9':
1382 n = 0;
1383 do
1384 {
1385 n = n * 10 + TODIGIT(c);
1386 c = *(++data->pf);
1387 }
1388 while (DIGIT(c));
1389 data->pf--; /* went too far */
1390 if (n < 0)
1391 n = 0;
1392 if (data->flags & PF_DOT)
95732b49 1393 data->precision = negprec ? NOT_FOUND : n;
f73dda09
JA
1394 else
1395 data->width = n;
1396 continue;
1397
1398 /* optional precision */
1399 case '.':
1400 data->flags |= PF_DOT;
1401 data->precision = 0;
1402 continue;
1403
1404 /* length modifiers */
1405 case 'h':
1406 data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT;
1407 continue;
1408 case 'l':
1409 data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT;
1410 continue;
1411 case 'L':
1412 data->flags |= PF_LONGDBL;
1413 continue;
1414 case 'q':
1415 data->flags |= PF_LONGLONG;
1416 continue;
1417 case 'j':
1418 data->flags |= PF_INTMAX_T;
1419 SET_SIZE_FLAGS(data, intmax_t);
1420 continue;
1421 case 'z':
1422 data->flags |= PF_SIZE_T;
1423 SET_SIZE_FLAGS(data, size_t);
1424 continue;
1425 case 't':
1426 data->flags |= PF_PTRDIFF_T;
1427 SET_SIZE_FLAGS(data, ptrdiff_t);
1428 continue;
1429
1430 /* Conversion specifiers */
1431#ifdef FLOATING_POINT
1432 case 'f': /* float, double */
1433 case 'F':
1434 STAR_ARGS(data);
1435 d = GETDOUBLE(data);
1436 floating(data, d);
1437conv_break:
1438 state = 0;
1439 break;
1440 case 'g':
1441 case 'G':
1442 STAR_ARGS(data);
1443 DEF_PREC(data);
1444 d = GETDOUBLE(data);
f1be666c 1445 i = (d != 0.) ? log_10(d) : -1;
f73dda09
JA
1446 /*
1447 * for '%g|%G' ANSI: use f if exponent
1448 * is in the range or [-4,p] exclusively
1449 * else use %e|%E
1450 */
1451 if (-4 < i && i < data->precision)
7117c2d2
JA
1452 {
1453 /* reset precision */
1454 data->precision -= i + 1;
1455 floating(data, d);
1456 }
f73dda09 1457 else
7117c2d2
JA
1458 {
1459 /* reduce precision by 1 because of leading digit before
ac50fbac
CR
1460 decimal point in e format, unless specified as 0. */
1461 if (data->precision > 0)
1462 data->precision--;
7117c2d2
JA
1463 exponent(data, d);
1464 }
f73dda09
JA
1465 state = 0;
1466 break;
1467 case 'e':
1468 case 'E': /* Exponent double */
1469 STAR_ARGS(data);
1470 d = GETDOUBLE(data);
1471 exponent(data, d);
1472 state = 0;
1473 break;
1474# ifdef HAVE_PRINTF_A_FORMAT
1475 case 'a':
1476 case 'A':
1477 STAR_ARGS(data);
1478 d = GETDOUBLE(data);
1479 dfallback(data, convstart, data->pf, d);
1480 state = 0;
1481 break;
1482# endif /* HAVE_PRINTF_A_FORMAT */
1483#endif /* FLOATING_POINT */
1484 case 'U':
1485 data->flags |= PF_LONGINT;
1486 /* FALLTHROUGH */
1487 case 'u':
1488 STAR_ARGS(data);
74091dd4 1489#ifdef HAVE_LONG_LONG_INT
f73dda09
JA
1490 if (data->flags & PF_LONGLONG)
1491 {
7117c2d2 1492 ull = GETARG (unsigned long long);
f73dda09
JA
1493 lnumber(data, ull, 10);
1494 }
1495 else
1496#endif
1497 {
1498 ul = GETUNSIGNED(data);
1499 number(data, ul, 10);
1500 }
1501 state = 0;
1502 break;
1503 case 'D':
1504 data->flags |= PF_LONGINT;
1505 /* FALLTHROUGH */
1506 case 'd': /* decimal */
1507 case 'i':
1508 STAR_ARGS(data);
74091dd4 1509#ifdef HAVE_LONG_LONG_INT
f73dda09
JA
1510 if (data->flags & PF_LONGLONG)
1511 {
7117c2d2 1512 ull = GETARG (long long);
f73dda09
JA
1513 lnumber(data, ull, 10);
1514 }
1515 else
1516#endif
1517 {
1518 ul = GETSIGNED(data);
1519 number(data, ul, 10);
1520 }
1521 state = 0;
1522 break;
1523 case 'o': /* octal */
1524 STAR_ARGS(data);
74091dd4 1525#ifdef HAVE_LONG_LONG_INT
f73dda09
JA
1526 if (data->flags & PF_LONGLONG)
1527 {
7117c2d2 1528 ull = GETARG (unsigned long long);
f73dda09
JA
1529 lnumber(data, ull, 8);
1530 }
1531 else
1532#endif
1533 {
1534 ul = GETUNSIGNED(data);
1535 number(data, ul, 8);
1536 }
1537 state = 0;
1538 break;
1539 case 'x':
1540 case 'X': /* hexadecimal */
1541 STAR_ARGS(data);
74091dd4 1542#ifdef HAVE_LONG_LONG_INT
f73dda09
JA
1543 if (data->flags & PF_LONGLONG)
1544 {
7117c2d2 1545 ull = GETARG (unsigned long long);
f73dda09
JA
1546 lnumber(data, ull, 16);
1547 }
1548 else
1549#endif
1550 {
1551 ul = GETUNSIGNED(data);
1552 number(data, ul, 16);
1553 }
1554 state = 0;
1555 break;
1556 case 'p':
1557 STAR_ARGS(data);
7117c2d2 1558 ul = (unsigned long)GETARG (void *);
f73dda09
JA
1559 pointer(data, ul);
1560 state = 0;
1561 break;
7117c2d2
JA
1562#if HANDLE_MULTIBYTE
1563 case 'C':
1564 data->flags |= PF_LONGINT;
1565 /* FALLTHROUGH */
1566#endif
f73dda09 1567 case 'c': /* character */
7117c2d2
JA
1568 STAR_ARGS(data);
1569#if HANDLE_MULTIBYTE
1570 if (data->flags & PF_LONGINT)
1571 {
1572 wc = GETARG (wint_t);
1573 wchars (data, wc);
1574 }
1575 else
1576#endif
1577 {
1578 ul = GETARG (int);
1579 PUT_CHAR(ul, data);
1580 }
f73dda09
JA
1581 state = 0;
1582 break;
7117c2d2
JA
1583#if HANDLE_MULTIBYTE
1584 case 'S':
1585 data->flags |= PF_LONGINT;
1586 /* FALLTHROUGH */
1587#endif
f73dda09
JA
1588 case 's': /* string */
1589 STAR_ARGS(data);
7117c2d2
JA
1590#if HANDLE_MULTIBYTE
1591 if (data->flags & PF_LONGINT)
1592 {
1593 ws = GETARG (wchar_t *);
1594 wstrings (data, ws);
1595 }
1596 else
1597#endif
1598 {
1599 s = GETARG (char *);
1600 strings(data, s);
1601 }
f73dda09
JA
1602 state = 0;
1603 break;
1604 case 'n':
74091dd4 1605#ifdef HAVE_LONG_LONG_INT
f73dda09 1606 if (data->flags & PF_LONGLONG)
7117c2d2 1607 *(GETARG (long long *)) = data->counter;
f73dda09
JA
1608 else
1609#endif
1610 if (data->flags & PF_LONGINT)
7117c2d2 1611 *(GETARG (long *)) = data->counter;
f73dda09 1612 else if (data->flags & PF_SHORTINT)
7117c2d2 1613 *(GETARG (short *)) = data->counter;
f73dda09 1614 else
7117c2d2 1615 *(GETARG (int *)) = data->counter;
f73dda09
JA
1616 state = 0;
1617 break;
1618 case '%': /* nothing just % */
1619 PUT_CHAR('%', data);
1620 state = 0;
1621 break;
1622 default:
1623 /* is this an error ? maybe bail out */
1624 state = 0;
1625 break;
1626 } /* end switch */
1627 } /* end of `%' for loop */
1628 } /* end of format string for loop */
1629
1630 if (data->length >= 0)
1631 *data->holder = '\0'; /* the end ye ! */
1632
1633 return data->counter;
1634}
1635
1636#if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1637/*
1638 * Printing floating point numbers accurately is an art. I'm not good
1639 * at it. Fall back to sprintf for long double formats.
1640 */
1641static void
1642ldfallback (data, fs, fe, ld)
1643 struct DATA *data;
1644 const char *fs, *fe;
1645 long double ld;
1646{
1647 register char *x;
1648 char fmtbuf[FALLBACK_FMTSIZE], *obuf;
1649 int fl;
1650
95732b49
JA
1651 fl = LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2;
1652 obuf = (char *)xmalloc (fl);
f73dda09
JA
1653 fl = fe - fs + 1;
1654 strncpy (fmtbuf, fs, fl);
1655 fmtbuf[fl] = '\0';
95732b49
JA
1656
1657 if ((data->flags & PF_STAR_W) && (data->flags & PF_STAR_P))
1658 sprintf (obuf, fmtbuf, data->width, data->precision, ld);
1659 else if (data->flags & PF_STAR_W)
1660 sprintf (obuf, fmtbuf, data->width, ld);
1661 else if (data->flags & PF_STAR_P)
1662 sprintf (obuf, fmtbuf, data->precision, ld);
1663 else
1664 sprintf (obuf, fmtbuf, ld);
1665
f73dda09
JA
1666 for (x = obuf; *x; x++)
1667 PUT_CHAR (*x, data);
1668 xfree (obuf);
1669}
1670#endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1671
1672#ifdef FLOATING_POINT
1673/* Used for %a, %A if the libc printf supports them. */
1674static void
1675dfallback (data, fs, fe, d)
1676 struct DATA *data;
1677 const char *fs, *fe;
1678 double d;
1679{
1680 register char *x;
1681 char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE];
1682 int fl;
1683
1684 fl = fe - fs + 1;
1685 strncpy (fmtbuf, fs, fl);
1686 fmtbuf[fl] = '\0';
95732b49
JA
1687
1688 if ((data->flags & PF_STAR_W) && (data->flags & PF_STAR_P))
1689 sprintf (obuf, fmtbuf, data->width, data->precision, d);
1690 else if (data->flags & PF_STAR_W)
1691 sprintf (obuf, fmtbuf, data->width, d);
1692 else if (data->flags & PF_STAR_P)
1693 sprintf (obuf, fmtbuf, data->precision, d);
1694 else
1695 sprintf (obuf, fmtbuf, d);
1696
f73dda09
JA
1697 for (x = obuf; *x; x++)
1698 PUT_CHAR (*x, data);
1699}
1700#endif /* FLOATING_POINT */
1701
0001803f 1702#if !HAVE_SNPRINTF
f73dda09
JA
1703
1704int
1705#if defined (__STDC__)
1706vsnprintf(char *string, size_t length, const char *format, va_list args)
1707#else
1708vsnprintf(string, length, format, args)
1709 char *string;
1710 size_t length;
1711 const char *format;
1712 va_list args;
1713#endif
1714{
1715 struct DATA data;
1716
7117c2d2
JA
1717 if (string == 0 && length != 0)
1718 return 0;
f73dda09
JA
1719 init_data (&data, string, length, format, PFM_SN);
1720 return (vsnprintf_internal(&data, string, length, format, args));
1721}
1722
1723int
1724#if defined(PREFER_STDARG)
1725snprintf(char *string, size_t length, const char * format, ...)
1726#else
1727snprintf(string, length, format, va_alist)
1728 char *string;
1729 size_t length;
1730 const char *format;
1731 va_dcl
1732#endif
1733{
1734 struct DATA data;
1735 int rval;
1736 va_list args;
1737
7117c2d2 1738 SH_VA_START(args, format);
f73dda09 1739
7117c2d2
JA
1740 if (string == 0 && length != 0)
1741 return 0;
f73dda09
JA
1742 init_data (&data, string, length, format, PFM_SN);
1743 rval = vsnprintf_internal (&data, string, length, format, args);
1744
1745 va_end(args);
1746
1747 return rval;
1748}
1749
1750#endif /* HAVE_SNPRINTF */
1751
0001803f 1752#if !HAVE_ASPRINTF
f73dda09
JA
1753
1754int
1755#if defined (__STDC__)
1756vasprintf(char **stringp, const char *format, va_list args)
1757#else
1758vasprintf(stringp, format, args)
1759 char **stringp;
1760 const char *format;
1761 va_list args;
1762#endif
1763{
1764 struct DATA data;
1765 char *string;
1766 int r;
1767
1768 string = (char *)xmalloc(ASBUFSIZE);
1769 init_data (&data, string, ASBUFSIZE, format, PFM_AS);
1770 r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args);
1771 *stringp = data.base; /* not string in case reallocated */
1772 return r;
1773}
1774
1775int
1776#if defined(PREFER_STDARG)
1777asprintf(char **stringp, const char * format, ...)
1778#else
1779asprintf(stringp, format, va_alist)
1780 char **stringp;
1781 const char *format;
1782 va_dcl
1783#endif
1784{
1785 int rval;
1786 va_list args;
1787
7117c2d2 1788 SH_VA_START(args, format);
f73dda09
JA
1789
1790 rval = vasprintf (stringp, format, args);
1791
1792 va_end(args);
1793
1794 return rval;
1795}
1796
0001803f 1797#endif /* !HAVE_ASPRINTF */
f73dda09 1798
0001803f 1799#endif /* !HAVE_SNPRINTF || !HAVE_ASPRINTF */
f73dda09
JA
1800
1801#ifdef DRIVER
1802
1803static void
1804memory_error_and_abort ()
1805{
1806 write (2, "out of virtual memory\n", 22);
1807 abort ();
1808}
1809
1810static void *
1811xmalloc(bytes)
1812 size_t bytes;
1813{
1814 void *ret;
1815
1816 ret = malloc(bytes);
1817 if (ret == 0)
1818 memory_error_and_abort ();
1819 return ret;
1820}
1821
1822static void *
1823xrealloc (pointer, bytes)
1824 void *pointer;
1825 size_t bytes;
1826{
1827 void *ret;
1828
1829 ret = pointer ? realloc(pointer, bytes) : malloc(bytes);
1830 if (ret == 0)
1831 memory_error_and_abort ();
1832 return ret;
1833}
1834
1835static void
1836xfree(x)
1837 void *x;
1838{
1839 if (x)
1840 free (x);
1841}
1842
f73dda09
JA
1843/* set of small tests for snprintf() */
1844main()
1845{
1846 char holder[100];
1847 char *h;
1848 int i, si, ai;
1849
7117c2d2
JA
1850#ifdef HAVE_LOCALE_H
1851 setlocale(LC_ALL, "");
1852#endif
1853
1854#if 1
1855 si = snprintf((char *)NULL, 0, "abcde\n");
1856 printf("snprintf returns %d with NULL first argument and size of 0\n", si);
1857 si = snprintf(holder, 0, "abcde\n");
1858 printf("snprintf returns %d with non-NULL first argument and size of 0\n", si);
1859 si = snprintf((char *)NULL, 16, "abcde\n");
1860 printf("snprintf returns %d with NULL first argument and non-zero size\n", si);
1861
f73dda09
JA
1862/*
1863 printf("Suite of test for snprintf:\n");
1864 printf("a_format\n");
1865 printf("printf() format\n");
1866 printf("snprintf() format\n\n");
1867*/
1868/* Checking the field widths */
1869
1870 printf("/%%ld %%ld/, 336, 336\n");
1871 snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336);
1872 asprintf(&h, "/%ld %ld/\n", 336, 336);
1873 printf("/%ld %ld/\n", 336, 336);
1874 printf("%s", holder);
1875 printf("%s\n", h);
1876
1877 printf("/%%d/, 336\n");
1878 snprintf(holder, sizeof holder, "/%d/\n", 336);
1879 asprintf(&h, "/%d/\n", 336);
1880 printf("/%d/\n", 336);
1881 printf("%s", holder);
1882 printf("%s\n", h);
1883
1884 printf("/%%2d/, 336\n");
1885 snprintf(holder, sizeof holder, "/%2d/\n", 336);
1886 asprintf(&h, "/%2d/\n", 336);
1887 printf("/%2d/\n", 336);
1888 printf("%s", holder);
1889 printf("%s\n", h);
1890
1891 printf("/%%10d/, 336\n");
1892 snprintf(holder, sizeof holder, "/%10d/\n", 336);
1893 asprintf(&h, "/%10d/\n", 336);
1894 printf("/%10d/\n", 336);
1895 printf("%s", holder);
1896 printf("%s\n", h);
1897
1898 printf("/%%-10d/, 336\n");
1899 snprintf(holder, sizeof holder, "/%-10d/\n", 336);
1900 asprintf(&h, "/%-10d/\n", 336);
1901 printf("/%-10d/\n", 336);
1902 printf("%s", holder);
1903 printf("%s\n", h);
1904
1905
1906/* floating points */
1907
1908 printf("/%%f/, 1234.56\n");
1909 snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
1910 asprintf(&h, "/%f/\n", 1234.56);
1911 printf("/%f/\n", 1234.56);
1912 printf("%s", holder);
1913 printf("%s\n", h);
1914
1915 printf("/%%e/, 1234.56\n");
1916 snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
1917 asprintf(&h, "/%e/\n", 1234.56);
1918 printf("/%e/\n", 1234.56);
1919 printf("%s", holder);
1920 printf("%s\n", h);
1921
1922 printf("/%%4.2f/, 1234.56\n");
1923 snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
1924 asprintf(&h, "/%4.2f/\n", 1234.56);
1925 printf("/%4.2f/\n", 1234.56);
1926 printf("%s", holder);
1927 printf("%s\n", h);
1928
1929 printf("/%%3.1f/, 1234.56\n");
1930 snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
1931 asprintf(&h, "/%3.1f/\n", 1234.56);
1932 printf("/%3.1f/\n", 1234.56);
1933 printf("%s", holder);
1934 printf("%s\n", h);
1935
1936 printf("/%%10.3f/, 1234.56\n");
1937 snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
1938 asprintf(&h, "/%10.3f/\n", 1234.56);
1939 printf("/%10.3f/\n", 1234.56);
1940 printf("%s", holder);
1941 printf("%s\n", h);
1942
1943 printf("/%%10.3e/, 1234.56\n");
1944 snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
1945 asprintf(&h, "/%10.3e/\n", 1234.56);
1946 printf("/%10.3e/\n", 1234.56);
1947 printf("%s", holder);
1948 printf("%s\n", h);
1949
1950 printf("/%%+4.2f/, 1234.56\n");
1951 snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
1952 asprintf(&h, "/%+4.2f/\n", 1234.56);
1953 printf("/%+4.2f/\n", 1234.56);
1954 printf("%s", holder);
1955 printf("%s\n", h);
1956
1957 printf("/%%010.2f/, 1234.56\n");
1958 snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
1959 asprintf(&h, "/%010.2f/\n", 1234.56);
1960 printf("/%010.2f/\n", 1234.56);
1961 printf("%s", holder);
1962 printf("%s\n", h);
1963
1964#define BLURB "Outstanding acting !"
1965/* strings precisions */
1966
1967 printf("/%%2s/, \"%s\"\n", BLURB);
1968 snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
1969 asprintf(&h, "/%2s/\n", BLURB);
1970 printf("/%2s/\n", BLURB);
1971 printf("%s", holder);
1972 printf("%s\n", h);
1973
1974 printf("/%%22s/ %s\n", BLURB);
1975 snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
1976 asprintf(&h, "/%22s/\n", BLURB);
1977 printf("/%22s/\n", BLURB);
1978 printf("%s", holder);
1979 printf("%s\n", h);
1980
1981 printf("/%%22.5s/ %s\n", BLURB);
1982 snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
1983 asprintf(&h, "/%22.5s/\n", BLURB);
1984 printf("/%22.5s/\n", BLURB);
1985 printf("%s", holder);
1986 printf("%s\n", h);
1987
1988 printf("/%%-22.5s/ %s\n", BLURB);
1989 snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
1990 asprintf(&h, "/%-22.5s/\n", BLURB);
1991 printf("/%-22.5s/\n", BLURB);
1992 printf("%s", holder);
1993 printf("%s\n", h);
1994
1995/* see some flags */
1996
1997 printf("%%x %%X %%#x, 31, 31, 31\n");
1998 snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
1999 asprintf(&h, "%x %X %#x\n", 31, 31, 31);
2000 printf("%x %X %#x\n", 31, 31, 31);
2001 printf("%s", holder);
2002 printf("%s\n", h);
2003
2004 printf("**%%d**%% d**%% d**, 42, 42, -42\n");
2005 snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
2006 asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42);
2007 printf("**%d**% d**% d**\n", 42, 42, -42);
2008 printf("%s", holder);
2009 printf("%s\n", h);
2010
2011/* other flags */
2012
2013 printf("/%%g/, 31.4\n");
2014 snprintf(holder, sizeof holder, "/%g/\n", 31.4);
2015 asprintf(&h, "/%g/\n", 31.4);
2016 printf("/%g/\n", 31.4);
2017 printf("%s", holder);
2018 printf("%s\n", h);
2019
2020 printf("/%%.6g/, 31.4\n");
2021 snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
2022 asprintf(&h, "/%.6g/\n", 31.4);
2023 printf("/%.6g/\n", 31.4);
2024 printf("%s", holder);
2025 printf("%s\n", h);
2026
2027 printf("/%%.1G/, 31.4\n");
2028 snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
2029 asprintf(&h, "/%.1G/\n", 31.4);
2030 printf("/%.1G/\n", 31.4);
2031 printf("%s", holder);
2032 printf("%s\n", h);
2033
2034 printf("/%%.1G/, 3100000000.4\n");
2035 snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);
2036 asprintf(&h, "/%.1G/\n", 3100000000.4);
2037 printf("/%.1G/\n", 3100000000.4);
2038 printf("%s", holder);
2039 printf("%s\n", h);
2040
2041 printf("abc%%n\n");
2042 printf("abc%n", &i); printf("%d\n", i);
2043 snprintf(holder, sizeof holder, "abc%n", &i);
2044 printf("%s", holder); printf("%d\n\n", i);
2045 asprintf(&h, "abc%n", &i);
2046 printf("%s", h); printf("%d\n\n", i);
2047
2048 printf("%%*.*s --> 10.10\n");
2049 snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
2050 asprintf(&h, "%*.*s\n", 10, 10, BLURB);
2051 printf("%*.*s\n", 10, 10, BLURB);
2052 printf("%s", holder);
2053 printf("%s\n", h);
2054
2055 printf("%%%%%%%%\n");
2056 snprintf(holder, sizeof holder, "%%%%\n");
2057 asprintf(&h, "%%%%\n");
2058 printf("%%%%\n");
2059 printf("%s", holder);
2060 printf("%s\n", h);
2061
2062#define BIG "Hello this is a too big string for the buffer"
2063/* printf("A buffer to small of 10, trying to put this:\n");*/
2064 printf("<%%>, %s\n", BIG);
2065 i = snprintf(holder, 10, "%s\n", BIG);
2066 i = asprintf(&h, "%s", BIG);
2067 printf("<%s>\n", BIG);
2068 printf("<%s>\n", holder);
2069 printf("<%s>\n\n", h);
2070
2071 printf ("<%%p> vsnprintf\n");
2072 i = snprintf(holder, 100, "%p", vsnprintf);
2073 i = asprintf(&h, "%p", vsnprintf);
2074 printf("<%p>\n", vsnprintf);
2075 printf("<%s>\n", holder);
2076 printf("<%s>\n\n", h);
2077
2078 printf ("<%%lu> LONG_MAX+1\n");
2079 i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1);
2080 i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1);
2081 printf("<%lu>\n", (unsigned long)(LONG_MAX)+1);
2082 printf("<%s>\n", holder);
2083 printf("<%s>\n\n", h);
2084
74091dd4 2085#ifdef HAVE_LONG_LONG_INT
f73dda09
JA
2086 printf ("<%%llu> LLONG_MAX+1\n");
2087 i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1);
2088 i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1);
2089 printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1);
2090 printf("<%s>\n", holder);
2091 printf("<%s>\n\n", h);
2092#endif
2093
2094#ifdef HAVE_LONG_DOUBLE
2095 printf ("<%%6.2LE> 42.42\n");
2096 i = snprintf(holder, 100, "%6.2LE", (long double)42.42);
2097 i = asprintf(&h, "%6.2LE", (long double)42.42);
2098 printf ("<%6.2LE>\n", (long double)42.42);
2099 printf ("<%s>\n", holder);
2100 printf ("<%s>\n\n", h);
2101#endif
2102
2103#ifdef HAVE_PRINTF_A_FORMAT
2104 printf ("<%%6.2A> 42.42\n");
2105 i = snprintf(holder, 100, "%6.2A", 42.42);
2106 i = asprintf(&h, "%6.2A", 42.42);
2107 printf ("<%6.2A>\n", 42.42);
2108 printf ("<%s>\n", holder);
2109 printf ("<%s>\n\n", h);
2110
2111 printf ("<%%6.2LA> 42.42\n");
2112 i = snprintf(holder, 100, "%6.2LA", (long double)42.42);
2113 i = asprintf(&h, "%6.2LA", (long double)42.42);
2114 printf ("<%6.2LA>\n", (long double)42.42);
2115 printf ("<%s>\n", holder);
2116 printf ("<%s>\n\n", h);
2117#endif
2118
2119 printf ("<%%.10240f> DBL_MAX\n");
2120 si = snprintf(holder, 100, "%.10240f", DBL_MAX);
2121 ai = asprintf(&h, "%.10240f", DBL_MAX);
2122 printf ("<%.10240f>\n", DBL_MAX);
2123 printf ("<%d> <%s>\n", si, holder);
2124 printf ("<%d> <%s>\n\n", ai, h);
2125
2126 printf ("<%%.10240Lf> LDBL_MAX\n");
2127 si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX);
2128 ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX);
2129 printf ("<%.10240Lf>\n", (long double)LDBL_MAX);
2130 printf ("<%d> <%s>\n", si, holder);
2131 printf ("<%d> <%s>\n\n", ai, h);
2132
7117c2d2
JA
2133 /* huh? */
2134 printf("/%%g/, 421.2345\n");
2135 snprintf(holder, sizeof holder, "/%g/\n", 421.2345);
2136 asprintf(&h, "/%g/\n", 421.2345);
2137 printf("/%g/\n", 421.2345);
2138 printf("%s", holder);
2139 printf("%s\n", h);
2140
2141 printf("/%%g/, 4214.2345\n");
2142 snprintf(holder, sizeof holder, "/%g/\n", 4214.2345);
2143 asprintf(&h, "/%g/\n", 4214.2345);
2144 printf("/%g/\n", 4214.2345);
2145 printf("%s", holder);
2146 printf("%s\n", h);
2147
2148 printf("/%%.5g/, 4214.2345\n");
2149 snprintf(holder, sizeof holder, "/%.5g/\n", 4214.2345);
2150 asprintf(&h, "/%.5g/\n", 4214.2345);
2151 printf("/%.5g/\n", 4214.2345);
2152 printf("%s", holder);
2153 printf("%s\n", h);
2154
2155 printf("/%%.4g/, 4214.2345\n");
2156 snprintf(holder, sizeof holder, "/%.4g/\n", 4214.2345);
2157 asprintf(&h, "/%.4g/\n", 4214.2345);
2158 printf("/%.4g/\n", 4214.2345);
2159 printf("%s", holder);
2160 printf("%s\n", h);
2161
2162 printf("/%%'ld %%'ld/, 12345, 1234567\n");
2163 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 12345, 1234567);
2164 asprintf(&h, "/%'ld %'ld/\n", 12345, 1234567);
2165 printf("/%'ld %'ld/\n", 12345, 1234567);
2166 printf("%s", holder);
2167 printf("%s\n", h);
2168
2169 printf("/%%'ld %%'ld/, 336, 3336\n");
2170 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 336, 3336);
2171 asprintf(&h, "/%'ld %'ld/\n", 336, 3336);
2172 printf("/%'ld %'ld/\n", 336, 3336);
2173 printf("%s", holder);
2174 printf("%s\n", h);
2175
2176 printf("/%%'ld %%'ld/, -42786, -142786\n");
2177 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", -42786, -142786);
2178 asprintf(&h, "/%'ld %'ld/\n", -42786, -142786);
2179 printf("/%'ld %'ld/\n", -42786, -142786);
2180 printf("%s", holder);
2181 printf("%s\n", h);
2182
2183 printf("/%%'f %%'f/, 421.2345, 421234.56789\n");
2184 snprintf(holder, sizeof holder, "/%'f %'f/\n", 421.2345, 421234.56789);
2185 asprintf(&h, "/%'f %'f/\n", 421.2345, 421234.56789);
2186 printf("/%'f %'f/\n", 421.2345, 421234.56789);
2187 printf("%s", holder);
2188 printf("%s\n", h);
2189
2190 printf("/%%'f %%'f/, -421.2345, -421234.56789\n");
2191 snprintf(holder, sizeof holder, "/%'f %'f/\n", -421.2345, -421234.56789);
2192 asprintf(&h, "/%'f %'f/\n", -421.2345, -421234.56789);
2193 printf("/%'f %'f/\n", -421.2345, -421234.56789);
2194 printf("%s", holder);
2195 printf("%s\n", h);
2196
2197 printf("/%%'g %%'g/, 421.2345, 421234.56789\n");
2198 snprintf(holder, sizeof holder, "/%'g %'g/\n", 421.2345, 421234.56789);
2199 asprintf(&h, "/%'g %'g/\n", 421.2345, 421234.56789);
2200 printf("/%'g %'g/\n", 421.2345, 421234.56789);
2201 printf("%s", holder);
2202 printf("%s\n", h);
2203
2204 printf("/%%'g %%'g/, -421.2345, -421234.56789\n");
2205 snprintf(holder, sizeof holder, "/%'g %'g/\n", -421.2345, -421234.56789);
2206 asprintf(&h, "/%'g %'g/\n", -421.2345, -421234.56789);
2207 printf("/%'g %'g/\n", -421.2345, -421234.56789);
2208 printf("%s", holder);
2209 printf("%s\n", h);
2210#endif
2211
2212 printf("/%%'g/, 4213455.8392\n");
2213 snprintf(holder, sizeof holder, "/%'g/\n", 4213455.8392);
2214 asprintf(&h, "/%'g/\n", 4213455.8392);
2215 printf("/%'g/\n", 4213455.8392);
2216 printf("%s", holder);
2217 printf("%s\n", h);
2218
f73dda09
JA
2219 exit (0);
2220}
2221#endif