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