1 /* estream-printf.c - Versatile C-99 compliant printf formatting
2 * Copyright (C) 2007, 2008, 2009 g10 Code GmbH
4 * This file is part of Libestream.
6 * Libestream is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License,
9 * or (at your option) any later version.
11 * Libestream is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Libestream; if not, see <http://www.gnu.org/licenses/>.
20 /* Required autoconf tests:
22 AC_TYPE_LONG_LONG_INT defines HAVE_LONG_LONG_INT
23 AC_TYPE_LONG_DOUBLE defines HAVE_LONG_DOUBLE
24 AC_TYPE_INTMAX_T defines HAVE_INTMAX_T
25 AC_TYPE_UINTMAX_T defines HAVE_UINTMAX_T
26 AC_CHECK_TYPES([ptrdiff_t]) defines HAVE_PTRDIFF_T
27 AC_CHECK_SIZEOF([unsigned long]) defines SIZEOF_UNSIGNED_LONG
28 AC_CHECK_SIZEOF([void *]) defines SIZEOF_VOID_P
29 HAVE_LANGINFO_THOUSANDS_SEP
31 Note that the file estream.m4 provides the autoconf macro
32 ESTREAM_PRINTF_INIT which runs all required checks.
33 See estream-printf.h for ways to tune this code.
35 Missing stuff: wchar and wint_t
36 thousands_sep in pr_float.
52 #if defined(HAVE_INTMAX_T) || defined(HAVE_UINTMAX_T)
57 #ifdef HAVE_LANGINFO_THOUSANDS_SEP
60 #ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE
61 # include _ESTREAM_PRINTF_EXTRA_INCLUDE
63 #include "estream-printf.h"
68 /* Allow redefinition of asprintf used malloc functions. */
69 #if defined(_ESTREAM_PRINTF_MALLOC)
70 #define my_printf_malloc(a) _ESTREAM_PRINTF_MALLOC((a))
72 #define my_printf_malloc(a) malloc((a))
74 #if defined(_ESTREAM_PRINTF_FREE)
75 #define my_printf_free(a) _ESTREAM_PRINTF_FREE((a))
77 #define my_printf_free(a) free((a))
81 /* Calculate array dimension. */
83 #define DIM(array) (sizeof (array) / sizeof (*array))
87 /* We allow for that many args without requiring malloced memory. */
88 #define DEFAULT_MAX_ARGSPECS 5
90 /* We allow for that many values without requiring malloced memory. */
91 #define DEFAULT_MAX_VALUES 8
93 /* We allocate this many new array argspec elements each time. */
94 #define ARGSPECS_BUMP_VALUE 10
96 /* Special values for the field width and the precision. */
97 #define NO_FIELD_VALUE (-1)
98 #define STAR_FIELD_VALUE (-2)
100 /* Bit valuues used for the conversion flags. */
101 #define FLAG_GROUPING 1
102 #define FLAG_LEFT_JUST 2
103 #define FLAG_PLUS_SIGN 4
104 #define FLAG_SPACE_PLUS 8
105 #define FLAG_ALT_CONV 16
106 #define FLAG_ZERO_PAD 32
108 /* Constants used the length modifiers. */
112 LENMOD_CHAR
, /* "hh" */
113 LENMOD_SHORT
, /* "h" */
114 LENMOD_LONG
, /* "l" */
115 LENMOD_LONGLONG
, /* "ll" */
116 LENMOD_INTMAX
, /* "j" */
117 LENMOD_SIZET
, /* "z" */
118 LENMOD_PTRDIFF
, /* "t" */
119 LENMOD_LONGDBL
/* "L" */
122 /* All the conversion specifiers. */
147 /* Constants describing all the suppoorted types. Note that we list
148 all the types we know about even if certain types are not available
152 VALTYPE_UNSUPPORTED
= 0, /* Artificial type for error detection. */
177 VALTYPE_LONGLONG_PTR
,
184 /* A union used to store the actual values. */
189 unsigned char a_uchar
;
191 unsigned short a_ushort
;
195 unsigned long int a_ulong
;
196 #ifdef HAVE_LONG_LONG_INT
197 long long int a_longlong
;
198 unsigned long long int a_ulonglong
;
201 #ifdef HAVE_LONG_DOUBLE
202 long double a_longdouble
;
204 const char *a_string
;
208 #ifdef HAVE_UINTMAX_T
212 #ifdef HAVE_PTRDIFF_T
217 signed char *a_schar_ptr
;
221 #ifdef HAVE_LONG_LONG_INT
222 long long int *a_longlong_ptr
;
225 intmax_t *a_intmax_ptr
;
228 #ifdef HAVE_PTRDIFF_T
229 ptrdiff_t *a_ptrdiff_ptr
;
233 /* An object used to keep track of a format option and arguments. */
236 size_t length
; /* The length of these args including the percent. */
237 unsigned int flags
; /* The conversion flags (bits defined by FLAG_foo). */
238 int width
; /* The field width. */
239 int precision
; /* The precision. */
240 lenmod_t lenmod
; /* The length modifier. */
241 conspec_t conspec
; /* The conversion specifier. */
242 int arg_pos
; /* The position of the argument. This one may
243 be -1 to indicate that no value is expected
245 int width_pos
; /* The position of the argument for a field
246 width star's value. 0 for not used. */
247 int precision_pos
; /* The position of the argument for the a
248 precision star's value. 0 for not used. */
249 valtype_t vt
; /* The type of the corresponding argument. */
251 typedef struct argspec_s
*argspec_t
;
253 /* An object to build up a table of values and their types. */
256 valtype_t vt
; /* The type of the value. */
257 value_t value
; /* The value. */
259 typedef struct valueitem_s
*valueitem_t
;
264 dump_argspecs (argspec_t arg
, size_t argcount
)
268 for (idx
=0; argcount
; argcount
--, arg
++, idx
++)
270 "%2d: len=%u flags=%u width=%d prec=%d mod=%d "
271 "con=%d vt=%d pos=%d-%d-%d\n",
273 (unsigned int)arg
->length
,
287 /* Set the vt field for ARG. */
289 compute_type (argspec_t arg
)
291 switch (arg
->conspec
)
293 case CONSPEC_UNKNOWN
:
294 arg
->vt
= VALTYPE_UNSUPPORTED
;
297 case CONSPEC_DECIMAL
:
300 case LENMOD_CHAR
: arg
->vt
= VALTYPE_SCHAR
; break;
301 case LENMOD_SHORT
: arg
->vt
= VALTYPE_SHORT
; break;
302 case LENMOD_LONG
: arg
->vt
= VALTYPE_LONG
; break;
303 case LENMOD_LONGLONG
: arg
->vt
= VALTYPE_LONGLONG
; break;
304 case LENMOD_INTMAX
: arg
->vt
= VALTYPE_INTMAX
; break;
305 case LENMOD_SIZET
: arg
->vt
= VALTYPE_SIZE
; break;
306 case LENMOD_PTRDIFF
: arg
->vt
= VALTYPE_PTRDIFF
; break;
307 default: arg
->vt
= VALTYPE_INT
; break;
312 case CONSPEC_UNSIGNED
:
317 case LENMOD_CHAR
: arg
->vt
= VALTYPE_UCHAR
; break;
318 case LENMOD_SHORT
: arg
->vt
= VALTYPE_USHORT
; break;
319 case LENMOD_LONG
: arg
->vt
= VALTYPE_ULONG
; break;
320 case LENMOD_LONGLONG
: arg
->vt
= VALTYPE_ULONGLONG
; break;
321 case LENMOD_INTMAX
: arg
->vt
= VALTYPE_UINTMAX
; break;
322 case LENMOD_SIZET
: arg
->vt
= VALTYPE_SIZE
; break;
323 case LENMOD_PTRDIFF
: arg
->vt
= VALTYPE_PTRDIFF
; break;
324 default: arg
->vt
= VALTYPE_UINT
; break;
329 case CONSPEC_FLOAT_UP
:
333 case CONSPEC_F_OR_G_UP
:
334 case CONSPEC_HEX_EXP
:
335 case CONSPEC_HEX_EXP_UP
:
338 case LENMOD_LONGDBL
: arg
->vt
= VALTYPE_LONGDOUBLE
; break;
339 case LENMOD_LONG
: arg
->vt
= VALTYPE_DOUBLE
; break;
340 default: arg
->vt
= VALTYPE_DOUBLE
; break;
345 arg
->vt
= VALTYPE_INT
;
349 arg
->vt
= VALTYPE_STRING
;
352 case CONSPEC_POINTER
:
353 arg
->vt
= VALTYPE_POINTER
;
356 case CONSPEC_STRERROR
:
357 arg
->vt
= VALTYPE_STRING
;
360 case CONSPEC_BYTES_SO_FAR
:
363 case LENMOD_CHAR
: arg
->vt
= VALTYPE_SCHAR_PTR
; break;
364 case LENMOD_SHORT
: arg
->vt
= VALTYPE_SHORT_PTR
; break;
365 case LENMOD_LONG
: arg
->vt
= VALTYPE_LONG_PTR
; break;
366 case LENMOD_LONGLONG
: arg
->vt
= VALTYPE_LONGLONG_PTR
; break;
367 case LENMOD_INTMAX
: arg
->vt
= VALTYPE_INTMAX_PTR
; break;
368 case LENMOD_SIZET
: arg
->vt
= VALTYPE_SIZE_PTR
; break;
369 case LENMOD_PTRDIFF
: arg
->vt
= VALTYPE_PTRDIFF_PTR
; break;
370 default: arg
->vt
= VALTYPE_INT_PTR
; break;
379 /* Parse the FORMAT string and populate the specification array stored
380 at the address ARGSPECS_ADDR. The caller has provided enough space
381 to store up to MAX_ARGSPECS in that buffer. The function may
382 however ignore the provided buffer and malloc a larger one. On
383 success the addrrss of that larger buffer will be stored at
384 ARGSPECS_ADDR. The actual number of specifications will be
385 returned at R_ARGSPECS_COUNT. */
387 parse_format (const char *format
,
388 argspec_t
*argspecs_addr
, size_t max_argspecs
,
389 size_t *r_argspecs_count
)
392 argspec_t argspecs
= *argspecs_addr
;
399 for (; *format
; format
++)
402 int width
, precision
;
405 int arg_pos
, width_pos
, precision_pos
;
413 continue; /* Just a quoted percent. */
415 /* First check whether there is a positional argument. */
416 arg_pos
= 0; /* No positional argument given. */
417 if (*s
>= '1' && *s
<= '9')
419 const char *save_s
= s
;
421 arg_pos
= (*s
++ - '0');
422 for (; *s
>= '0' && *s
<= '9'; s
++)
423 arg_pos
= 10*arg_pos
+ (*s
- '0');
425 goto leave_einval
; /* Overflow during conversion. */
435 /* Parse the flags. */
441 case '\'': flags
|= FLAG_GROUPING
; break;
442 case '-': flags
|= FLAG_LEFT_JUST
; break;
443 case '+': flags
|= FLAG_PLUS_SIGN
; break;
444 case ' ': flags
|= FLAG_SPACE_PLUS
; break;
445 case '#': flags
|= FLAG_ALT_CONV
; break;
446 case '0': flags
|= FLAG_ZERO_PAD
; break;
453 /* Parse the field width. */
457 width
= STAR_FIELD_VALUE
;
459 /* If we have a positional argument, another one might also
460 be used to give the position of the star's value. */
461 if (arg_pos
&& *s
>= '1' && *s
<= '9')
463 width_pos
= (*s
++ - '0');
464 for (; *s
>= '0' && *s
<= '9'; s
++)
465 width_pos
= 10*width_pos
+ (*s
- '0');
467 goto leave_einval
; /* Overflow during conversion. */
469 goto leave_einval
; /* Not followed by $. */
473 else if ( *s
>= '0' && *s
<= '9')
475 width
= (*s
++ - '0');
476 for (; *s
>= '0' && *s
<= '9'; s
++)
478 if (!width
&& *s
== '0')
479 goto leave_einval
; /* Leading zeroes are not allowed.
480 Fixme: check what other
481 implementations do. */
482 width
= 10*width
+ (*s
- '0');
485 goto leave_einval
; /* Overflow during conversion. */
488 width
= NO_FIELD_VALUE
;
490 /* Parse the precision. */
492 precision
= NO_FIELD_VALUE
;
495 int ignore_value
= (s
[1] == '-');
500 precision
= STAR_FIELD_VALUE
;
502 /* If we have a positional argument, another one might also
503 be used to give the position of the star's value. */
504 if (arg_pos
&& *s
>= '1' && *s
<= '9')
506 precision_pos
= (*s
++ - '0');
507 for (; *s
>= '0' && *s
<= '9'; s
++)
508 precision_pos
= 10*precision_pos
+ (*s
- '0');
509 if (precision_pos
< 1)
510 goto leave_einval
; /* Overflow during conversion. */
512 goto leave_einval
; /* Not followed by $. */
516 else if ( *s
>= '0' && *s
<= '9')
518 precision
= (*s
++ - '0');
519 for (; *s
>= '0' && *s
<= '9'; s
++)
521 if (!precision
&& *s
== '0')
522 goto leave_einval
; /* Leading zeroes are not allowed.
523 Fixme: check what other
524 implementations do. */
525 precision
= 10*precision
+ (*s
- '0');
528 goto leave_einval
; /* Overflow during conversion. */
533 precision
= NO_FIELD_VALUE
;
536 /* Parse the length modifiers. */
542 lenmod
= LENMOD_CHAR
;
546 lenmod
= LENMOD_SHORT
;
552 lenmod
= LENMOD_LONGLONG
;
556 lenmod
= LENMOD_LONG
;
559 case 'j': lenmod
= LENMOD_INTMAX
; s
++; break;
560 case 'z': lenmod
= LENMOD_SIZET
; s
++; break;
561 case 't': lenmod
= LENMOD_PTRDIFF
; s
++; break;
562 case 'L': lenmod
= LENMOD_LONGDBL
; s
++; break;
563 default: lenmod
= LENMOD_NONE
; break;
566 /* Parse the conversion specifier. */
570 case 'i': conspec
= CONSPEC_DECIMAL
; break;
571 case 'o': conspec
= CONSPEC_OCTAL
; break;
572 case 'u': conspec
= CONSPEC_UNSIGNED
; break;
573 case 'x': conspec
= CONSPEC_HEX
; break;
574 case 'X': conspec
= CONSPEC_HEX_UP
; break;
575 case 'f': conspec
= CONSPEC_FLOAT
; break;
576 case 'F': conspec
= CONSPEC_FLOAT_UP
; break;
577 case 'e': conspec
= CONSPEC_EXP
; break;
578 case 'E': conspec
= CONSPEC_EXP_UP
; break;
579 case 'g': conspec
= CONSPEC_F_OR_G
; break;
580 case 'G': conspec
= CONSPEC_F_OR_G_UP
; break;
581 case 'a': conspec
= CONSPEC_HEX_EXP
; break;
582 case 'A': conspec
= CONSPEC_HEX_EXP_UP
; break;
583 case 'c': conspec
= CONSPEC_CHAR
; break;
584 case 's': conspec
= CONSPEC_STRING
; break;
585 case 'p': conspec
= CONSPEC_POINTER
; break;
586 case 'n': conspec
= CONSPEC_BYTES_SO_FAR
; break;
587 case 'C': conspec
= CONSPEC_CHAR
; lenmod
= LENMOD_LONG
; break;
588 case 'S': conspec
= CONSPEC_STRING
; lenmod
= LENMOD_LONG
; break;
589 case 'm': conspec
= CONSPEC_STRERROR
; arg_pos
= -1; break;
590 default: conspec
= CONSPEC_UNKNOWN
;
594 if (argcount
>= max_argspecs
)
596 /* We either need to allocate a new array instead of the
597 caller provided one or realloc the array. Instead of
598 using realloc we allocate a new one and release the
599 original one then. */
603 newmax
= max_argspecs
+ ARGSPECS_BUMP_VALUE
;
604 if (newmax
<= max_argspecs
)
605 goto leave_einval
; /* Too many arguments. */
606 newarg
= calloc (newmax
, sizeof *newarg
);
609 for (n
=0; n
< argcount
; n
++)
610 newarg
[n
] = argspecs
[n
];
611 if (argspecs
!= *argspecs_addr
)
614 max_argspecs
= newmax
;
617 arg
= argspecs
+ argcount
;
618 arg
->length
= s
- format
+ 2;
621 arg
->precision
= precision
;
622 arg
->lenmod
= lenmod
;
623 arg
->conspec
= conspec
;
624 arg
->arg_pos
= arg_pos
;
625 arg
->width_pos
= width_pos
;
626 arg
->precision_pos
= precision_pos
;
632 *argspecs_addr
= argspecs
;
633 *r_argspecs_count
= argcount
;
634 return 0; /* Success. */
639 if (argspecs
!= *argspecs_addr
)
641 *argspecs_addr
= NULL
;
646 /* This function reads all the values as specified by VALUETABLE into
647 VALUETABLE. The values are expected in VAARGS. The function
648 returns -1 if a specified type is not supported. */
650 read_values (valueitem_t valuetable
, size_t valuetable_len
, va_list vaargs
)
654 for (validx
=0; validx
< valuetable_len
; validx
++)
656 value_t
*value
= &valuetable
[validx
].value
;
657 valtype_t vt
= valuetable
[validx
].vt
;
661 case VALTYPE_CHAR
: value
->a_char
= va_arg (vaargs
, int); break;
662 case VALTYPE_CHAR_PTR
:
663 value
->a_char_ptr
= va_arg (vaargs
, char *);
665 case VALTYPE_SCHAR
: value
->a_schar
= va_arg (vaargs
, int); break;
666 case VALTYPE_SCHAR_PTR
:
667 value
->a_schar_ptr
= va_arg (vaargs
, signed char *);
669 case VALTYPE_UCHAR
: value
->a_uchar
= va_arg (vaargs
, int); break;
670 case VALTYPE_SHORT
: value
->a_short
= va_arg (vaargs
, int); break;
671 case VALTYPE_USHORT
: value
->a_ushort
= va_arg (vaargs
, int); break;
672 case VALTYPE_SHORT_PTR
:
673 value
->a_short_ptr
= va_arg (vaargs
, short *);
676 value
->a_int
= va_arg (vaargs
, int);
678 case VALTYPE_INT_PTR
:
679 value
->a_int_ptr
= va_arg (vaargs
, int *);
682 value
->a_uint
= va_arg (vaargs
, unsigned int);
685 value
->a_long
= va_arg (vaargs
, long);
688 value
->a_ulong
= va_arg (vaargs
, unsigned long);
690 case VALTYPE_LONG_PTR
:
691 value
->a_long_ptr
= va_arg (vaargs
, long *);
693 #ifdef HAVE_LONG_LONG_INT
694 case VALTYPE_LONGLONG
:
695 value
->a_longlong
= va_arg (vaargs
, long long int);
697 case VALTYPE_ULONGLONG
:
698 value
->a_ulonglong
= va_arg (vaargs
, unsigned long long int);
700 case VALTYPE_LONGLONG_PTR
:
701 value
->a_longlong_ptr
= va_arg (vaargs
, long long *);
705 value
->a_double
= va_arg (vaargs
, double);
707 #ifdef HAVE_LONG_DOUBLE
708 case VALTYPE_LONGDOUBLE
:
709 value
->a_longdouble
= va_arg (vaargs
, long double);
713 value
->a_string
= va_arg (vaargs
, const char *);
715 case VALTYPE_POINTER
:
716 value
->a_void_ptr
= va_arg (vaargs
, void *);
720 value
->a_intmax
= va_arg (vaargs
, intmax_t);
722 case VALTYPE_INTMAX_PTR
:
723 value
->a_intmax_ptr
= va_arg (vaargs
, intmax_t *);
726 #ifdef HAVE_UINTMAX_T
727 case VALTYPE_UINTMAX
:
728 value
->a_uintmax
= va_arg (vaargs
, uintmax_t);
732 value
->a_size
= va_arg (vaargs
, size_t);
734 case VALTYPE_SIZE_PTR
:
735 value
->a_size_ptr
= va_arg (vaargs
, size_t *);
737 #ifdef HAVE_PTRDIFF_T
738 case VALTYPE_PTRDIFF
:
739 value
->a_ptrdiff
= va_arg (vaargs
, ptrdiff_t);
741 case VALTYPE_PTRDIFF_PTR
:
742 value
->a_ptrdiff_ptr
= va_arg (vaargs
, ptrdiff_t *);
745 default: /* Unsupported type. */
754 /* Output COUNT padding characters PADCHAR and update NBYTES by the
755 number of bytes actually written. */
757 pad_out (estream_printf_out_t outfnc
, void *outfncarg
,
758 int padchar
, int count
, size_t *nbytes
)
766 n
= (count
<= sizeof buf
)? count
: sizeof buf
;
767 memset (buf
, padchar
, n
);
768 rc
= outfnc (outfncarg
, buf
, n
);
779 /* "d,i,o,u,x,X" formatting. OUTFNC and OUTFNCARG describes the
780 output routine, ARG gives the argument description and VALUE the
781 actual value (its type is available through arg->vt). */
783 pr_integer (estream_printf_out_t outfnc
, void *outfncarg
,
784 argspec_t arg
, value_t value
, size_t *nbytes
)
787 #ifdef HAVE_LONG_LONG_INT
788 unsigned long long aulong
;
790 unsigned long aulong
;
796 int n_prec
; /* Number of extra precision digits required. */
797 int n_extra
; /* Extra number of prefix or sign characters. */
799 if (arg
->conspec
== CONSPEC_DECIMAL
)
801 #ifdef HAVE_LONG_LONG_INT
809 case VALTYPE_SHORT
: along
= value
.a_short
; break;
810 case VALTYPE_INT
: along
= value
.a_int
; break;
811 case VALTYPE_LONG
: along
= value
.a_long
; break;
812 #ifdef HAVE_LONG_LONG_INT
813 case VALTYPE_LONGLONG
: along
= value
.a_longlong
; break;
814 case VALTYPE_SIZE
: along
= value
.a_size
; break;
815 # ifdef HAVE_INTMAX_T
816 case VALTYPE_INTMAX
: along
= value
.a_intmax
; break;
818 # ifdef HAVE_PTRDIFF_T
819 case VALTYPE_PTRDIFF
: along
= value
.a_ptrdiff
; break;
821 #endif /*HAVE_LONG_LONG_INT*/
837 case VALTYPE_USHORT
: aulong
= value
.a_ushort
; break;
838 case VALTYPE_UINT
: aulong
= value
.a_uint
; break;
839 case VALTYPE_ULONG
: aulong
= value
.a_ulong
; break;
840 #ifdef HAVE_LONG_LONG_INT
841 case VALTYPE_ULONGLONG
: aulong
= value
.a_ulonglong
; break;
842 case VALTYPE_SIZE
: aulong
= value
.a_size
; break;
843 # ifdef HAVE_UINTMAX_T
844 case VALTYPE_UINTMAX
: aulong
= value
.a_uintmax
; break;
846 # ifdef HAVE_PTRDIFF_T
847 case VALTYPE_PTRDIFF
: aulong
= value
.a_ptrdiff
; break;
849 #endif /*HAVE_LONG_LONG_INT*/
857 else if ((arg
->flags
& FLAG_PLUS_SIGN
))
859 else if ((arg
->flags
& FLAG_SPACE_PLUS
))
862 n_extra
= !!signchar
;
864 /* We build the string up backwards. */
865 p
= pend
= numbuf
+ DIM(numbuf
);
866 if ((!aulong
&& !arg
->precision
))
868 else if (arg
->conspec
== CONSPEC_DECIMAL
869 || arg
->conspec
== CONSPEC_UNSIGNED
)
872 const char * grouping_string
=
873 #ifdef HAVE_LANGINFO_THOUSANDS_SEP
874 nl_langinfo(THOUSANDS_SEP
);
881 if ((arg
->flags
& FLAG_GROUPING
)
882 && (++grouping
== 3) && *grouping_string
)
884 *--p
= *grouping_string
;
887 *--p
= '0' + (aulong
% 10);
892 else if (arg
->conspec
== CONSPEC_OCTAL
)
896 *--p
= '0' + (aulong
% 8);
900 if ((arg
->flags
& FLAG_ALT_CONV
) && *p
!= '0')
903 else /* HEX or HEXUP */
905 const char *digits
= ((arg
->conspec
== CONSPEC_HEX
)
906 ? "0123456789abcdef" : "0123456789ABCDEF");
909 *--p
= digits
[(aulong
% 16)];
913 if ((arg
->flags
& FLAG_ALT_CONV
))
919 if ((arg
->flags
& FLAG_ZERO_PAD
)
920 && arg
->precision
== NO_FIELD_VALUE
&& !(arg
->flags
& FLAG_LEFT_JUST
)
921 && n
&& arg
->width
- n_extra
> n
)
922 n_prec
= arg
->width
- n_extra
- n
;
923 else if (arg
->precision
> 0 && arg
->precision
> n
)
924 n_prec
= arg
->precision
- n
;
928 if (!(arg
->flags
& FLAG_LEFT_JUST
)
929 && arg
->width
>= 0 && arg
->width
- n_extra
> n
930 && arg
->width
- n_extra
- n
>= n_prec
)
932 rc
= pad_out (outfnc
, outfncarg
, ' ',
933 arg
->width
- n_extra
- n
- n_prec
, nbytes
);
940 rc
= outfnc (outfncarg
, &signchar
, 1);
946 if ((arg
->flags
& FLAG_ALT_CONV
)
947 && (arg
->conspec
== CONSPEC_HEX
|| arg
->conspec
== CONSPEC_HEX_UP
))
949 rc
= outfnc (outfncarg
, arg
->conspec
== CONSPEC_HEX
? "0x": "0X", 2);
957 rc
= pad_out (outfnc
, outfncarg
, '0', n_prec
, nbytes
);
962 rc
= outfnc (outfncarg
, p
, pend
- p
);
967 if ((arg
->flags
& FLAG_LEFT_JUST
)
968 && arg
->width
>= 0 && arg
->width
- n_extra
- n_prec
> n
)
970 rc
= pad_out (outfnc
, outfncarg
, ' ',
971 arg
->width
- n_extra
- n_prec
- n
, nbytes
);
980 /* "e,E,f,F,g,G,a,A" formatting. OUTFNC and OUTFNCARG describes the
981 output routine, ARG gives the argument description and VALUE the
982 actual value (its type is available through arg->vt). For
983 portability reasons sprintf is used for the actual formatting.
984 This is useful because sprint is the only standard function to
985 convert a floating number into its ascii representation. To avoid
986 using malloc we just pass the precision to sprintf and do the final
987 formatting with our own code. */
989 pr_float (estream_printf_out_t outfnc
, void *outfncarg
,
990 argspec_t arg
, value_t value
, size_t *nbytes
)
993 #ifdef HAVE_LONG_DOUBLE
994 long double adblfloat
= 0; /* Just to please gcc. */
1003 int n_extra
; /* Extra number of prefix or sign characters. */
1007 case VALTYPE_DOUBLE
: afloat
= value
.a_double
; break;
1008 #ifdef HAVE_LONG_DOUBLE
1009 case VALTYPE_LONGDOUBLE
:
1010 afloat
= 0; /* Just to please gcc. */
1011 adblfloat
= value
.a_longdouble
;
1018 /* We build the string using sprint. */
1019 p
= formatstr
+ sizeof formatstr
;
1021 switch (arg
->conspec
)
1023 case CONSPEC_FLOAT
: *--p
= 'f'; break;
1024 case CONSPEC_FLOAT_UP
: *--p
= 'F'; break;
1025 case CONSPEC_EXP
: *--p
= 'e'; break;
1026 case CONSPEC_EXP_UP
: *--p
= 'E'; break;
1027 case CONSPEC_F_OR_G
: *--p
= 'g'; break;
1028 case CONSPEC_F_OR_G_UP
: *--p
= 'G'; break;
1029 case CONSPEC_HEX_EXP
: *--p
= 'a'; break;
1030 case CONSPEC_HEX_EXP_UP
: *--p
= 'A'; break;
1032 return -1; /* Actually a bug. */
1034 #ifdef HAVE_LONG_DOUBLE
1038 if (arg
->precision
!= NO_FIELD_VALUE
)
1040 /* Limit it to a meaningful value so that even a stupid sprintf
1041 won't overflow our buffer. */
1042 n
= arg
->precision
<= 100? arg
->precision
: 100;
1045 *--p
= '0' + (n
% 10);
1051 if ((arg
->flags
& FLAG_ALT_CONV
))
1054 #ifdef HAVE_LONG_DOUBLE
1056 sprintf (numbuf
, p
, adblfloat
);
1058 #endif /*HAVE_LONG_DOUBLE*/
1059 sprintf (numbuf
, p
, afloat
);
1061 n
= strlen (numbuf
);
1070 else if ((arg
->flags
& FLAG_PLUS_SIGN
))
1072 else if ((arg
->flags
& FLAG_SPACE_PLUS
))
1075 n_extra
= !!signchar
;
1077 if (!(arg
->flags
& FLAG_LEFT_JUST
)
1078 && arg
->width
>= 0 && arg
->width
- n_extra
> n
)
1080 rc
= pad_out (outfnc
, outfncarg
, ' ', arg
->width
- n_extra
- n
, nbytes
);
1087 rc
= outfnc (outfncarg
, &signchar
, 1);
1093 rc
= outfnc (outfncarg
, p
, pend
- p
);
1096 *nbytes
+= pend
- p
;
1098 if ((arg
->flags
& FLAG_LEFT_JUST
)
1099 && arg
->width
>= 0 && arg
->width
- n_extra
> n
)
1101 rc
= pad_out (outfnc
, outfncarg
, ' ', arg
->width
- n_extra
- n
, nbytes
);
1110 /* "c" formatting. */
1112 pr_char (estream_printf_out_t outfnc
, void *outfncarg
,
1113 argspec_t arg
, value_t value
, size_t *nbytes
)
1118 if (arg
->vt
!= VALTYPE_INT
)
1120 buf
[0] = (unsigned int)value
.a_int
;
1121 rc
= outfnc (outfncarg
, buf
, 1);
1130 /* "s" formatting. */
1132 pr_string (estream_printf_out_t outfnc
, void *outfncarg
,
1133 argspec_t arg
, value_t value
, size_t *nbytes
)
1137 const char *string
, *s
;
1139 if (arg
->vt
!= VALTYPE_STRING
)
1141 string
= value
.a_string
;
1144 if (arg
->precision
>= 0)
1146 for (n
=0,s
=string
; *s
&& n
< arg
->precision
; s
++)
1150 n
= strlen (string
);
1152 if (!(arg
->flags
& FLAG_LEFT_JUST
)
1153 && arg
->width
>= 0 && arg
->width
> n
)
1155 rc
= pad_out (outfnc
, outfncarg
, ' ', arg
->width
- n
, nbytes
);
1160 rc
= outfnc (outfncarg
, string
, n
);
1165 if ((arg
->flags
& FLAG_LEFT_JUST
)
1166 && arg
->width
>= 0 && arg
->width
> n
)
1168 rc
= pad_out (outfnc
, outfncarg
, ' ', arg
->width
- n
, nbytes
);
1177 /* "p" formatting. */
1179 pr_pointer (estream_printf_out_t outfnc
, void *outfncarg
,
1180 argspec_t arg
, value_t value
, size_t *nbytes
)
1183 #ifdef HAVE_LONG_LONG_INT
1184 unsigned long long aulong
;
1186 unsigned long aulong
;
1191 if (arg
->vt
!= VALTYPE_POINTER
)
1193 /* We assume that a pointer can be converted to an unsigned long.
1194 That is not correct for a 64 bit Windows, but then we assume that
1195 long long is supported and usable for storing a pointer. */
1196 #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P)
1197 aulong
= (unsigned long long)value
.a_void_ptr
;
1199 aulong
= (unsigned long)value
.a_void_ptr
;
1202 p
= pend
= numbuf
+ DIM(numbuf
);
1205 *--p
= "0123456789abcdefx"[(aulong
% 16)];
1209 while ((pend
-p
) < 2*sizeof (aulong
))
1214 rc
= outfnc (outfncarg
, p
, pend
- p
);
1217 *nbytes
+= pend
- p
;
1222 /* "n" pesudo format operation. */
1224 pr_bytes_so_far (estream_printf_out_t outfnc
, void *outfncarg
,
1225 argspec_t arg
, value_t value
, size_t *nbytes
)
1232 case VALTYPE_SCHAR_PTR
:
1233 *value
.a_schar_ptr
= (signed char)(unsigned int)(*nbytes
);
1235 case VALTYPE_SHORT_PTR
:
1236 *value
.a_short_ptr
= (short)(unsigned int)(*nbytes
);
1238 case VALTYPE_LONG_PTR
:
1239 *value
.a_long_ptr
= (long)(*nbytes
);
1241 #ifdef HAVE_LONG_LONG_INT
1242 case VALTYPE_LONGLONG_PTR
:
1243 *value
.a_longlong_ptr
= (long long)(*nbytes
);
1246 #ifdef HAVE_INTMAX_T
1247 case VALTYPE_INTMAX_PTR
:
1248 *value
.a_intmax_ptr
= (intmax_t)(*nbytes
);
1251 case VALTYPE_SIZE_PTR
:
1252 *value
.a_size_ptr
= (*nbytes
);
1254 #ifdef HAVE_PTRDIFF_T
1255 case VALTYPE_PTRDIFF_PTR
:
1256 *value
.a_ptrdiff_ptr
= (ptrdiff_t)(*nbytes
);
1259 case VALTYPE_INT_PTR
:
1260 *value
.a_int_ptr
= (int)(*nbytes
);
1263 return -1; /* An unsupported type has been used. */
1271 /* Run the actual formatting. OUTFNC and OUTFNCARG are the output
1272 functions. FORMAT is format string ARGSPECS is the parsed format
1273 string, ARGSPECS_LEN the number of items in ARGSPECS. VALUETABLE
1274 holds the values and may be directly addressed using the position
1275 arguments given by ARGSPECS. MYERRNO is used for the "%m"
1276 conversion. NBYTES well be updated to reflect the number of bytes
1277 send to the output function. */
1279 do_format (estream_printf_out_t outfnc
, void *outfncarg
,
1280 const char *format
, argspec_t argspecs
, size_t argspecs_len
,
1281 valueitem_t valuetable
, int myerrno
, size_t *nbytes
)
1285 argspec_t arg
= argspecs
;
1286 int argidx
= 0; /* Only used for assertion. */
1300 rc
= outfnc (outfncarg
, format
, (n
=s
-format
));
1307 /* Note that this code ignores one trailing percent escape -
1308 this is however okay as the args parser must have
1309 detected this already. */
1310 rc
= outfnc (outfncarg
, s
, 1);
1319 /* Save the next start. */
1323 assert (argidx
< argspecs_len
);
1326 /* Apply indirect field width and precision values. */
1327 if (arg
->width
== STAR_FIELD_VALUE
)
1329 assert (valuetable
[arg
->width_pos
-1].vt
== VALTYPE_INT
);
1330 arg
->width
= valuetable
[arg
->width_pos
-1].value
.a_int
;
1333 arg
->width
= -arg
->width
;
1334 arg
->flags
|= FLAG_LEFT_JUST
;
1337 if (arg
->precision
== STAR_FIELD_VALUE
)
1339 assert (valuetable
[arg
->precision_pos
-1].vt
== VALTYPE_INT
);
1340 arg
->precision
= valuetable
[arg
->precision_pos
-1].value
.a_int
;
1341 if (arg
->precision
< 0)
1342 arg
->precision
= NO_FIELD_VALUE
;
1345 if (arg
->arg_pos
== -1 && arg
->conspec
== CONSPEC_STRERROR
)
1346 value
.a_string
= strerror (myerrno
);
1349 assert (arg
->vt
== valuetable
[arg
->arg_pos
-1].vt
);
1350 value
= valuetable
[arg
->arg_pos
-1].value
;
1353 switch (arg
->conspec
)
1355 case CONSPEC_UNKNOWN
: assert (!"bug"); break;
1357 case CONSPEC_DECIMAL
:
1358 case CONSPEC_UNSIGNED
:
1361 case CONSPEC_HEX_UP
:
1362 rc
= pr_integer (outfnc
, outfncarg
, arg
, value
, nbytes
);
1365 case CONSPEC_FLOAT_UP
:
1367 case CONSPEC_EXP_UP
:
1368 case CONSPEC_F_OR_G
:
1369 case CONSPEC_F_OR_G_UP
:
1370 case CONSPEC_HEX_EXP
:
1371 case CONSPEC_HEX_EXP_UP
:
1372 rc
= pr_float (outfnc
, outfncarg
, arg
, value
, nbytes
);
1375 rc
= pr_char (outfnc
, outfncarg
, arg
, value
, nbytes
);
1377 case CONSPEC_STRING
:
1378 case CONSPEC_STRERROR
:
1379 rc
= pr_string (outfnc
, outfncarg
, arg
, value
, nbytes
);
1381 case CONSPEC_POINTER
:
1382 rc
= pr_pointer (outfnc
, outfncarg
, arg
, value
, nbytes
);
1384 case CONSPEC_BYTES_SO_FAR
:
1385 rc
= pr_bytes_so_far (outfnc
, outfncarg
, arg
, value
, nbytes
);
1393 /* Print out any trailing stuff. */
1395 rc
= n
? outfnc (outfncarg
, format
, n
) : 0;
1405 /* The versatile printf formatting routine. It expects a callback
1406 function OUTFNC and an opaque argument OUTFNCARG used for actual
1407 output of the formatted stuff. FORMAT is the format specification
1408 and VAARGS a variable argumemt list matching the arguments of
1411 estream_format (estream_printf_out_t outfnc
,
1413 const char *format
, va_list vaargs
)
1415 /* Buffer to hold the argspecs and a pointer to it.*/
1416 struct argspec_s argspecs_buffer
[DEFAULT_MAX_ARGSPECS
];
1417 argspec_t argspecs
= argspecs_buffer
;
1418 size_t argspecs_len
; /* Number of specifications in ARGSPECS. */
1420 /* Buffer to hold the description for the values. */
1421 struct valueitem_s valuetable_buffer
[DEFAULT_MAX_VALUES
];
1422 valueitem_t valuetable
= valuetable_buffer
;
1424 int rc
; /* Return code. */
1425 size_t argidx
; /* Used to index the argspecs array. */
1426 size_t validx
; /* Used to index the valuetable. */
1427 int max_pos
;/* Highest argument position. */
1429 size_t nbytes
= 0; /* Keep track of the number of bytes passed to
1430 the output function. */
1432 int myerrno
= errno
; /* Save the errno for use with "%m". */
1435 /* Parse the arguments to come up with descriptive list. We can't
1436 do this on the fly because we need to support positional
1438 rc
= parse_format (format
, &argspecs
, DIM(argspecs_buffer
), &argspecs_len
);
1442 /* Check that all ARG_POS fields are set. */
1443 for (argidx
=0,max_pos
=0; argidx
< argspecs_len
; argidx
++)
1445 if (argspecs
[argidx
].arg_pos
!= -1
1446 && argspecs
[argidx
].arg_pos
> max_pos
)
1447 max_pos
= argspecs
[argidx
].arg_pos
;
1448 if (argspecs
[argidx
].width_pos
> max_pos
)
1449 max_pos
= argspecs
[argidx
].width_pos
;
1450 if (argspecs
[argidx
].precision_pos
> max_pos
)
1451 max_pos
= argspecs
[argidx
].precision_pos
;
1455 /* Fill in all the positions. */
1456 for (argidx
=0; argidx
< argspecs_len
; argidx
++)
1458 if (argspecs
[argidx
].width
== STAR_FIELD_VALUE
)
1459 argspecs
[argidx
].width_pos
= ++max_pos
;
1460 if (argspecs
[argidx
].precision
== STAR_FIELD_VALUE
)
1461 argspecs
[argidx
].precision_pos
= ++max_pos
;
1462 if (argspecs
[argidx
].arg_pos
!= -1 )
1463 argspecs
[argidx
].arg_pos
= ++max_pos
;
1468 /* Check that they are all filled. More test are done later. */
1469 for (argidx
=0; argidx
< argspecs_len
; argidx
++)
1471 if (!argspecs
[argidx
].arg_pos
1472 || (argspecs
[argidx
].width
== STAR_FIELD_VALUE
1473 && !argspecs
[argidx
].width_pos
)
1474 || (argspecs
[argidx
].precision
== STAR_FIELD_VALUE
1475 && !argspecs
[argidx
].precision_pos
))
1479 /* Check that there is no overflow in max_pos and that it has a
1480 reasonable length. There may never be more elements than the
1481 number of characters in FORMAT. */
1482 if (max_pos
< 0 || max_pos
>= strlen (format
))
1486 dump_argspecs (argspecs
, argspecs_len
);
1489 /* Allocate a table to hold the values. If it is small enough we
1490 use a stack allocated buffer. */
1491 if (max_pos
> DIM(valuetable_buffer
))
1493 valuetable
= calloc (max_pos
, sizeof *valuetable
);
1499 for (validx
=0; validx
< DIM(valuetable_buffer
); validx
++)
1500 valuetable
[validx
].vt
= VALTYPE_UNSUPPORTED
;
1502 for (argidx
=0; argidx
< argspecs_len
; argidx
++)
1504 if (argspecs
[argidx
].arg_pos
!= - 1)
1506 validx
= argspecs
[argidx
].arg_pos
- 1;
1507 if (valuetable
[validx
].vt
)
1508 goto leave_einval
; /* Already defined. */
1509 valuetable
[validx
].vt
= argspecs
[argidx
].vt
;
1511 if (argspecs
[argidx
].width
== STAR_FIELD_VALUE
)
1513 validx
= argspecs
[argidx
].width_pos
- 1;
1514 if (valuetable
[validx
].vt
)
1515 goto leave_einval
; /* Already defined. */
1516 valuetable
[validx
].vt
= VALTYPE_INT
;
1518 if (argspecs
[argidx
].precision
== STAR_FIELD_VALUE
)
1520 validx
= argspecs
[argidx
].precision_pos
- 1;
1521 if (valuetable
[validx
].vt
)
1522 goto leave_einval
; /* Already defined. */
1523 valuetable
[validx
].vt
= VALTYPE_INT
;
1527 /* Read all the arguments. This will error out for unsupported
1528 types and for not given positional arguments. */
1529 rc
= read_values (valuetable
, max_pos
, vaargs
);
1533 /* for (validx=0; validx < max_pos; validx++) */
1534 /* fprintf (stderr, "%2d: vt=%d\n", validx, valuetable[validx].vt); */
1536 /* Everything has been collected, go ahead with the formatting. */
1537 rc
= do_format (outfnc
, outfncarg
, format
,
1538 argspecs
, argspecs_len
, valuetable
, myerrno
, &nbytes
);
1547 if (valuetable
!= valuetable_buffer
)
1549 if (argspecs
!= argspecs_buffer
)
1557 /* A simple output handler utilizing stdio. */
1559 plain_stdio_out (void *outfncarg
, const char *buf
, size_t buflen
)
1561 FILE *fp
= (FILE*)outfncarg
;
1563 if ( fwrite (buf
, buflen
, 1, fp
) != 1 )
1569 /* A replacement for printf. */
1571 estream_printf (const char *format
, ...)
1576 va_start (arg_ptr
, format
);
1577 rc
= estream_format (plain_stdio_out
, stderr
, format
, arg_ptr
);
1583 /* A replacement for fprintf. */
1585 estream_fprintf (FILE *fp
, const char *format
, ...)
1590 va_start (arg_ptr
, format
);
1591 rc
= estream_format (plain_stdio_out
, fp
, format
, arg_ptr
);
1597 /* A replacement for vfprintf. */
1599 estream_vfprintf (FILE *fp
, const char *format
, va_list arg_ptr
)
1601 return estream_format (plain_stdio_out
, fp
, format
, arg_ptr
);
1606 /* Communication object used between estream_snprintf and
1607 fixed_buffer_out. */
1608 struct fixed_buffer_parm_s
1610 size_t size
; /* Size of the buffer. */
1611 size_t count
; /* Number of bytes requested for output. */
1612 size_t used
; /* Used size of the buffer. */
1613 char *buffer
; /* Provided buffer. */
1616 /* A simple malloced buffer output handler. */
1618 fixed_buffer_out (void *outfncarg
, const char *buf
, size_t buflen
)
1620 struct fixed_buffer_parm_s
*parm
= outfncarg
;
1622 parm
->count
+= buflen
;
1626 else if (parm
->used
+ buflen
< parm
->size
)
1628 /* Handle the common case that everything fits into the buffer
1630 memcpy (parm
->buffer
+ parm
->used
, buf
, buflen
);
1631 parm
->used
+= buflen
;
1635 /* The slow version of above. */
1636 for ( ;buflen
&& parm
->used
< parm
->size
; buflen
--)
1637 parm
->buffer
[parm
->used
++] = *buf
++;
1644 /* A replacement for vsnprintf. */
1646 estream_vsnprintf (char *buf
, size_t bufsize
,
1647 const char *format
, va_list arg_ptr
)
1649 struct fixed_buffer_parm_s parm
;
1652 parm
.size
= bufsize
;
1655 parm
.buffer
= bufsize
?buf
:NULL
;
1656 rc
= estream_format (fixed_buffer_out
, &parm
, format
, arg_ptr
);
1658 rc
= fixed_buffer_out (&parm
, "", 1); /* Print terminating Nul. */
1661 if (bufsize
&& buf
&& parm
.size
&& parm
.count
>= parm
.size
)
1662 buf
[parm
.size
-1] = 0;
1664 parm
.count
--; /* Do not count the trailing nul. */
1665 return (int)parm
.count
; /* Return number of bytes which would have
1669 /* A replacement for snprintf. */
1671 estream_snprintf (char *buf
, size_t bufsize
, const char *format
, ...)
1676 va_start (arg_ptr
, format
);
1677 rc
= estream_vsnprintf (buf
, bufsize
, format
, arg_ptr
);
1685 /* Communication object used between estream_asprintf and
1686 dynamic_buffer_out. */
1687 struct dynamic_buffer_parm_s
1689 int error_flag
; /* Internal helper. */
1690 size_t alloced
; /* Allocated size of the buffer. */
1691 size_t used
; /* Used size of the buffer. */
1692 char *buffer
; /* Malloced buffer. */
1695 /* A simple malloced buffer output handler. */
1697 dynamic_buffer_out (void *outfncarg
, const char *buf
, size_t buflen
)
1699 struct dynamic_buffer_parm_s
*parm
= outfncarg
;
1701 if (parm
->error_flag
)
1703 /* Just in case some formatting routine did not checked for an
1705 errno
= parm
->error_flag
;
1709 if (parm
->used
+ buflen
>= parm
->alloced
)
1713 parm
->alloced
+= buflen
+ 512;
1714 p
= realloc (parm
->buffer
, parm
->alloced
);
1717 parm
->error_flag
= errno
? errno
: ENOMEM
;
1718 /* Wipe out what we already accumulated. This is useful in
1719 case sensitive data is formated. */
1720 memset (parm
->buffer
, 0, parm
->used
);
1725 memcpy (parm
->buffer
+ parm
->used
, buf
, buflen
);
1726 parm
->used
+= buflen
;
1732 /* A replacement for vasprintf. As with the BSD of vasprintf version -1
1733 will be returned on error and NULL stored at BUFP. On success the
1734 number of bytes printed will be returned. */
1736 estream_vasprintf (char **bufp
, const char *format
, va_list arg_ptr
)
1738 struct dynamic_buffer_parm_s parm
;
1741 parm
.error_flag
= 0;
1744 parm
.buffer
= my_printf_malloc (parm
.alloced
);
1751 rc
= estream_format (dynamic_buffer_out
, &parm
, format
, arg_ptr
);
1753 rc
= dynamic_buffer_out (&parm
, "", 1); /* Print terminating Nul. */
1754 /* Fixme: Should we shrink the resulting buffer? */
1755 if (rc
!= -1 && parm
.error_flag
)
1758 errno
= parm
.error_flag
;
1762 memset (parm
.buffer
, 0, parm
.used
);
1763 my_printf_free (parm
.buffer
);
1767 assert (parm
.used
); /* We have at least the terminating Nul. */
1768 *bufp
= parm
.buffer
;
1769 return parm
.used
- 1; /* Do not include that Nul. */
1772 /* A replacement for asprintf. As with the BSD of asprintf version -1
1773 will be returned on error and NULL stored at BUFP. On success the
1774 number of bytes printed will be returned. */
1776 estream_asprintf (char **bufp
, const char *format
, ...)
1781 va_start (arg_ptr
, format
);
1782 rc
= estream_vasprintf (bufp
, format
, arg_ptr
);