1 /* estream-printf.c - Versatile C-99 compliant printf formatting
2 * Copyright (C) 2007, 2008 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.
51 #if defined(HAVE_INTMAX_T) || defined(HAVE_UINTMAX_T)
54 #ifdef HAVE_LANGINFO_THOUSANDS_SEP
60 # ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE
61 # include _ESTREAM_PRINTF_EXTRA_INCLUDE
64 #include "estream-printf.h"
66 /* Allow redefinition of asprintf used malloc functions. */
67 #if defined(_ESTREAM_PRINTF_MALLOC) && !defined(TEST)
68 #define my_printf_malloc(a) _ESTREAM_PRINTF_MALLOC((a))
70 #define my_printf_malloc(a) malloc((a))
72 #if defined(_ESTREAM_PRINTF_FREE) && !defined(TEST)
73 #define my_printf_free(a) _ESTREAM_PRINTF_FREE((a))
75 #define my_printf_free(a) free((a))
79 /* Calculate array dimension. */
81 #define DIM(array) (sizeof (array) / sizeof (*array))
85 /* We allow for that many args without requiring malloced memory. */
86 #define DEFAULT_MAX_ARGSPECS 5
88 /* We allow for that many values without requiring malloced memory. */
89 #define DEFAULT_MAX_VALUES 8
91 /* We allocate this many new array argspec elements each time. */
92 #define ARGSPECS_BUMP_VALUE 10
94 /* Special values for the field width and the precision. */
95 #define NO_FIELD_VALUE (-1)
96 #define STAR_FIELD_VALUE (-2)
98 /* Bit valuues used for the conversion flags. */
99 #define FLAG_GROUPING 1
100 #define FLAG_LEFT_JUST 2
101 #define FLAG_PLUS_SIGN 4
102 #define FLAG_SPACE_PLUS 8
103 #define FLAG_ALT_CONV 16
104 #define FLAG_ZERO_PAD 32
106 /* Constants used the length modifiers. */
110 LENMOD_CHAR
, /* "hh" */
111 LENMOD_SHORT
, /* "h" */
112 LENMOD_LONG
, /* "l" */
113 LENMOD_LONGLONG
, /* "ll" */
114 LENMOD_INTMAX
, /* "j" */
115 LENMOD_SIZET
, /* "z" */
116 LENMOD_PTRDIFF
, /* "t" */
117 LENMOD_LONGDBL
/* "L" */
120 /* All the conversion specifiers. */
145 /* Constants describing all the suppoorted types. Note that we list
146 all the types we know about even if certain types are not available
150 VALTYPE_UNSUPPORTED
= 0, /* Artificial type for error detection. */
175 VALTYPE_LONGLONG_PTR
,
182 /* A union used to store the actual values. */
187 unsigned char a_uchar
;
189 unsigned short a_ushort
;
193 unsigned long int a_ulong
;
194 #ifdef HAVE_LONG_LONG_INT
195 long long int a_longlong
;
196 unsigned long long int a_ulonglong
;
199 #ifdef HAVE_LONG_DOUBLE
200 long double a_longdouble
;
202 const char *a_string
;
206 #ifdef HAVE_UINTMAX_T
210 #ifdef HAVE_PTRDIFF_T
215 signed char *a_schar_ptr
;
219 #ifdef HAVE_LONG_LONG_INT
220 long long int *a_longlong_ptr
;
223 intmax_t *a_intmax_ptr
;
226 #ifdef HAVE_PTRDIFF_T
227 ptrdiff_t *a_ptrdiff_ptr
;
231 /* An object used to keep track of a format option and arguments. */
234 size_t length
; /* The length of these args including the percent. */
235 unsigned int flags
; /* The conversion flags (bits defined by FLAG_foo). */
236 int width
; /* The field width. */
237 int precision
; /* The precision. */
238 lenmod_t lenmod
; /* The length modifier. */
239 conspec_t conspec
; /* The conversion specifier. */
240 int arg_pos
; /* The position of the argument. This one may
241 be -1 to indicate that no value is expected
243 int width_pos
; /* The position of the argument for a field
244 width star's value. 0 for not used. */
245 int precision_pos
; /* The position of the argument for the a
246 precision star's value. 0 for not used. */
247 valtype_t vt
; /* The type of the corresponding argument. */
249 typedef struct argspec_s
*argspec_t
;
251 /* An object to build up a table of values and their types. */
254 valtype_t vt
; /* The type of the value. */
255 value_t value
; /* The value. */
257 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
))
1487 dump_argspecs (argspecs
, argspecs_len
);
1490 /* Allocate a table to hold the values. If it is small enough we
1491 use a stack allocated buffer. */
1492 if (max_pos
> DIM(valuetable_buffer
))
1494 valuetable
= calloc (max_pos
, sizeof *valuetable
);
1500 for (validx
=0; validx
< DIM(valuetable_buffer
); validx
++)
1501 valuetable
[validx
].vt
= VALTYPE_UNSUPPORTED
;
1503 for (argidx
=0; argidx
< argspecs_len
; argidx
++)
1505 if (argspecs
[argidx
].arg_pos
!= - 1)
1507 validx
= argspecs
[argidx
].arg_pos
- 1;
1508 if (valuetable
[validx
].vt
)
1509 goto leave_einval
; /* Already defined. */
1510 valuetable
[validx
].vt
= argspecs
[argidx
].vt
;
1512 if (argspecs
[argidx
].width
== STAR_FIELD_VALUE
)
1514 validx
= argspecs
[argidx
].width_pos
- 1;
1515 if (valuetable
[validx
].vt
)
1516 goto leave_einval
; /* Already defined. */
1517 valuetable
[validx
].vt
= VALTYPE_INT
;
1519 if (argspecs
[argidx
].precision
== STAR_FIELD_VALUE
)
1521 validx
= argspecs
[argidx
].precision_pos
- 1;
1522 if (valuetable
[validx
].vt
)
1523 goto leave_einval
; /* Already defined. */
1524 valuetable
[validx
].vt
= VALTYPE_INT
;
1528 /* Read all the arguments. This will error out for unsupported
1529 types and for not given positional arguments. */
1530 rc
= read_values (valuetable
, max_pos
, vaargs
);
1534 /* for (validx=0; validx < max_pos; validx++) */
1535 /* fprintf (stderr, "%2d: vt=%d\n", validx, valuetable[validx].vt); */
1537 /* Everything has been collected, go ahead with the formatting. */
1538 rc
= do_format (outfnc
, outfncarg
, format
,
1539 argspecs
, argspecs_len
, valuetable
, myerrno
, &nbytes
);
1548 if (valuetable
!= valuetable_buffer
)
1550 if (argspecs
!= argspecs_buffer
)
1558 /* A simple output handler utilizing stdio. */
1560 plain_stdio_out (void *outfncarg
, const char *buf
, size_t buflen
)
1562 FILE *fp
= (FILE*)outfncarg
;
1564 if ( fwrite (buf
, buflen
, 1, fp
) != 1 )
1570 /* A replacement for printf. */
1572 estream_printf (const char *format
, ...)
1577 va_start (arg_ptr
, format
);
1578 rc
= estream_format (plain_stdio_out
, stderr
, format
, arg_ptr
);
1584 /* A replacement for fprintf. */
1586 estream_fprintf (FILE *fp
, const char *format
, ...)
1591 va_start (arg_ptr
, format
);
1592 rc
= estream_format (plain_stdio_out
, fp
, format
, arg_ptr
);
1598 /* A replacement for vfprintf. */
1600 estream_vfprintf (FILE *fp
, const char *format
, va_list arg_ptr
)
1602 return estream_format (plain_stdio_out
, fp
, format
, arg_ptr
);
1607 /* Communication object used between estream_snprintf and
1608 fixed_buffer_out. */
1609 struct fixed_buffer_parm_s
1611 size_t size
; /* Size of the buffer. */
1612 size_t count
; /* Number of bytes requested for output. */
1613 size_t used
; /* Used size of the buffer. */
1614 char *buffer
; /* Provided buffer. */
1617 /* A simple malloced buffer output handler. */
1619 fixed_buffer_out (void *outfncarg
, const char *buf
, size_t buflen
)
1621 struct fixed_buffer_parm_s
*parm
= outfncarg
;
1623 parm
->count
+= buflen
;
1627 else if (parm
->used
+ buflen
< parm
->size
)
1629 /* Handle the common case that everything fits into the buffer
1631 memcpy (parm
->buffer
+ parm
->used
, buf
, buflen
);
1632 parm
->used
+= buflen
;
1636 /* The slow version of above. */
1637 for ( ;buflen
&& parm
->used
< parm
->size
; buflen
--)
1638 parm
->buffer
[parm
->used
++] = *buf
++;
1645 /* A replacement for vsnprintf. */
1647 estream_vsnprintf (char *buf
, size_t bufsize
,
1648 const char *format
, va_list arg_ptr
)
1650 struct fixed_buffer_parm_s parm
;
1653 parm
.size
= bufsize
;
1656 parm
.buffer
= bufsize
?buf
:NULL
;
1657 rc
= estream_format (fixed_buffer_out
, &parm
, format
, arg_ptr
);
1659 rc
= fixed_buffer_out (&parm
, "", 1); /* Print terminating Nul. */
1662 if (bufsize
&& buf
&& parm
.size
&& parm
.count
>= parm
.size
)
1663 buf
[parm
.size
-1] = 0;
1665 parm
.count
--; /* Do not count the trailing nul. */
1666 return (int)parm
.count
; /* Return number of bytes which would have
1670 /* A replacement for snprintf. */
1672 estream_snprintf (char *buf
, size_t bufsize
, const char *format
, ...)
1677 va_start (arg_ptr
, format
);
1678 rc
= estream_vsnprintf (buf
, bufsize
, format
, arg_ptr
);
1686 /* Communication object used between estream_asprintf and
1687 dynamic_buffer_out. */
1688 struct dynamic_buffer_parm_s
1690 int error_flag
; /* Internal helper. */
1691 size_t alloced
; /* Allocated size of the buffer. */
1692 size_t used
; /* Used size of the buffer. */
1693 char *buffer
; /* Malloced buffer. */
1696 /* A simple malloced buffer output handler. */
1698 dynamic_buffer_out (void *outfncarg
, const char *buf
, size_t buflen
)
1700 struct dynamic_buffer_parm_s
*parm
= outfncarg
;
1702 if (parm
->error_flag
)
1704 /* Just in case some formatting routine did not checked for an
1706 errno
= parm
->error_flag
;
1710 if (parm
->used
+ buflen
>= parm
->alloced
)
1714 parm
->alloced
+= buflen
+ 512;
1715 p
= realloc (parm
->buffer
, parm
->alloced
);
1718 parm
->error_flag
= errno
? errno
: ENOMEM
;
1719 /* Wipe out what we already accumulated. This is useful in
1720 case sensitive data is formated. */
1721 memset (parm
->buffer
, 0, parm
->used
);
1726 memcpy (parm
->buffer
+ parm
->used
, buf
, buflen
);
1727 parm
->used
+= buflen
;
1733 /* A replacement for vasprintf. As with the BSD of vasprintf version -1
1734 will be returned on error and NULL stored at BUFP. On success the
1735 number of bytes printed will be returned. */
1737 estream_vasprintf (char **bufp
, const char *format
, va_list arg_ptr
)
1739 struct dynamic_buffer_parm_s parm
;
1742 parm
.error_flag
= 0;
1745 parm
.buffer
= my_printf_malloc (parm
.alloced
);
1752 rc
= estream_format (dynamic_buffer_out
, &parm
, format
, arg_ptr
);
1754 rc
= dynamic_buffer_out (&parm
, "", 1); /* Print terminating Nul. */
1755 /* Fixme: Should we shrink the resulting buffer? */
1756 if (rc
!= -1 && parm
.error_flag
)
1759 errno
= parm
.error_flag
;
1763 memset (parm
.buffer
, 0, parm
.used
);
1764 my_printf_free (parm
.buffer
);
1768 assert (parm
.used
); /* We have at least the terminating Nul. */
1769 *bufp
= parm
.buffer
;
1770 return parm
.used
- 1; /* Do not include that Nul. */
1773 /* A replacement for asprintf. As with the BSD of asprintf version -1
1774 will be returned on error and NULL stored at BUFP. On success the
1775 number of bytes printed will be returned. */
1777 estream_asprintf (char **bufp
, const char *format
, ...)
1782 va_start (arg_ptr
, format
);
1783 rc
= estream_vasprintf (bufp
, format
, arg_ptr
);
1793 one_test (const char *format
, ...)
1801 /* We do not have a system vasprintf. */
1802 printf ("one-test: disabled under W32\n");
1812 printf ("format: ->%s<-\n", format
);
1814 va_start (arg_ptr
, format
);
1815 rc1
= vasprintf (&buf1
, format
, arg_ptr
);
1819 printf (" sys: errno=%d (%s)\n", errno
, strerror (errno
));
1823 printf (" sys: ->%s<-\n", buf1
);
1825 va_start (arg_ptr
, format
);
1826 rc2
= estream_vasprintf (&buf2
, format
, arg_ptr
);
1829 printf (" our: errno=%d (%s)\n", errno
, strerror (errno
));
1831 printf (" our: ->%s<-\n", buf2
);
1833 if (rc1
!= -1 && rc2
!= -1 && strcmp (buf1
, buf2
))
1834 printf ("error: output does not match\n"
1835 "format: ->%s<-\n sys: ->%s<-\n our: ->%s<-\n",
1836 format
, buf1
, buf2
);
1837 else if ( rc1
!= rc2
)
1838 printf ("error: return codes are different: sys_rc=%d our_rc=%d\n",
1851 /*one_test ("%d %% %'d", 17, 19681977);*/
1853 one_test ("%d %% %d", 17, 768114563);
1854 one_test ("%d %% %d", 17, -768114563);
1856 one_test ("%d", 17);
1857 one_test ("%4d", 17);
1858 one_test ("%40d", 17);
1859 one_test ("%-d", 17);
1860 one_test ("%-4d", 17);
1861 one_test ("%-140d", 17);
1862 one_test ("%d", -17);
1863 one_test ("%4d", -17);
1864 one_test ("%40d", -17);
1865 one_test ("%-d", -17);
1866 one_test ("%-4d", -17);
1867 one_test ("%-40d", -17);
1869 one_test ("%+4d", 17);
1870 one_test ("%+4d", -17);
1871 one_test ("%-+4d", 17);
1872 one_test ("%-+4d", -17);
1873 one_test ("% 4d", 17);
1874 one_test ("% 4d", -17);
1875 one_test ("%- +4d", 17);
1876 one_test ("%- +4d", -17);
1878 one_test ("%.4d", 17);
1879 one_test ("%.0d", 17);
1880 one_test ("%.0d", 0);
1881 one_test ("%.4d", -17);
1882 one_test ("%.0d", -17);
1883 one_test ("%6.4d", 17);
1884 one_test ("%6.4d", -17);
1885 one_test ("%6.0d", 0);
1886 one_test ("%4.6d", 17);
1887 one_test ("%4.6d", -17);
1889 one_test ("% 4.6d", 17);
1890 one_test ("% 6.0d", 0);
1892 one_test ("%.4d", 17);
1893 one_test ("%04d", 17);
1894 one_test ("%.4d", -17);
1895 one_test ("%04d", -17);
1896 one_test ("%0.d", 0);
1898 one_test ("%*d", 7, 42);
1899 one_test ("%*d", -7, 42);
1900 one_test ("%.*d", 7, 42);
1901 one_test ("%.*d", -7, 42);
1902 one_test ("%*.*d", 10, 7, 42);
1903 one_test ("%*.*d", 10, -7, 42);
1904 one_test ("%*.*d", -10, 7, 42);
1905 one_test ("%*.*d", -10, -7, 42);
1907 one_test ("%*x", 7, 42);
1908 one_test ("%*x", -7, 42);
1909 one_test ("%.*x", 7, 42);
1910 one_test ("%.*x", -7, 42);
1911 one_test ("%*.*x", 10, 7, 42);
1912 one_test ("%*.*x", 10, -7, 42);
1913 one_test ("%*.*x", -10, 7, 42);
1914 one_test ("%*.*x", -10, -7, 42);
1915 one_test ("%#*x", 7, 42);
1916 one_test ("%#*x", -7, 42);
1917 one_test ("%#.*x", 7, 42);
1918 one_test ("%#.*x", -7, 42);
1919 one_test ("%#*.*x", 10, 7, 42);
1920 one_test ("%#*.*x", 10, -7, 42);
1921 one_test ("%#*.*x", -10, 7, 42);
1922 one_test ("%#*.*x", -10, -7, 42);
1924 one_test ("%*X", 7, 42);
1925 one_test ("%*X", -7, 42);
1926 one_test ("%.*X", 7, 42);
1927 one_test ("%.*X", -7, 42);
1928 one_test ("%*.*X", 10, 7, 42);
1929 one_test ("%*.*X", 10, -7, 42);
1930 one_test ("%*.*X", -10, 7, 42);
1931 one_test ("%*.*X", -10, -7, 42);
1932 one_test ("%#*X", 7, 42);
1933 one_test ("%#*X", -7, 42);
1934 one_test ("%#.*X", 7, 42);
1935 one_test ("%#.*X", -7, 42);
1936 one_test ("%#*.*X", 10, 7, 42);
1937 one_test ("%#*.*X", 10, -7, 42);
1938 one_test ("%#*.*X", -10, 7, 42);
1939 one_test ("%#*.*X", -10, -7, 42);
1941 one_test ("%*o", 7, 42);
1942 one_test ("%*o", -7, 42);
1943 one_test ("%.*o", 7, 42);
1944 one_test ("%.*o", -7, 42);
1945 one_test ("%*.*o", 10, 7, 42);
1946 one_test ("%*.*o", 10, -7, 42);
1947 one_test ("%*.*o", -10, 7, 42);
1948 one_test ("%*.*o", -10, -7, 42);
1949 one_test ("%#*o", 7, 42);
1950 one_test ("%#*o", -7, 42);
1951 one_test ("%#.*o", 7, 42);
1952 one_test ("%#.*o", -7, 42);
1953 one_test ("%#*.*o", 10, 7, 42);
1954 one_test ("%#*.*o", 10, -7, 42);
1955 one_test ("%#*.*o", -10, 7, 42);
1956 one_test ("%#*.*o", -10, -7, 42);
1958 one_test ("%s", "the quick brown fox jumps over the lazy dogs back");
1959 one_test ("%.0s", "the quick brown fox jumps over the lazy dogs back");
1960 one_test ("%.10s", "the quick brown fox jumps over the lazy dogs back");
1961 one_test ("%.48s", "the quick brown fox jumps over the lazy dogs back");
1962 one_test ("%.49s", "the quick brown fox jumps over the lazy dogs back");
1963 one_test ("%.50s", "the quick brown fox jumps over the lazy dogs back");
1964 one_test ("%.51s", "the quick brown fox jumps over the lazy dogs back");
1965 one_test ("%48s", "the quick brown fox jumps over the lazy dogs back");
1966 one_test ("%49s", "the quick brown fox jumps over the lazy dogs back");
1967 one_test ("%50s", "the quick brown fox jumps over the lazy dogs back");
1968 one_test ("%51s", "the quick brown fox jumps over the lazy dogs back");
1969 one_test ("%-51s", "the quick brown fox jumps over the lazy dogs back");
1971 one_test ("/%s=", "CN");
1973 one_test ("%f", 3.1415926535);
1974 one_test ("%f", -3.1415926535);
1975 one_test ("%.10f", 3.1415926535);
1976 one_test ("%.2f", 3.1415926535);
1977 one_test ("%.1f", 3.1415926535);
1978 one_test ("%.0f", 3.1415926535);
1979 one_test ("%.20f", 3.1415926535);
1980 one_test ("%10.10f", 3.1415926535);
1981 one_test ("%10.2f", 3.1415926535);
1982 one_test ("%10.1f", 3.1415926535);
1983 one_test ("%10.0f", 3.1415926535);
1984 one_test ("%30.20f", 3.1415926535);
1985 one_test ("%10.10f", -3.1415926535);
1986 one_test ("%10.2f", -3.1415926535);
1987 one_test ("%10.1f", -3.1415926535);
1988 one_test ("%10.0f", -3.1415926535);
1989 one_test ("%30.20f", -3.1415926535);
1991 one_test ("%-10f", 3.1415926535);
1992 one_test ("%-10.10f", 3.1415926535);
1993 one_test ("%-10.2f", 3.1415926535);
1994 one_test ("%-10.1f", 3.1415926535);
1995 one_test ("%-10.0f", 3.1415926535);
1996 one_test ("%-30.20f", 3.1415926535);
1997 one_test ("%-10f", -3.1415926535);
1998 one_test ("%-10.10f", -3.1415926535);
1999 one_test ("%-10.2f", -3.1415926535);
2000 one_test ("%-10.1f", -3.1415926535);
2001 one_test ("%-10.0f", -3.1415926535);
2002 one_test ("%-30.20f", -3.1415926535);
2004 one_test ("%#.0f", 3.1415926535);
2005 one_test ("%#10.0f", 3.1415926535);
2006 one_test ("%#10.0f", -3.1415926535);
2007 one_test ("%-#10.0f", 3.1415926535);
2008 one_test ("%-#10.0f", -3.1415926535);
2010 one_test ("%e", 3.1415926535);
2011 one_test ("%g", 3.1415926535);
2014 one_test ("%a", -1);
2015 one_test ("%a", 3.1415926535);
2017 #ifdef HAVE_LONG_DOUBLE
2018 one_test ("%La", 1);
2019 one_test ("%La", -1);
2020 one_test ("%La", 3.1415926535);
2024 /* "%m" is a glibc extension so this _test_ will only work on such a
2029 one_test ("%d=%m", 17);
2031 one_test ("%2$d:%m:%1$d", 42, 17);
2032 #endif /*__GLIBC__*/
2037 check_snprintf (void)
2041 size_t tmplen
, blen
, blen2
;
2043 rc
= estream_snprintf (buffer
, 0, "%*s", 18, "");
2045 printf ("rc=%d\n", rc
);
2046 rc
= estream_snprintf (buffer
, sizeof buffer
, "%*s", 18, "");
2048 printf ("rc=%d, strlen(buffer)=%d\n", rc
, (int)strlen (buffer
));
2049 rc
= estream_snprintf (buffer
, sizeof buffer
, "%*s", 19, "");
2051 printf ("rc=%d, strlen(buffer)=%d\n", rc
, (int)strlen (buffer
));
2052 rc
= estream_snprintf (buffer
, sizeof buffer
, "%*s", 20, "");
2054 printf ("rc=%d, strlen(buffer)=%d\n", rc
, (int)strlen (buffer
));
2055 rc
= estream_snprintf (buffer
, sizeof buffer
, "%*s", 21, "");
2057 printf ("rc=%d, strlen(buffer)=%d\n", rc
, (int)strlen (buffer
));
2059 for (tmplen
= 0; tmplen
<= sizeof buffer
; tmplen
++)
2061 rc
= estream_snprintf (buffer
, tmplen
, "%04d%02d%02dT%02d%02d%02d",
2062 1998, 9, 7, 16, 56, 05);
2063 blen
= strlen (buffer
);
2064 rc2
= snprintf (buffer
, tmplen
, "%04d%02d%02dT%02d%02d%02d",
2065 1998, 9, 7, 16, 56, 05);
2066 blen2
= strlen (buffer
);
2067 if (rc
!= rc2
|| blen
!= blen2
)
2068 printf ("snprintf test with len %u gives %d instead of %d (%d,%d)\n",
2069 (unsigned int)tmplen
, rc
, rc2
, blen
, blen2
);
2076 main (int argc
, char **argv
)
2080 if (argc
) {argc
--; argv
++; }
2082 setlocale (LC_NUMERIC
, "");
2084 while (argc
&& !strcmp (*argv
, "--verbose"))
2098 rc
= estream_vfprintf (stdout
, argv
[0], NULL
);
2100 fprintf (stderr
, "[estream_vfprintf returns: %d]\n", rc
);
2108 compile-command: "cc -Wall -O3 -g -I.. -DHAVE_CONFIG_H -DTEST -o estream-printf estream-printf.c"