]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/sh/snprintf.c
Imported from ../bash-2.05a.tar.gz.
[thirdparty/bash.git] / lib / sh / snprintf.c
CommitLineData
f73dda09
JA
1/*
2 build a test version with
3 gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o
4*/
5
6/*
7 Unix snprintf implementation.
8 derived from inetutils/libinetutils/snprintf.c Version 1.1
9
10 Copyright (C) 2001 Free Software Foundation, Inc.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General License for more details.
21
22 You should have received a copy of the GNU General License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 Revision History:
27
28 1.1:
29 * added changes from Miles Bader
30 * corrected a bug with %f
31 * added support for %#g
32 * added more comments :-)
33 1.0:
34 * supporting must ANSI syntaxic_sugars
35 0.0:
36 * support %s %c %d
37
38 THANKS(for the patches and ideas):
39 Miles Bader
40 Cyrille Rustom
41 Jacek Slabocewiz
42 Mike Parker(mouse)
43
44*/
45
46/*
47 * Currently doesn't handle (and bash/readline doesn't use):
48 * *M$ width, precision specifications
49 * %N$ numbered argument conversions
50 * inf, nan floating values (could use isinf(), isnan())
51 * `,', `'' flags
52 * `C', `S' conversions
53 * support for `F' is imperfect, since underlying printf may not handle it
54 */
55
56#define FLOATING_POINT
57
58#ifdef HAVE_CONFIG_H
59# include <config.h>
60#endif
61
62#if defined(DRIVER) && !defined(HAVE_CONFIG_H)
63#define HAVE_LONG_LONG
64#define HAVE_LONG_DOUBLE
65#ifdef __linux__
66#define HAVE_PRINTF_A_FORMAT
67#endif
68#define PREFER_STDARG
69#define HAVE_STRINGIZE
70#define HAVE_LIMITS_H
71#define HAVE_STDDEF_H
72#define intmax_t long
73#endif
74
75#if !defined (HAVE_SNPRINTF) || !defined (HAVE_ASPRINTF)
76
77#include <bashtypes.h>
78
79#if defined(PREFER_STDARG)
80# include <stdarg.h>
81#else
82# include <varargs.h>
83#endif
84
85#ifdef HAVE_LIMITS_H
86# include <limits.h>
87#endif
88#include <bashansi.h>
89#ifdef HAVE_STDDEF_H
90# include <stddef.h>
91#endif
92#include <chartypes.h>
93
94#ifdef HAVE_STDINT_H
95# include <stdint.h>
96#endif
97
98#ifdef FLOATING_POINT
99# include <stdio.h> /* for sprintf */
100#endif
101
102#include <typemax.h>
103
104#include "stdc.h"
105
106#ifndef DRIVER
107# include "shell.h"
108#else
109# define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
110# define FL_ADDBASE 0x02 /* add base# prefix to converted value */
111# define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
112# define FL_UNSIGNED 0x08 /* don't add any sign */
113extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
114extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
115#endif
116
117/* Bound on length of the string representing an integer value of type T.
118 Subtract one for the sign bit if T is signed;
119 302 / 1000 is log10 (2) rounded up;
120 add one for integer division truncation;
121 add one more for a minus sign if t is signed. */
122#define INT_STRLEN_BOUND(t) \
123 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
124 + 1 + TYPE_SIGNED (t))
125
126/* conversion flags */
127#define PF_ALTFORM 0x00001 /* # */
128#define PF_HEXPREFIX 0x00002 /* 0[Xx] */
129#define PF_LADJUST 0x00004 /* - */
130#define PF_ZEROPAD 0x00008 /* 0 */
131#define PF_PLUS 0x00010 /* + */
132#define PF_SPACE 0x00020 /* ' ' */
133#define PF_COMMA 0x00040 /* , */
134
135#define PF_DOT 0x00080 /* `.precision' */
136#define PF_STAR_P 0x00100 /* `*' after precision */
137#define PF_STAR_W 0x00200 /* `*' before or without precision */
138
139/* length modifiers */
140#define PF_SIGNEDCHAR 0x00400 /* hh */
141#define PF_SHORTINT 0x00800 /* h */
142#define PF_LONGINT 0x01000 /* l */
143#define PF_LONGLONG 0x02000 /* ll */
144#define PF_LONGDBL 0x04000 /* L */
145#define PF_INTMAX_T 0x08000 /* j */
146#define PF_SIZE_T 0x10000 /* z */
147#define PF_PTRDIFF_T 0x20000 /* t */
148
149#define PF_ALLOCBUF 0x40000 /* for asprintf, vasprintf */
150
151#define PFM_SN 0x01 /* snprintf, vsnprintf */
152#define PFM_AS 0x02 /* asprintf, vasprintf */
153
154#define ASBUFSIZE 128
155
156#define x_digs "0123456789abcdef"
157#define X_digs "0123456789ABCDEF"
158
159static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
160
161/*
162 * For the FLOATING POINT FORMAT :
163 * the challenge was finding a way to
164 * manipulate the Real numbers without having
165 * to resort to mathematical function(it
166 * would require to link with -lm) and not
167 * going down to the bit pattern(not portable)
168 *
169 * so a number, a real is:
170
171 real = integral + fraction
172
173 integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
174 fraction = b(1)*10^-1 + b(2)*10^-2 + ...
175
176 where:
177 0 <= a(i) => 9
178 0 <= b(i) => 9
179
180 from then it was simple math
181 */
182
183/*
184 * size of the buffer for the integral part
185 * and the fraction part
186 */
187#define MAX_INT 99 + 1 /* 1 for the null */
188#define MAX_FRACT 307 + 1
189
190/*
191 * These functions use static buffers to store the results,
192 * and so are not reentrant
193 */
194#define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
195#define dtoa(n, p, f) numtoa(n, 10, p, f)
196
197#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
198
199/* Macros that do proper sign extension and handle length modifiers. Used
200 for the integer conversion specifiers. */
201#define GETSIGNED(p) \
202 (((p)->flags & PF_LONGINT) \
203 ? va_arg(args, long) \
204 : (((p)->flags & PF_SHORTINT) ? (long)(short)va_arg(args, int) \
205 : (long)va_arg(args, int)))
206
207#define GETUNSIGNED(p) \
208 (((p)->flags & PF_LONGINT) \
209 ? va_arg(args, unsigned long) \
210 : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)va_arg(args, int) \
211 : (unsigned long)va_arg(args, unsigned int)))
212
213
214#ifdef HAVE_LONG_DOUBLE
215#define GETLDOUBLE(p) va_arg(args, long double)
216#endif
217#define GETDOUBLE(p) va_arg(args, double)
218
219#define SET_SIZE_FLAGS(p, type) \
220 if (sizeof (type) > sizeof (int)) \
221 (p)->flags |= PF_LONGINT; \
222 if (sizeof (type) > sizeof (long)) \
223 (p)->flags |= PF_LONGLONG;
224
225/* this struct holds everything we need */
226struct DATA
227{
228 int length;
229 char *base; /* needed for [v]asprintf */
230 char *holder;
231 int counter;
232 const char *pf;
233
234/* FLAGS */
235 int flags;
236 int justify;
237 int width, precision;
238 char pad;
239};
240
241/* the floating point stuff */
242#ifdef FLOATING_POINT
243static double pow_10 __P((int));
244static int log_10 __P((double));
245static double integral __P((double, double *));
246static char *numtoa __P((double, int, int, char **));
247#endif
248
249static void init_data __P((struct DATA *, char *, size_t, const char *, int));
250static void init_conv_flag __P((struct DATA *));
251
252/* for the format */
253#ifdef FLOATING_POINT
254static void floating __P((struct DATA *, double));
255static void exponent __P((struct DATA *, double));
256#endif
257static void number __P((struct DATA *, unsigned long, int));
258#ifdef HAVE_LONG_LONG
259static void lnumber __P((struct DATA *, unsigned long long, int));
260#endif
261static void pointer __P((struct DATA *, unsigned long));
262static void strings __P((struct DATA *, char *));
263
264#ifdef FLOATING_POINT
265# define FALLBACK_FMTSIZE 32
266# define FALLBACK_BASE 4096
267# define LFALLBACK_BASE 5120
268# ifdef HAVE_LONG_DOUBLE
269static void ldfallback __P((struct DATA *, const char *, const char *, long double));
270# endif
271static void dfallback __P((struct DATA *, const char *, const char *, double));
272#endif
273
274#ifdef DRIVER
275static void memory_error_and_abort ();
276static void *xmalloc __P((size_t));
277static void *xrealloc __P((void *, size_t));
278static void xfree __P((void *));
279#else
280# include <xmalloc.h>
281#endif
282
283/* those are defines specific to snprintf to hopefully
284 * make the code clearer :-)
285 */
286#define RIGHT 1
287#define LEFT 0
288#define NOT_FOUND -1
289#define FOUND 1
290#define MAX_FIELD 15
291
292/* round off to the precision */
293#define ROUND(d, p) \
294 (d < 0.) ? \
295 d - pow_10(-(p)->precision) * 0.5 : \
296 d + pow_10(-(p)->precision) * 0.5
297
298/* set default precision */
299#define DEF_PREC(p) \
300 if ((p)->precision == NOT_FOUND) \
301 (p)->precision = 6
302
303/* put a char. increment the number of chars written even if we've exceeded
304 the vsnprintf/snprintf buffer size (for the return value) */
305#define PUT_CHAR(c, p) \
306 do \
307 { \
308 if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \
309 { \
310 (p)->length += ASBUFSIZE; \
311 (p)->base = (char *)xrealloc((p)->base, (p)->length); \
312 (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \
313 } \
314 if ((p)->counter < (p)->length) \
315 *(p)->holder++ = (c); \
316 (p)->counter++; \
317 } \
318 while (0)
319
320#define PUT_PLUS(d, p, zero) \
321 if ((d) > zero && (p)->justify == RIGHT) \
322 PUT_CHAR('+', p)
323
324#define PUT_SPACE(d, p, zero) \
325 if (((p)->flags & PF_SPACE) && (d) > zero) \
326 PUT_CHAR(' ', p)
327
328/* pad right */
329#define PAD_RIGHT(p) \
330 if ((p)->width > 0 && (p)->justify != LEFT) \
331 for (; (p)->width > 0; (p)->width--) \
332 PUT_CHAR((p)->pad, p)
333
334/* pad left */
335#define PAD_LEFT(p) \
336 if ((p)->width > 0 && (p)->justify == LEFT) \
337 for (; (p)->width > 0; (p)->width--) \
338 PUT_CHAR((p)->pad, p)
339
340/* if width and prec. in the args */
341#define STAR_ARGS(p) \
342 if ((p)->flags & PF_STAR_W) \
343 (p)->width = va_arg(args, int); \
344 if ((p)->flags & PF_STAR_P) \
345 (p)->precision = va_arg(args, int)
346
347#ifdef FLOATING_POINT
348/*
349 * Find the nth power of 10
350 */
351static double
352pow_10(n)
353 int n;
354{
355 double P;
356
357 /* handle common cases with fast switch statement. */
358 switch (n)
359 {
360 case -3: return .001;
361 case -2: return .01;
362 case -1: return .1;
363 case 0: return 1.;
364 case 1: return 10.;
365 case 2: return 100.;
366 case 3: return 1000.;
367 }
368
369 if (n < 0)
370 {
371 P = .0001;
372 for (n += 4; n < 0; n++)
373 P /= 10.;
374 }
375 else
376 {
377 P = 10000.;
378 for (n -= 4; n > 0; n--)
379 P *= 10.;
380 }
381
382 return P;
383}
384
385/*
386 * Find the integral part of the log in base 10
387 * Note: this not a real log10()
388 I just need and approximation(integerpart) of x in:
389 10^x ~= r
390 * log_10(200) = 2;
391 * log_10(250) = 2;
392 */
393static int
394log_10(r)
395 double r;
396{
397 int i = 0;
398 double result = 1.;
399
400 if (r < 0.)
401 r = -r;
402
403 if (r < 1.)
404 {
405 while (result >= r)
406 {
407 result /= 10.;
408 i++;
409 }
410 return (-i);
411 }
412 else
413 {
414 while (result <= r)
415 {
416 result *= 10.;
417 i++;
418 }
419 return (i - 1);
420 }
421}
422
423/*
424 * This function return the fraction part of a double
425 * and set in ip the integral part.
426 * In many ways it resemble the modf() found on most Un*x
427 */
428static double
429integral(real, ip)
430 double real;
431 double *ip;
432{
433 int j;
434 double i, s, p;
435 double real_integral = 0.;
436
437 /* take care of the obvious */
438 /* equal to zero ? */
439 if (real == 0.)
440 {
441 *ip = 0.;
442 return (0.);
443 }
444
445 /* negative number ? */
446 if (real < 0.)
447 real = -real;
448
449 /* a fraction ? */
450 if ( real < 1.)
451 {
452 *ip = 0.;
453 return real;
454 }
455
456 /* the real work :-) */
457 for (j = log_10(real); j >= 0; j--)
458 {
459 p = pow_10(j);
460 s = (real - real_integral)/p;
461 i = 0.;
462 while (i + 1. <= s)
463 i++;
464 real_integral += i*p;
465 }
466 *ip = real_integral;
467 return (real - real_integral);
468}
469
470#define PRECISION 1.e-6
471/*
472 * return an ascii representation of the integral part of the number
473 * and set fract to be an ascii representation of the fraction part
474 * the container for the fraction and the integral part or staticly
475 * declare with fix size
476 */
477static char *
478numtoa(number, base, precision, fract)
479 double number;
480 int base, precision;
481 char **fract;
482{
483 register int i, j;
484 double ip, fp; /* integer and fraction part */
485 double fraction;
486 int digits = MAX_INT - 1;
487 static char integral_part[MAX_INT];
488 static char fraction_part[MAX_FRACT];
489 double sign;
490 int ch;
491
492 /* taking care of the obvious case: 0.0 */
493 if (number == 0.)
494 {
495 integral_part[0] = '0';
496 integral_part[1] = '\0';
497 fraction_part[0] = '0';
498 fraction_part[1] = '\0';
499 return integral_part;
500 }
501
502 /* for negative numbers */
503 if ((sign = number) < 0.)
504 {
505 number = -number;
506 digits--; /* sign consume one digit */
507 }
508
509 fraction = integral(number, &ip);
510 number = ip;
511
512 /* do the integral part */
513 if (ip == 0.)
514 {
515 integral_part[0] = '0';
516 i = 1;
517 }
518 else
519 {
520 for ( i = 0; i < digits && number != 0.; ++i)
521 {
522 number /= base;
523 fp = integral(number, &ip);
524 ch = (int)((fp + PRECISION)*base); /* force to round */
525 integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
526 if (! ISXDIGIT((unsigned char)integral_part[i]))
527 break; /* bail out overflow !! */
528 number = ip;
529 }
530 }
531
532 /* Oh No !! out of bound, ho well fill it up ! */
533 if (number != 0.)
534 for (i = 0; i < digits; ++i)
535 integral_part[i] = '9';
536
537 /* put the sign ? */
538 if (sign < 0.)
539 integral_part[i++] = '-';
540
541 integral_part[i] = '\0';
542
543 /* reverse every thing */
544 for ( i--, j = 0; j < i; j++, i--)
545 SWAP_INT(integral_part[i], integral_part[j]);
546
547 /* the fractional part */
548 for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--)
549 {
550 fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
551 if (! DIGIT(fraction_part[i])) /* underflow ? */
552 break;
553 fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
554 }
555 fraction_part[i] = '\0';
556
557 if (fract != (char **)0)
558 *fract = fraction_part;
559
560 return integral_part;
561}
562#endif
563
564/* for %d and friends, it puts in holder
565 * the representation with the right padding
566 */
567static void
568number(p, d, base)
569 struct DATA *p;
570 unsigned long d;
571 int base;
572{
573 char *tmp;
574 long sd;
575 int flags;
576
577 sd = d; /* signed for ' ' padding in base 10 */
578 flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
579 if (*p->pf == 'X')
580 flags |= FL_HEXUPPER;
581
582 tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
583 p->width -= strlen(tmp);
584 PAD_RIGHT(p);
585
586 switch (base)
587 {
588 case 10:
589 PUT_PLUS(sd, p, 0);
590 PUT_SPACE(sd, p, 0);
591 break;
592 case 8:
593 if (p->flags & PF_ALTFORM)
594 PUT_CHAR('0', p);
595 break;
596 case 16:
597 if (p->flags & PF_ALTFORM)
598 {
599 PUT_CHAR('0', p);
600 PUT_CHAR(*p->pf, p);
601 }
602 break;
603 }
604
605 while (*tmp)
606 {
607 PUT_CHAR(*tmp, p);
608 tmp++;
609 }
610
611 PAD_LEFT(p);
612}
613
614#ifdef HAVE_LONG_LONG
615/*
616 * identical to number() but works for `long long'
617 */
618static void
619lnumber(p, d, base)
620 struct DATA *p;
621 unsigned long long d;
622 int base;
623{
624 char *tmp;
625 long long sd;
626 int flags;
627
628 sd = d; /* signed for ' ' padding in base 10 */
629 flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
630 if (*p->pf == 'X')
631 flags |= FL_HEXUPPER;
632
633 tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
634 p->width -= strlen(tmp);
635 PAD_RIGHT(p);
636
637 switch (base)
638 {
639 case 10:
640 PUT_PLUS(sd, p, 0);
641 PUT_SPACE(sd, p, 0);
642 break;
643 case 8:
644 if (p->flags & PF_ALTFORM)
645 PUT_CHAR('0', p);
646 break;
647 case 16:
648 if (p->flags & PF_ALTFORM)
649 {
650 PUT_CHAR('0', p);
651 PUT_CHAR(*p->pf, p);
652 }
653 break;
654 }
655
656 while (*tmp)
657 {
658 PUT_CHAR(*tmp, p);
659 tmp++;
660 }
661
662 PAD_LEFT(p);
663}
664#endif
665
666static void
667pointer(p, d)
668 struct DATA *p;
669 unsigned long d;
670{
671 char *tmp;
672
673 tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0);
674 p->width -= strlen(tmp);
675 PAD_RIGHT(p);
676
677 /* prefix '0x' for pointers */
678 PUT_CHAR('0', p);
679 PUT_CHAR('x', p);
680
681 while (*tmp)
682 {
683 PUT_CHAR(*tmp, p);
684 tmp++;
685 }
686 PAD_LEFT(p);
687}
688
689/* %s strings */
690static void
691strings(p, tmp)
692 struct DATA *p;
693 char *tmp;
694{
695 int i;
696
697 i = strlen(tmp);
698 if (p->precision != NOT_FOUND) /* the smallest number */
699 i = (i < p->precision ? i : p->precision);
700 p->width -= i;
701 PAD_RIGHT(p);
702 while (i-- > 0)
703 { /* put the sting */
704 PUT_CHAR(*tmp, p);
705 tmp++;
706 }
707 PAD_LEFT(p);
708}
709
710#ifdef FLOATING_POINT
711/* %f %F %g %G floating point representation */
712static void
713floating(p, d)
714 struct DATA *p;
715 double d;
716{
717 char *tmp, *tmp2;
718 int i;
719
720 DEF_PREC(p);
721 d = ROUND(d, p);
722 tmp = dtoa(d, p->precision, &tmp2);
723 /* calculate the padding. 1 for the dot */
724 p->width = p->width -
725 ((d > 0. && p->justify == RIGHT) ? 1:0) -
726 ((p->flags & PF_SPACE) ? 1:0) -
727 strlen(tmp) - p->precision - 1;
728 PAD_RIGHT(p);
729 PUT_PLUS(d, p, 0.);
730 PUT_SPACE(d, p, 0.);
731 while (*tmp)
732 { /* the integral */
733 PUT_CHAR(*tmp, p);
734 tmp++;
735 }
736 if (p->precision != 0 || (p->flags & PF_ALTFORM))
737 PUT_CHAR('.', p); /* put the '.' */
738 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
739 /* smash the trailing zeros unless altform */
740 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
741 tmp2[i] = '\0';
742 for (; *tmp2; tmp2++)
743 PUT_CHAR(*tmp2, p); /* the fraction */
744
745 PAD_LEFT(p);
746}
747
748/* %e %E %g %G exponent representation */
749static void
750exponent(p, d)
751 struct DATA *p;
752 double d;
753{
754 char *tmp, *tmp2;
755 int j, i, nsig, ndig;
756
757 DEF_PREC(p);
758 j = log_10(d);
759 d = d / pow_10(j); /* get the Mantissa */
760 d = ROUND(d, p);
761 tmp = dtoa(d, p->precision, &tmp2);
762 /* 1 for unit, 1 for the '.', 1 for 'e|E',
763 * 1 for '+|-', 2 for 'exp' */
764 /* calculate how much padding need */
765 p->width = p->width -
766 ((d > 0. && p->justify == RIGHT) ? 1:0) -
767 ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
768 PAD_RIGHT(p);
769 PUT_PLUS(d, p, 0.);
770 PUT_SPACE(d, p, 0.);
771 /*
772 * When supplied %g or %G, an optional precision is the number of
773 * significant digits to print.
774 *
775 * nsig = number of significant digits we've printed (leading zeros are
776 * never significant)
777 * ndig = if non-zero, max number of significant digits to print (only
778 * applicable to %g/%G)
779 */
780 nsig = ndig = 0;
781 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_DOT))
782 ndig = (p->precision == 0) ? 1 : p->precision;
783
784 while (*tmp)
785 {
786 PUT_CHAR(*tmp, p);
787 tmp++;
788 if (ndig && (++nsig >= ndig))
789 break;
790 }
791
792 if ((p->precision != 0 || (p->flags & PF_ALTFORM)) && (ndig == 0 || nsig < ndig))
793 PUT_CHAR('.', p); /* the '.' */
794 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
795 /* smash the trailing zeros unless altform */
796 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
797 tmp2[i] = '\0';
798 for (; *tmp2; tmp2++)
799 {
800 if (ndig && (nsig++ >= ndig))
801 break;
802 PUT_CHAR(*tmp2, p); /* the fraction */
803 }
804
805 /* the exponent put the 'e|E' */
806 if (*p->pf == 'g' || *p->pf == 'e')
807 {
808 PUT_CHAR('e', p);
809 }
810 else
811 PUT_CHAR('E', p);
812
813 /* the sign of the exp */
814 if (j > 0)
815 {
816 PUT_CHAR('+', p);
817 }
818 else
819 {
820 PUT_CHAR('-', p);
821 j = -j;
822 }
823
824 tmp = itoa(j);
825 /* pad out to at least two spaces. pad with `0' if the exponent is a
826 single digit. */
827 if (j <= 9)
828 {
829 PUT_CHAR('0', p);
830 }
831
832 /* the exponent */
833 while (*tmp)
834 {
835 PUT_CHAR(*tmp, p);
836 tmp++;
837 }
838 PAD_LEFT(p);
839}
840#endif
841
842/* initialize the conversion specifiers */
843static void
844init_conv_flag (p)
845 struct DATA *p;
846{
847 p->flags &= PF_ALLOCBUF; /* preserve PF_ALLOCBUF flag */
848 p->precision = p->width = NOT_FOUND;
849 p->justify = NOT_FOUND;
850 p->pad = ' ';
851}
852
853static void
854init_data (p, string, length, format, mode)
855 struct DATA *p;
856 char *string;
857 size_t length;
858 const char *format;
859 int mode;
860{
861 p->length = length - 1; /* leave room for '\0' */
862 p->holder = p->base = string;
863 p->pf = format;
864 p->counter = 0;
865 p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0;
866}
867
868static int
869#if defined (__STDC__)
870vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args)
871#else
872vsnprintf_internal(data, string, length, format, args)
873 struct DATA *data;
874 char *string;
875 size_t length;
876 const char *format;
877 va_list args;
878#endif
879{
880 double d; /* temporary holder */
881#ifdef HAVE_LONG_DOUBLE
882 long double ld; /* for later */
883#endif
884 unsigned long ul;
885#ifdef HAVE_LONG_LONG
886 unsigned long long ull;
887#endif
888 int state, i, c, n;
889 char *s;
890 const char *convstart;
891
892 /* Sanity check, the string must be > 1. C99 actually says that LENGTH
893 can be zero here, in the case of snprintf/vsnprintf (it's never 0 in
894 the case of asprintf/vasprintf), and the return value is the number
895 of characters that would have been written. */
896 if (length < 1)
897 return -1;
898
899 if (format == 0)
900 return 0;
901
902 for (; c = *(data->pf); data->pf++)
903 {
904 if (c != '%')
905 {
906 PUT_CHAR (c, data);
907 continue;
908 }
909
910 convstart = data->pf;
911 init_conv_flag (data); /* initialise format flags */
912
913 state = 1;
914 for (state = 1; state && *data->pf; )
915 {
916 c = *(++data->pf);
917 /* fmtend = data->pf */
918#if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
919 if (data->flags & PF_LONGDBL)
920 {
921 switch (c)
922 {
923 case 'f': case 'F':
924 case 'e': case 'E':
925 case 'g': case 'G':
926# ifdef HAVE_PRINTF_A_FORMAT
927 case 'a': case 'A':
928# endif
929 STAR_ARGS (data);
930 ld = GETLDOUBLE (data);
931 ldfallback (data, convstart, data->pf, ld);
932 goto conv_break;
933 }
934 }
935#endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
936
937 switch (c)
938 {
939 /* Parse format flags */
940 case '\0': /* a NULL here ? ? bail out */
941 *data->holder = '\0';
942 return data->counter;
943 break;
944 case '#':
945 data->flags |= PF_ALTFORM;
946 continue;
947 case '0':
948 data->flags |= PF_ZEROPAD;
949 data->pad = '0';
950 continue;
951 case '*':
952 if (data->flags & PF_DOT)
953 data->flags |= PF_STAR_P;
954 else
955 data->flags |= PF_STAR_W;
956 continue;
957 case '-':
958 data->flags |= PF_LADJUST;
959 data->justify = LEFT;
960 continue;
961 case ' ':
962 if ((data->flags & PF_PLUS) == 0)
963 data->flags |= PF_SPACE;
964 continue;
965 case '+':
966 data->flags |= PF_PLUS;
967 data->justify = RIGHT;
968 continue;
969 case ',':
970 data->flags |= PF_COMMA; /* not implemented yet */
971 continue;
972
973 case '1': case '2': case '3':
974 case '4': case '5': case '6':
975 case '7': case '8': case '9':
976 n = 0;
977 do
978 {
979 n = n * 10 + TODIGIT(c);
980 c = *(++data->pf);
981 }
982 while (DIGIT(c));
983 data->pf--; /* went too far */
984 if (n < 0)
985 n = 0;
986 if (data->flags & PF_DOT)
987 data->precision = n;
988 else
989 data->width = n;
990 continue;
991
992 /* optional precision */
993 case '.':
994 data->flags |= PF_DOT;
995 data->precision = 0;
996 continue;
997
998 /* length modifiers */
999 case 'h':
1000 data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT;
1001 continue;
1002 case 'l':
1003 data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT;
1004 continue;
1005 case 'L':
1006 data->flags |= PF_LONGDBL;
1007 continue;
1008 case 'q':
1009 data->flags |= PF_LONGLONG;
1010 continue;
1011 case 'j':
1012 data->flags |= PF_INTMAX_T;
1013 SET_SIZE_FLAGS(data, intmax_t);
1014 continue;
1015 case 'z':
1016 data->flags |= PF_SIZE_T;
1017 SET_SIZE_FLAGS(data, size_t);
1018 continue;
1019 case 't':
1020 data->flags |= PF_PTRDIFF_T;
1021 SET_SIZE_FLAGS(data, ptrdiff_t);
1022 continue;
1023
1024 /* Conversion specifiers */
1025#ifdef FLOATING_POINT
1026 case 'f': /* float, double */
1027 case 'F':
1028 STAR_ARGS(data);
1029 d = GETDOUBLE(data);
1030 floating(data, d);
1031conv_break:
1032 state = 0;
1033 break;
1034 case 'g':
1035 case 'G':
1036 STAR_ARGS(data);
1037 DEF_PREC(data);
1038 d = GETDOUBLE(data);
1039 i = log_10(d);
1040 /*
1041 * for '%g|%G' ANSI: use f if exponent
1042 * is in the range or [-4,p] exclusively
1043 * else use %e|%E
1044 */
1045 if (-4 < i && i < data->precision)
1046 floating(data, d);
1047 else
1048 exponent(data, d);
1049 state = 0;
1050 break;
1051 case 'e':
1052 case 'E': /* Exponent double */
1053 STAR_ARGS(data);
1054 d = GETDOUBLE(data);
1055 exponent(data, d);
1056 state = 0;
1057 break;
1058# ifdef HAVE_PRINTF_A_FORMAT
1059 case 'a':
1060 case 'A':
1061 STAR_ARGS(data);
1062 d = GETDOUBLE(data);
1063 dfallback(data, convstart, data->pf, d);
1064 state = 0;
1065 break;
1066# endif /* HAVE_PRINTF_A_FORMAT */
1067#endif /* FLOATING_POINT */
1068 case 'U':
1069 data->flags |= PF_LONGINT;
1070 /* FALLTHROUGH */
1071 case 'u':
1072 STAR_ARGS(data);
1073#ifdef HAVE_LONG_LONG
1074 if (data->flags & PF_LONGLONG)
1075 {
1076 ull = va_arg(args, unsigned long long);
1077 lnumber(data, ull, 10);
1078 }
1079 else
1080#endif
1081 {
1082 ul = GETUNSIGNED(data);
1083 number(data, ul, 10);
1084 }
1085 state = 0;
1086 break;
1087 case 'D':
1088 data->flags |= PF_LONGINT;
1089 /* FALLTHROUGH */
1090 case 'd': /* decimal */
1091 case 'i':
1092 STAR_ARGS(data);
1093#ifdef HAVE_LONG_LONG
1094 if (data->flags & PF_LONGLONG)
1095 {
1096 ull = va_arg(args, long long);
1097 lnumber(data, ull, 10);
1098 }
1099 else
1100#endif
1101 {
1102 ul = GETSIGNED(data);
1103 number(data, ul, 10);
1104 }
1105 state = 0;
1106 break;
1107 case 'o': /* octal */
1108 STAR_ARGS(data);
1109#ifdef HAVE_LONG_LONG
1110 if (data->flags & PF_LONGLONG)
1111 {
1112 ull = va_arg(args, unsigned long long);
1113 lnumber(data, ull, 8);
1114 }
1115 else
1116#endif
1117 {
1118 ul = GETUNSIGNED(data);
1119 number(data, ul, 8);
1120 }
1121 state = 0;
1122 break;
1123 case 'x':
1124 case 'X': /* hexadecimal */
1125 STAR_ARGS(data);
1126#ifdef HAVE_LONG_LONG
1127 if (data->flags & PF_LONGLONG)
1128 {
1129 ull = va_arg(args, unsigned long long);
1130 lnumber(data, ull, 16);
1131 }
1132 else
1133#endif
1134 {
1135 ul = GETUNSIGNED(data);
1136 number(data, ul, 16);
1137 }
1138 state = 0;
1139 break;
1140 case 'p':
1141 STAR_ARGS(data);
1142 ul = (unsigned long)va_arg(args, void *);
1143 pointer(data, ul);
1144 state = 0;
1145 break;
1146 case 'c': /* character */
1147 ul = va_arg(args, int);
1148 PUT_CHAR(ul, data);
1149 state = 0;
1150 break;
1151 case 's': /* string */
1152 STAR_ARGS(data);
1153 s = va_arg(args, char *);
1154 strings(data, s);
1155 state = 0;
1156 break;
1157 case 'n':
1158#ifdef HAVE_LONG_LONG
1159 if (data->flags & PF_LONGLONG)
1160 *(va_arg(args, long long *)) = data->counter;
1161 else
1162#endif
1163 if (data->flags & PF_LONGINT)
1164 *(va_arg(args, long *)) = data->counter;
1165 else if (data->flags & PF_SHORTINT)
1166 *(va_arg(args, short *)) = data->counter;
1167 else
1168 *(va_arg(args, int *)) = data->counter;
1169 state = 0;
1170 break;
1171 case '%': /* nothing just % */
1172 PUT_CHAR('%', data);
1173 state = 0;
1174 break;
1175 default:
1176 /* is this an error ? maybe bail out */
1177 state = 0;
1178 break;
1179 } /* end switch */
1180 } /* end of `%' for loop */
1181 } /* end of format string for loop */
1182
1183 if (data->length >= 0)
1184 *data->holder = '\0'; /* the end ye ! */
1185
1186 return data->counter;
1187}
1188
1189#if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1190/*
1191 * Printing floating point numbers accurately is an art. I'm not good
1192 * at it. Fall back to sprintf for long double formats.
1193 */
1194static void
1195ldfallback (data, fs, fe, ld)
1196 struct DATA *data;
1197 const char *fs, *fe;
1198 long double ld;
1199{
1200 register char *x;
1201 char fmtbuf[FALLBACK_FMTSIZE], *obuf;
1202 int fl;
1203
1204 obuf = xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2);
1205 fl = fe - fs + 1;
1206 strncpy (fmtbuf, fs, fl);
1207 fmtbuf[fl] = '\0';
1208 sprintf (obuf, fmtbuf, ld);
1209 for (x = obuf; *x; x++)
1210 PUT_CHAR (*x, data);
1211 xfree (obuf);
1212}
1213#endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1214
1215#ifdef FLOATING_POINT
1216/* Used for %a, %A if the libc printf supports them. */
1217static void
1218dfallback (data, fs, fe, d)
1219 struct DATA *data;
1220 const char *fs, *fe;
1221 double d;
1222{
1223 register char *x;
1224 char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE];
1225 int fl;
1226
1227 fl = fe - fs + 1;
1228 strncpy (fmtbuf, fs, fl);
1229 fmtbuf[fl] = '\0';
1230 sprintf (obuf, fmtbuf, d);
1231 for (x = obuf; *x; x++)
1232 PUT_CHAR (*x, data);
1233}
1234#endif /* FLOATING_POINT */
1235
1236#ifndef HAVE_SNPRINTF
1237
1238int
1239#if defined (__STDC__)
1240vsnprintf(char *string, size_t length, const char *format, va_list args)
1241#else
1242vsnprintf(string, length, format, args)
1243 char *string;
1244 size_t length;
1245 const char *format;
1246 va_list args;
1247#endif
1248{
1249 struct DATA data;
1250
1251 init_data (&data, string, length, format, PFM_SN);
1252 return (vsnprintf_internal(&data, string, length, format, args));
1253}
1254
1255int
1256#if defined(PREFER_STDARG)
1257snprintf(char *string, size_t length, const char * format, ...)
1258#else
1259snprintf(string, length, format, va_alist)
1260 char *string;
1261 size_t length;
1262 const char *format;
1263 va_dcl
1264#endif
1265{
1266 struct DATA data;
1267 int rval;
1268 va_list args;
1269
1270#if defined(PREFER_STDARG)
1271 va_start(args, format);
1272#else
1273 va_start(args);
1274#endif
1275
1276 init_data (&data, string, length, format, PFM_SN);
1277 rval = vsnprintf_internal (&data, string, length, format, args);
1278
1279 va_end(args);
1280
1281 return rval;
1282}
1283
1284#endif /* HAVE_SNPRINTF */
1285
1286#ifndef HAVE_ASPRINTF
1287
1288int
1289#if defined (__STDC__)
1290vasprintf(char **stringp, const char *format, va_list args)
1291#else
1292vasprintf(stringp, format, args)
1293 char **stringp;
1294 const char *format;
1295 va_list args;
1296#endif
1297{
1298 struct DATA data;
1299 char *string;
1300 int r;
1301
1302 string = (char *)xmalloc(ASBUFSIZE);
1303 init_data (&data, string, ASBUFSIZE, format, PFM_AS);
1304 r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args);
1305 *stringp = data.base; /* not string in case reallocated */
1306 return r;
1307}
1308
1309int
1310#if defined(PREFER_STDARG)
1311asprintf(char **stringp, const char * format, ...)
1312#else
1313asprintf(stringp, format, va_alist)
1314 char **stringp;
1315 const char *format;
1316 va_dcl
1317#endif
1318{
1319 int rval;
1320 va_list args;
1321
1322#if defined(PREFER_STDARG)
1323 va_start(args, format);
1324#else
1325 va_start(args);
1326#endif
1327
1328 rval = vasprintf (stringp, format, args);
1329
1330 va_end(args);
1331
1332 return rval;
1333}
1334
1335#endif
1336
1337#endif
1338
1339#ifdef DRIVER
1340
1341static void
1342memory_error_and_abort ()
1343{
1344 write (2, "out of virtual memory\n", 22);
1345 abort ();
1346}
1347
1348static void *
1349xmalloc(bytes)
1350 size_t bytes;
1351{
1352 void *ret;
1353
1354 ret = malloc(bytes);
1355 if (ret == 0)
1356 memory_error_and_abort ();
1357 return ret;
1358}
1359
1360static void *
1361xrealloc (pointer, bytes)
1362 void *pointer;
1363 size_t bytes;
1364{
1365 void *ret;
1366
1367 ret = pointer ? realloc(pointer, bytes) : malloc(bytes);
1368 if (ret == 0)
1369 memory_error_and_abort ();
1370 return ret;
1371}
1372
1373static void
1374xfree(x)
1375 void *x;
1376{
1377 if (x)
1378 free (x);
1379}
1380
1381#ifdef FLOATING_POINT
1382# include <float.h>
1383#endif
1384
1385/* set of small tests for snprintf() */
1386main()
1387{
1388 char holder[100];
1389 char *h;
1390 int i, si, ai;
1391
1392/*
1393 printf("Suite of test for snprintf:\n");
1394 printf("a_format\n");
1395 printf("printf() format\n");
1396 printf("snprintf() format\n\n");
1397*/
1398/* Checking the field widths */
1399
1400 printf("/%%ld %%ld/, 336, 336\n");
1401 snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336);
1402 asprintf(&h, "/%ld %ld/\n", 336, 336);
1403 printf("/%ld %ld/\n", 336, 336);
1404 printf("%s", holder);
1405 printf("%s\n", h);
1406
1407 printf("/%%d/, 336\n");
1408 snprintf(holder, sizeof holder, "/%d/\n", 336);
1409 asprintf(&h, "/%d/\n", 336);
1410 printf("/%d/\n", 336);
1411 printf("%s", holder);
1412 printf("%s\n", h);
1413
1414 printf("/%%2d/, 336\n");
1415 snprintf(holder, sizeof holder, "/%2d/\n", 336);
1416 asprintf(&h, "/%2d/\n", 336);
1417 printf("/%2d/\n", 336);
1418 printf("%s", holder);
1419 printf("%s\n", h);
1420
1421 printf("/%%10d/, 336\n");
1422 snprintf(holder, sizeof holder, "/%10d/\n", 336);
1423 asprintf(&h, "/%10d/\n", 336);
1424 printf("/%10d/\n", 336);
1425 printf("%s", holder);
1426 printf("%s\n", h);
1427
1428 printf("/%%-10d/, 336\n");
1429 snprintf(holder, sizeof holder, "/%-10d/\n", 336);
1430 asprintf(&h, "/%-10d/\n", 336);
1431 printf("/%-10d/\n", 336);
1432 printf("%s", holder);
1433 printf("%s\n", h);
1434
1435
1436/* floating points */
1437
1438 printf("/%%f/, 1234.56\n");
1439 snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
1440 asprintf(&h, "/%f/\n", 1234.56);
1441 printf("/%f/\n", 1234.56);
1442 printf("%s", holder);
1443 printf("%s\n", h);
1444
1445 printf("/%%e/, 1234.56\n");
1446 snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
1447 asprintf(&h, "/%e/\n", 1234.56);
1448 printf("/%e/\n", 1234.56);
1449 printf("%s", holder);
1450 printf("%s\n", h);
1451
1452 printf("/%%4.2f/, 1234.56\n");
1453 snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
1454 asprintf(&h, "/%4.2f/\n", 1234.56);
1455 printf("/%4.2f/\n", 1234.56);
1456 printf("%s", holder);
1457 printf("%s\n", h);
1458
1459 printf("/%%3.1f/, 1234.56\n");
1460 snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
1461 asprintf(&h, "/%3.1f/\n", 1234.56);
1462 printf("/%3.1f/\n", 1234.56);
1463 printf("%s", holder);
1464 printf("%s\n", h);
1465
1466 printf("/%%10.3f/, 1234.56\n");
1467 snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
1468 asprintf(&h, "/%10.3f/\n", 1234.56);
1469 printf("/%10.3f/\n", 1234.56);
1470 printf("%s", holder);
1471 printf("%s\n", h);
1472
1473 printf("/%%10.3e/, 1234.56\n");
1474 snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
1475 asprintf(&h, "/%10.3e/\n", 1234.56);
1476 printf("/%10.3e/\n", 1234.56);
1477 printf("%s", holder);
1478 printf("%s\n", h);
1479
1480 printf("/%%+4.2f/, 1234.56\n");
1481 snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
1482 asprintf(&h, "/%+4.2f/\n", 1234.56);
1483 printf("/%+4.2f/\n", 1234.56);
1484 printf("%s", holder);
1485 printf("%s\n", h);
1486
1487 printf("/%%010.2f/, 1234.56\n");
1488 snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
1489 asprintf(&h, "/%010.2f/\n", 1234.56);
1490 printf("/%010.2f/\n", 1234.56);
1491 printf("%s", holder);
1492 printf("%s\n", h);
1493
1494#define BLURB "Outstanding acting !"
1495/* strings precisions */
1496
1497 printf("/%%2s/, \"%s\"\n", BLURB);
1498 snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
1499 asprintf(&h, "/%2s/\n", BLURB);
1500 printf("/%2s/\n", BLURB);
1501 printf("%s", holder);
1502 printf("%s\n", h);
1503
1504 printf("/%%22s/ %s\n", BLURB);
1505 snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
1506 asprintf(&h, "/%22s/\n", BLURB);
1507 printf("/%22s/\n", BLURB);
1508 printf("%s", holder);
1509 printf("%s\n", h);
1510
1511 printf("/%%22.5s/ %s\n", BLURB);
1512 snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
1513 asprintf(&h, "/%22.5s/\n", BLURB);
1514 printf("/%22.5s/\n", BLURB);
1515 printf("%s", holder);
1516 printf("%s\n", h);
1517
1518 printf("/%%-22.5s/ %s\n", BLURB);
1519 snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
1520 asprintf(&h, "/%-22.5s/\n", BLURB);
1521 printf("/%-22.5s/\n", BLURB);
1522 printf("%s", holder);
1523 printf("%s\n", h);
1524
1525/* see some flags */
1526
1527 printf("%%x %%X %%#x, 31, 31, 31\n");
1528 snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
1529 asprintf(&h, "%x %X %#x\n", 31, 31, 31);
1530 printf("%x %X %#x\n", 31, 31, 31);
1531 printf("%s", holder);
1532 printf("%s\n", h);
1533
1534 printf("**%%d**%% d**%% d**, 42, 42, -42\n");
1535 snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
1536 asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42);
1537 printf("**%d**% d**% d**\n", 42, 42, -42);
1538 printf("%s", holder);
1539 printf("%s\n", h);
1540
1541/* other flags */
1542
1543 printf("/%%g/, 31.4\n");
1544 snprintf(holder, sizeof holder, "/%g/\n", 31.4);
1545 asprintf(&h, "/%g/\n", 31.4);
1546 printf("/%g/\n", 31.4);
1547 printf("%s", holder);
1548 printf("%s\n", h);
1549
1550 printf("/%%.6g/, 31.4\n");
1551 snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
1552 asprintf(&h, "/%.6g/\n", 31.4);
1553 printf("/%.6g/\n", 31.4);
1554 printf("%s", holder);
1555 printf("%s\n", h);
1556
1557 printf("/%%.1G/, 31.4\n");
1558 snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
1559 asprintf(&h, "/%.1G/\n", 31.4);
1560 printf("/%.1G/\n", 31.4);
1561 printf("%s", holder);
1562 printf("%s\n", h);
1563
1564 printf("/%%.1G/, 3100000000.4\n");
1565 snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);
1566 asprintf(&h, "/%.1G/\n", 3100000000.4);
1567 printf("/%.1G/\n", 3100000000.4);
1568 printf("%s", holder);
1569 printf("%s\n", h);
1570
1571 printf("abc%%n\n");
1572 printf("abc%n", &i); printf("%d\n", i);
1573 snprintf(holder, sizeof holder, "abc%n", &i);
1574 printf("%s", holder); printf("%d\n\n", i);
1575 asprintf(&h, "abc%n", &i);
1576 printf("%s", h); printf("%d\n\n", i);
1577
1578 printf("%%*.*s --> 10.10\n");
1579 snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
1580 asprintf(&h, "%*.*s\n", 10, 10, BLURB);
1581 printf("%*.*s\n", 10, 10, BLURB);
1582 printf("%s", holder);
1583 printf("%s\n", h);
1584
1585 printf("%%%%%%%%\n");
1586 snprintf(holder, sizeof holder, "%%%%\n");
1587 asprintf(&h, "%%%%\n");
1588 printf("%%%%\n");
1589 printf("%s", holder);
1590 printf("%s\n", h);
1591
1592#define BIG "Hello this is a too big string for the buffer"
1593/* printf("A buffer to small of 10, trying to put this:\n");*/
1594 printf("<%%>, %s\n", BIG);
1595 i = snprintf(holder, 10, "%s\n", BIG);
1596 i = asprintf(&h, "%s", BIG);
1597 printf("<%s>\n", BIG);
1598 printf("<%s>\n", holder);
1599 printf("<%s>\n\n", h);
1600
1601 printf ("<%%p> vsnprintf\n");
1602 i = snprintf(holder, 100, "%p", vsnprintf);
1603 i = asprintf(&h, "%p", vsnprintf);
1604 printf("<%p>\n", vsnprintf);
1605 printf("<%s>\n", holder);
1606 printf("<%s>\n\n", h);
1607
1608 printf ("<%%lu> LONG_MAX+1\n");
1609 i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1);
1610 i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1);
1611 printf("<%lu>\n", (unsigned long)(LONG_MAX)+1);
1612 printf("<%s>\n", holder);
1613 printf("<%s>\n\n", h);
1614
1615#ifdef HAVE_LONG_LONG
1616 printf ("<%%llu> LLONG_MAX+1\n");
1617 i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1);
1618 i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1);
1619 printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1);
1620 printf("<%s>\n", holder);
1621 printf("<%s>\n\n", h);
1622#endif
1623
1624#ifdef HAVE_LONG_DOUBLE
1625 printf ("<%%6.2LE> 42.42\n");
1626 i = snprintf(holder, 100, "%6.2LE", (long double)42.42);
1627 i = asprintf(&h, "%6.2LE", (long double)42.42);
1628 printf ("<%6.2LE>\n", (long double)42.42);
1629 printf ("<%s>\n", holder);
1630 printf ("<%s>\n\n", h);
1631#endif
1632
1633#ifdef HAVE_PRINTF_A_FORMAT
1634 printf ("<%%6.2A> 42.42\n");
1635 i = snprintf(holder, 100, "%6.2A", 42.42);
1636 i = asprintf(&h, "%6.2A", 42.42);
1637 printf ("<%6.2A>\n", 42.42);
1638 printf ("<%s>\n", holder);
1639 printf ("<%s>\n\n", h);
1640
1641 printf ("<%%6.2LA> 42.42\n");
1642 i = snprintf(holder, 100, "%6.2LA", (long double)42.42);
1643 i = asprintf(&h, "%6.2LA", (long double)42.42);
1644 printf ("<%6.2LA>\n", (long double)42.42);
1645 printf ("<%s>\n", holder);
1646 printf ("<%s>\n\n", h);
1647#endif
1648
1649 printf ("<%%.10240f> DBL_MAX\n");
1650 si = snprintf(holder, 100, "%.10240f", DBL_MAX);
1651 ai = asprintf(&h, "%.10240f", DBL_MAX);
1652 printf ("<%.10240f>\n", DBL_MAX);
1653 printf ("<%d> <%s>\n", si, holder);
1654 printf ("<%d> <%s>\n\n", ai, h);
1655
1656 printf ("<%%.10240Lf> LDBL_MAX\n");
1657 si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX);
1658 ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX);
1659 printf ("<%.10240Lf>\n", (long double)LDBL_MAX);
1660 printf ("<%d> <%s>\n", si, holder);
1661 printf ("<%d> <%s>\n\n", ai, h);
1662
1663 exit (0);
1664}
1665#endif