Obsolete option --no-sig-create-check.
[gnupg.git] / util / estream-printf.c
1 /* estream-printf.c - Versatile C-99 compliant printf formatting
2  * Copyright (C) 2007, 2008, 2009 g10 Code GmbH
3  *
4  * This file is part of Libestream.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 /*  Required autoconf tests:
21
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
30
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.
34
35   Missing stuff:  wchar and wint_t
36                   thousands_sep in pr_float.
37
38 */
39
40 #ifdef HAVE_CONFIG_H
41 # include <config.h>
42 #endif
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <stdarg.h>
49 #include <errno.h>
50 #include <stddef.h>
51 #include <assert.h>
52 #if defined(HAVE_INTMAX_T) || defined(HAVE_UINTMAX_T)
53 # ifdef HAVE_STDINT_H
54 #  include <stdint.h>
55 # endif
56 #endif
57 #ifdef HAVE_LANGINFO_THOUSANDS_SEP
58 #include <langinfo.h>
59 #endif
60 #ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE
61 # include _ESTREAM_PRINTF_EXTRA_INCLUDE
62 #endif
63 #include "estream-printf.h"
64
65 /* #define DEBUG 1 */
66
67
68 /* Allow redefinition of asprintf used malloc functions.  */
69 #if defined(_ESTREAM_PRINTF_MALLOC)
70 #define my_printf_malloc(a) _ESTREAM_PRINTF_MALLOC((a))
71 #else
72 #define my_printf_malloc(a) malloc((a))
73 #endif
74 #if defined(_ESTREAM_PRINTF_FREE)
75 #define my_printf_free(a)   _ESTREAM_PRINTF_FREE((a))
76 #else
77 #define my_printf_free(a)   free((a))
78 #endif
79
80
81 /* Calculate array dimension.  */
82 #ifndef DIM
83 #define DIM(array) (sizeof (array) / sizeof (*array))
84 #endif
85
86
87 /* We allow for that many args without requiring malloced memory. */
88 #define DEFAULT_MAX_ARGSPECS  5
89
90 /* We allow for that many values without requiring malloced memory. */
91 #define DEFAULT_MAX_VALUES  8
92
93 /* We allocate this many new array argspec elements each time.  */
94 #define ARGSPECS_BUMP_VALUE   10
95
96 /* Special values for the field width and the precision.  */
97 #define NO_FIELD_VALUE   (-1)
98 #define STAR_FIELD_VALUE (-2)
99
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
107
108 /* Constants used the length modifiers.  */
109 typedef enum
110   {
111     LENMOD_NONE = 0,
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"  */
120   } lenmod_t;
121
122 /* All the conversion specifiers.  */
123 typedef enum
124   {
125     CONSPEC_UNKNOWN = 0,
126     CONSPEC_DECIMAL,
127     CONSPEC_OCTAL,
128     CONSPEC_UNSIGNED,
129     CONSPEC_HEX,
130     CONSPEC_HEX_UP,
131     CONSPEC_FLOAT,
132     CONSPEC_FLOAT_UP,
133     CONSPEC_EXP,
134     CONSPEC_EXP_UP,
135     CONSPEC_F_OR_G,
136     CONSPEC_F_OR_G_UP,
137     CONSPEC_HEX_EXP,
138     CONSPEC_HEX_EXP_UP,
139     CONSPEC_CHAR,
140     CONSPEC_STRING,
141     CONSPEC_POINTER,
142     CONSPEC_STRERROR,
143     CONSPEC_BYTES_SO_FAR
144   } conspec_t;
145
146
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
149    on this system. */
150 typedef enum
151   {
152     VALTYPE_UNSUPPORTED = 0,  /* Artificial type for error detection.  */
153     VALTYPE_CHAR,
154     VALTYPE_SCHAR,
155     VALTYPE_UCHAR,
156     VALTYPE_SHORT,
157     VALTYPE_USHORT,
158     VALTYPE_INT,
159     VALTYPE_UINT,
160     VALTYPE_LONG,
161     VALTYPE_ULONG,
162     VALTYPE_LONGLONG,
163     VALTYPE_ULONGLONG,
164     VALTYPE_DOUBLE,
165     VALTYPE_LONGDOUBLE,
166     VALTYPE_STRING,
167     VALTYPE_INTMAX,
168     VALTYPE_UINTMAX,
169     VALTYPE_SIZE,
170     VALTYPE_PTRDIFF,
171     VALTYPE_POINTER,
172     VALTYPE_CHAR_PTR,
173     VALTYPE_SCHAR_PTR,
174     VALTYPE_SHORT_PTR,
175     VALTYPE_INT_PTR,
176     VALTYPE_LONG_PTR,
177     VALTYPE_LONGLONG_PTR,
178     VALTYPE_INTMAX_PTR,
179     VALTYPE_SIZE_PTR,
180     VALTYPE_PTRDIFF_PTR
181   } valtype_t;
182
183
184 /* A union used to store the actual values. */
185 typedef union
186 {
187   char a_char;
188   signed char a_schar;
189   unsigned char a_uchar;
190   short a_short;
191   unsigned short a_ushort;
192   int a_int;
193   unsigned int a_uint;
194   long int a_long;
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;
199 #endif
200   double a_double;
201 #ifdef HAVE_LONG_DOUBLE
202   long double a_longdouble;
203 #endif
204   const char *a_string;
205 #ifdef HAVE_INTMAX_T
206   intmax_t a_intmax;
207 #endif
208 #ifdef HAVE_UINTMAX_T
209   intmax_t a_uintmax;
210 #endif
211   size_t a_size;
212 #ifdef HAVE_PTRDIFF_T
213   ptrdiff_t a_ptrdiff;
214 #endif
215   void *a_void_ptr;
216   char *a_char_ptr;
217   signed char *a_schar_ptr;
218   short *a_short_ptr;
219   int  *a_int_ptr;
220   long *a_long_ptr;
221 #ifdef HAVE_LONG_LONG_INT
222   long long int *a_longlong_ptr;
223 #endif
224 #ifdef HAVE_INTMAX_T
225   intmax_t *a_intmax_ptr;
226 #endif
227   size_t *a_size_ptr;
228 #ifdef HAVE_PTRDIFF_T
229   ptrdiff_t *a_ptrdiff_ptr;
230 #endif
231 } value_t;
232
233 /* An object used to keep track of a format option and arguments. */
234 struct argspec_s
235 {
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
244                           (e.g. for "%m").  */
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.  */
250 };
251 typedef struct argspec_s *argspec_t;
252
253 /* An object to build up a table of values and their types.  */
254 struct valueitem_s
255 {
256   valtype_t vt;  /* The type of the value.  */
257   value_t value; /* The value.  */
258 };
259 typedef struct valueitem_s *valueitem_t;
260
261
262 #ifdef DEBUG
263 static void
264 dump_argspecs (argspec_t arg, size_t argcount)
265 {
266   int idx;
267
268   for (idx=0; argcount; argcount--, arg++, idx++)
269     fprintf (stderr,
270              "%2d: len=%u flags=%u width=%d prec=%d mod=%d "
271              "con=%d vt=%d pos=%d-%d-%d\n",
272              idx,
273              (unsigned int)arg->length,
274              arg->flags,
275              arg->width,
276              arg->precision,
277              arg->lenmod,
278              arg->conspec,
279              arg->vt,
280              arg->arg_pos,
281              arg->width_pos,
282              arg->precision_pos);
283 }
284 #endif /*DEBUG*/
285
286
287 /* Set the vt field for ARG.  */
288 static void
289 compute_type (argspec_t arg)
290 {
291   switch (arg->conspec)
292     {
293     case CONSPEC_UNKNOWN:
294       arg->vt = VALTYPE_UNSUPPORTED;
295       break;
296
297     case CONSPEC_DECIMAL:
298       switch (arg->lenmod)
299         {
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;
308         }
309       break;
310
311     case CONSPEC_OCTAL:
312     case CONSPEC_UNSIGNED:
313     case CONSPEC_HEX:
314     case CONSPEC_HEX_UP:
315       switch (arg->lenmod)
316         {
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;
325         }
326       break;
327
328     case CONSPEC_FLOAT:
329     case CONSPEC_FLOAT_UP:
330     case CONSPEC_EXP:
331     case CONSPEC_EXP_UP:
332     case CONSPEC_F_OR_G:
333     case CONSPEC_F_OR_G_UP:
334     case CONSPEC_HEX_EXP:
335     case CONSPEC_HEX_EXP_UP:
336       switch (arg->lenmod)
337         {
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;
341         }
342       break;
343
344     case CONSPEC_CHAR:
345       arg->vt = VALTYPE_INT;
346       break;
347
348     case CONSPEC_STRING:
349       arg->vt = VALTYPE_STRING;
350       break;
351
352     case CONSPEC_POINTER:
353       arg->vt = VALTYPE_POINTER;
354       break;
355
356     case CONSPEC_STRERROR:
357       arg->vt = VALTYPE_STRING;
358       break;
359
360     case CONSPEC_BYTES_SO_FAR:
361       switch (arg->lenmod)
362         {
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;
371         }
372       break;
373
374     }
375 }
376
377
378
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. */
386 static int
387 parse_format (const char *format,
388               argspec_t *argspecs_addr, size_t max_argspecs,
389               size_t *r_argspecs_count)
390 {
391   const char *s;
392   argspec_t argspecs = *argspecs_addr;
393   argspec_t arg;
394   size_t argcount = 0;
395
396   if (!format)
397     goto leave_einval;
398
399   for (; *format; format++)
400     {
401       unsigned int flags;
402       int width, precision;
403       lenmod_t lenmod;
404       conspec_t conspec;
405       int arg_pos, width_pos, precision_pos;
406
407       if (*format != '%')
408         continue;
409       s = ++format;
410       if (!*s)
411         goto leave_einval;
412       if (*s == '%')
413         continue; /* Just a quoted percent.  */
414
415       /* First check whether there is a positional argument.  */
416       arg_pos = 0; /* No positional argument given.  */
417       if (*s >= '1' && *s <= '9')
418         {
419           const char *save_s = s;
420
421           arg_pos = (*s++ - '0');
422           for (; *s >= '0' && *s <= '9'; s++)
423             arg_pos = 10*arg_pos + (*s - '0');
424           if (arg_pos < 0)
425             goto leave_einval; /* Overflow during conversion.  */
426           if (*s == '$')
427             s++;
428           else
429             {
430               arg_pos = 0;
431               s = save_s;
432             }
433         }
434
435       /* Parse the flags.  */
436       flags = 0;
437       for ( ; *s; s++)
438         {
439           switch (*s)
440             {
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;
447             default:
448               goto flags_parsed;
449             }
450         }
451     flags_parsed:
452
453       /* Parse the field width.  */
454       width_pos = 0;
455       if (*s == '*')
456         {
457           width = STAR_FIELD_VALUE;
458           s++;
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')
462             {
463               width_pos = (*s++ - '0');
464               for (; *s >= '0' && *s <= '9'; s++)
465                 width_pos = 10*width_pos + (*s - '0');
466               if (width_pos < 1)
467                 goto leave_einval; /* Overflow during conversion.  */
468               if (*s != '$')
469                 goto leave_einval; /* Not followed by $.  */
470               s++;
471             }
472         }
473       else if ( *s >= '0' && *s <= '9')
474         {
475           width = (*s++ - '0');
476           for (; *s >= '0' && *s <= '9'; s++)
477             {
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');
483             }
484           if (width < 0)
485             goto leave_einval; /* Overflow during conversion.  */
486         }
487       else
488         width = NO_FIELD_VALUE;
489
490       /* Parse the precision.  */
491       precision_pos = 0;
492       precision = NO_FIELD_VALUE;
493       if (*s == '.')
494         {
495           int ignore_value = (s[1] == '-');
496
497           s++;
498           if (*s == '*')
499             {
500               precision = STAR_FIELD_VALUE;
501               s++;
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')
505                 {
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.  */
511                   if (*s != '$')
512                     goto leave_einval; /* Not followed by $.  */
513                   s++;
514                 }
515             }
516           else if ( *s >= '0' && *s <= '9')
517             {
518               precision = (*s++ - '0');
519               for (; *s >= '0' && *s <= '9'; s++)
520                 {
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');
526                 }
527               if (precision < 0)
528                 goto leave_einval; /* Overflow during conversion.  */
529             }
530           else
531             precision = 0;
532           if (ignore_value)
533             precision = NO_FIELD_VALUE;
534         }
535
536       /* Parse the length modifiers.  */
537       switch (*s)
538         {
539         case 'h':
540           if (s[1] == 'h')
541             {
542               lenmod = LENMOD_CHAR;
543               s++;
544             }
545           else
546             lenmod = LENMOD_SHORT;
547           s++;
548           break;
549         case 'l':
550           if (s[1] == 'l')
551             {
552               lenmod = LENMOD_LONGLONG;
553               s++;
554             }
555           else
556             lenmod = LENMOD_LONG;
557           s++;
558           break;
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;
564         }
565
566       /* Parse the conversion specifier.  */
567       switch (*s)
568         {
569         case 'd':
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;
591         }
592
593       /* Save the args. */
594       if (argcount >= max_argspecs)
595         {
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. */
600           size_t n, newmax;
601           argspec_t newarg;
602
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);
607           if (!newarg)
608             goto leave;
609           for (n=0; n < argcount; n++)
610             newarg[n] = argspecs[n];
611           if (argspecs != *argspecs_addr)
612             free (argspecs);
613           argspecs = newarg;
614           max_argspecs = newmax;
615         }
616
617       arg = argspecs + argcount;
618       arg->length = s - format + 2;
619       arg->flags = flags;
620       arg->width = width;
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;
627       compute_type (arg);
628       argcount++;
629       format = s;
630     }
631
632   *argspecs_addr = argspecs;
633   *r_argspecs_count = argcount;
634   return 0; /* Success.  */
635
636  leave_einval:
637   errno = EINVAL;
638  leave:
639   if (argspecs != *argspecs_addr)
640     free (argspecs);
641   *argspecs_addr = NULL;
642   return -1;
643 }
644
645
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. */
649 static int
650 read_values (valueitem_t valuetable, size_t valuetable_len, va_list vaargs)
651 {
652   int validx;
653
654   for (validx=0; validx < valuetable_len; validx++)
655     {
656       value_t *value = &valuetable[validx].value;
657       valtype_t vt = valuetable[validx].vt;
658
659       switch (vt)
660         {
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 *);
664           break;
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 *);
668           break;
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 *);
674           break;
675         case VALTYPE_INT:
676           value->a_int = va_arg (vaargs, int);
677           break;
678         case VALTYPE_INT_PTR:
679           value->a_int_ptr = va_arg (vaargs, int *);
680           break;
681         case VALTYPE_UINT:
682           value->a_uint = va_arg (vaargs, unsigned int);
683           break;
684         case VALTYPE_LONG:
685           value->a_long = va_arg (vaargs, long);
686           break;
687         case VALTYPE_ULONG:
688           value->a_ulong = va_arg (vaargs, unsigned long);
689           break;
690         case VALTYPE_LONG_PTR:
691           value->a_long_ptr = va_arg (vaargs, long *);
692           break;
693 #ifdef HAVE_LONG_LONG_INT
694         case VALTYPE_LONGLONG:
695           value->a_longlong = va_arg (vaargs, long long int);
696           break;
697         case VALTYPE_ULONGLONG:
698           value->a_ulonglong = va_arg (vaargs, unsigned long long int);
699           break;
700         case VALTYPE_LONGLONG_PTR:
701           value->a_longlong_ptr = va_arg (vaargs, long long *);
702           break;
703 #endif
704         case VALTYPE_DOUBLE:
705           value->a_double = va_arg (vaargs, double);
706           break;
707 #ifdef HAVE_LONG_DOUBLE
708         case VALTYPE_LONGDOUBLE:
709           value->a_longdouble = va_arg (vaargs, long double);
710           break;
711 #endif
712         case VALTYPE_STRING:
713           value->a_string = va_arg (vaargs, const char *);
714           break;
715         case VALTYPE_POINTER:
716           value->a_void_ptr = va_arg (vaargs, void *);
717           break;
718 #ifdef HAVE_INTMAX_T
719         case VALTYPE_INTMAX:
720           value->a_intmax = va_arg (vaargs, intmax_t);
721           break;
722         case VALTYPE_INTMAX_PTR:
723           value->a_intmax_ptr = va_arg (vaargs, intmax_t *);
724           break;
725 #endif
726 #ifdef HAVE_UINTMAX_T
727         case VALTYPE_UINTMAX:
728           value->a_uintmax = va_arg (vaargs, uintmax_t);
729           break;
730 #endif
731         case VALTYPE_SIZE:
732           value->a_size = va_arg (vaargs, size_t);
733           break;
734         case VALTYPE_SIZE_PTR:
735           value->a_size_ptr = va_arg (vaargs, size_t *);
736           break;
737 #ifdef HAVE_PTRDIFF_T
738         case VALTYPE_PTRDIFF:
739           value->a_ptrdiff = va_arg (vaargs, ptrdiff_t);
740           break;
741         case VALTYPE_PTRDIFF_PTR:
742           value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *);
743           break;
744 #endif
745         default: /* Unsupported type.  */
746           return -1;
747         }
748     }
749   return 0;
750 }
751
752
753 \f
754 /* Output COUNT padding characters PADCHAR and update NBYTES by the
755    number of bytes actually written.  */
756 static int
757 pad_out (estream_printf_out_t outfnc, void *outfncarg,
758          int padchar, int count, size_t *nbytes)
759 {
760   char buf[32];
761   size_t n;
762   int rc;
763
764   while (count > 0)
765     {
766       n = (count <= sizeof buf)? count : sizeof buf;
767       memset (buf, padchar, n);
768       rc = outfnc (outfncarg, buf, n);
769       if (rc)
770         return rc;
771       *nbytes += n;
772       count -= n;
773     }
774
775   return 0;
776 }
777
778
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).  */
782 static int
783 pr_integer (estream_printf_out_t outfnc, void *outfncarg,
784             argspec_t arg, value_t value, size_t *nbytes)
785 {
786   int rc;
787 #ifdef HAVE_LONG_LONG_INT
788   unsigned long long aulong;
789 #else
790   unsigned long aulong;
791 #endif
792   char numbuf[100];
793   char *p, *pend;
794   size_t n;
795   char signchar = 0;
796   int n_prec;  /* Number of extra precision digits required.  */
797   int n_extra; /* Extra number of prefix or sign characters.  */
798
799   if (arg->conspec == CONSPEC_DECIMAL)
800     {
801 #ifdef HAVE_LONG_LONG_INT
802       long long along;
803 #else
804       long along;
805 #endif
806
807       switch (arg->vt)
808         {
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;
817 # endif
818 # ifdef HAVE_PTRDIFF_T
819         case VALTYPE_PTRDIFF: along = value.a_ptrdiff; break;
820 # endif
821 #endif /*HAVE_LONG_LONG_INT*/
822         default:
823           return -1;
824         }
825       if (along < 0)
826         {
827           aulong = -along;
828           signchar = '-';
829         }
830       else
831         aulong = along;
832     }
833   else
834     {
835       switch (arg->vt)
836         {
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;
845 # endif
846 # ifdef HAVE_PTRDIFF_T
847         case VALTYPE_PTRDIFF: aulong = value.a_ptrdiff; break;
848 # endif
849 #endif /*HAVE_LONG_LONG_INT*/
850         default:
851           return -1;
852         }
853     }
854
855   if (signchar == '-')
856     ;
857   else if ((arg->flags & FLAG_PLUS_SIGN))
858     signchar = '+';
859   else if ((arg->flags & FLAG_SPACE_PLUS))
860     signchar = ' ';
861
862   n_extra = !!signchar;
863
864   /* We build the string up backwards.  */
865   p = pend = numbuf + DIM(numbuf);
866   if ((!aulong && !arg->precision))
867     ;
868   else if (arg->conspec == CONSPEC_DECIMAL
869            || arg->conspec == CONSPEC_UNSIGNED)
870     {
871       int grouping = -1;
872       const char * grouping_string =
873 #ifdef HAVE_LANGINFO_THOUSANDS_SEP
874         nl_langinfo(THOUSANDS_SEP);
875 #else
876         "'";
877 #endif
878
879       do
880         {
881           if ((arg->flags & FLAG_GROUPING)
882               && (++grouping == 3) && *grouping_string)
883             {
884               *--p = *grouping_string;
885               grouping = 0;
886             }
887           *--p = '0' + (aulong % 10);
888           aulong /= 10;
889         }
890       while (aulong);
891     }
892   else if (arg->conspec == CONSPEC_OCTAL)
893     {
894       do
895         {
896           *--p = '0' + (aulong % 8);
897           aulong /= 8;
898         }
899       while (aulong);
900       if ((arg->flags & FLAG_ALT_CONV) && *p != '0')
901         *--p = '0';
902     }
903   else /* HEX or HEXUP */
904     {
905       const char *digits = ((arg->conspec == CONSPEC_HEX)
906                             ? "0123456789abcdef" : "0123456789ABCDEF");
907       do
908         {
909           *--p = digits[(aulong % 16)];
910           aulong /= 16;
911         }
912       while (aulong);
913       if ((arg->flags & FLAG_ALT_CONV))
914         n_extra += 2;
915     }
916
917   n = pend - p;
918
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;
925   else
926     n_prec = 0;
927
928   if (!(arg->flags & FLAG_LEFT_JUST)
929       && arg->width >= 0 && arg->width - n_extra > n
930       && arg->width - n_extra - n >= n_prec )
931     {
932       rc = pad_out (outfnc, outfncarg, ' ',
933                     arg->width - n_extra - n - n_prec, nbytes);
934       if (rc)
935         return rc;
936     }
937
938   if (signchar)
939     {
940       rc = outfnc (outfncarg, &signchar, 1);
941       if (rc)
942         return rc;
943       *nbytes += 1;
944     }
945
946   if ((arg->flags & FLAG_ALT_CONV)
947       && (arg->conspec == CONSPEC_HEX || arg->conspec == CONSPEC_HEX_UP))
948     {
949       rc = outfnc (outfncarg, arg->conspec == CONSPEC_HEX? "0x": "0X", 2);
950       if (rc)
951         return rc;
952       *nbytes += 2;
953     }
954
955   if (n_prec)
956     {
957       rc = pad_out (outfnc, outfncarg, '0', n_prec, nbytes);
958       if (rc)
959         return rc;
960     }
961
962   rc = outfnc (outfncarg, p, pend - p);
963   if (rc)
964     return rc;
965   *nbytes += pend - p;
966
967   if ((arg->flags & FLAG_LEFT_JUST)
968       && arg->width >= 0 && arg->width - n_extra - n_prec > n)
969     {
970       rc = pad_out (outfnc, outfncarg, ' ',
971                     arg->width - n_extra - n_prec - n, nbytes);
972       if (rc)
973         return rc;
974     }
975
976   return 0;
977 }
978
979
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.  */
988 static int
989 pr_float (estream_printf_out_t outfnc, void *outfncarg,
990           argspec_t arg, value_t value, size_t *nbytes)
991 {
992   int rc;
993 #ifdef HAVE_LONG_DOUBLE
994   long double adblfloat = 0; /* Just to please gcc.  */
995   int use_dbl = 0;
996 #endif
997   double afloat;
998   char numbuf[350];
999   char formatstr[20];
1000   char *p, *pend;
1001   size_t n;
1002   char signchar = 0;
1003   int n_extra;  /* Extra number of prefix or sign characters.  */
1004
1005   switch (arg->vt)
1006     {
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;
1012       use_dbl=1; break;
1013 #endif
1014     default:
1015       return -1;
1016     }
1017
1018   /* We build the string using sprint.  */
1019   p = formatstr + sizeof formatstr;
1020   *--p = 0;
1021   switch (arg->conspec)
1022     {
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;
1031     default:
1032       return -1; /* Actually a bug.  */
1033     }
1034 #ifdef HAVE_LONG_DOUBLE
1035   if (use_dbl)
1036     *--p = 'L';
1037 #endif
1038   if (arg->precision != NO_FIELD_VALUE)
1039     {
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;
1043       do
1044         {
1045           *--p = '0' + (n % 10);
1046           n /= 10;
1047         }
1048       while (n);
1049       *--p = '.';
1050     }
1051   if ((arg->flags & FLAG_ALT_CONV))
1052     *--p = '#';
1053   *--p = '%';
1054
1055 #if GNUPG_GCC_VERSION >= 40600
1056 # pragma GCC diagnostic push
1057 # pragma GCC diagnostic ignored "-Wformat-nonliteral"
1058 #endif
1059
1060 #ifdef HAVE_LONG_DOUBLE
1061   if (use_dbl)
1062     sprintf (numbuf, p, adblfloat);
1063   else
1064 #endif /*HAVE_LONG_DOUBLE*/
1065     sprintf (numbuf, p, afloat);
1066
1067 #if GNUPG_GCC_VERSION >= 40600
1068 # pragma GCC diagnostic pop
1069 #endif
1070
1071   p = numbuf;
1072   n = strlen (numbuf);
1073   pend = p + n;
1074
1075   if (*p =='-')
1076     {
1077       signchar = '-';
1078       p++;
1079       n--;
1080     }
1081   else if ((arg->flags & FLAG_PLUS_SIGN))
1082     signchar = '+';
1083   else if ((arg->flags & FLAG_SPACE_PLUS))
1084     signchar = ' ';
1085
1086   n_extra = !!signchar;
1087
1088   if (!(arg->flags & FLAG_LEFT_JUST)
1089       && arg->width >= 0 && arg->width - n_extra > n)
1090     {
1091       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes);
1092       if (rc)
1093         return rc;
1094     }
1095
1096   if (signchar)
1097     {
1098       rc = outfnc (outfncarg, &signchar, 1);
1099       if (rc)
1100         return rc;
1101       *nbytes += 1;
1102     }
1103
1104   rc = outfnc (outfncarg, p, pend - p);
1105   if (rc)
1106     return rc;
1107   *nbytes += pend - p;
1108
1109   if ((arg->flags & FLAG_LEFT_JUST)
1110       && arg->width >= 0 && arg->width - n_extra > n)
1111     {
1112       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes);
1113       if (rc)
1114         return rc;
1115     }
1116
1117   return 0;
1118 }
1119
1120
1121 /* "c" formatting.  */
1122 static int
1123 pr_char (estream_printf_out_t outfnc, void *outfncarg,
1124             argspec_t arg, value_t value, size_t *nbytes)
1125 {
1126   int rc;
1127   char buf[1];
1128
1129   if (arg->vt != VALTYPE_INT)
1130     return -1;
1131   buf[0] = (unsigned int)value.a_int;
1132   rc = outfnc (outfncarg, buf, 1);
1133   if(rc)
1134     return rc;
1135   *nbytes += 1;
1136
1137   return 0;
1138 }
1139
1140
1141 /* "s" formatting.  */
1142 static int
1143 pr_string (estream_printf_out_t outfnc, void *outfncarg,
1144             argspec_t arg, value_t value, size_t *nbytes)
1145 {
1146   int rc;
1147   size_t n;
1148   const char *string, *s;
1149
1150   if (arg->vt != VALTYPE_STRING)
1151     return -1;
1152   string = value.a_string;
1153   if (!string)
1154     string = "(null)";
1155   if (arg->precision >= 0)
1156     {
1157       for (n=0,s=string; *s && n < arg->precision; s++)
1158         n++;
1159     }
1160   else
1161     n = strlen (string);
1162
1163   if (!(arg->flags & FLAG_LEFT_JUST)
1164       && arg->width >= 0 && arg->width > n )
1165     {
1166       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
1167       if (rc)
1168         return rc;
1169     }
1170
1171   rc = outfnc (outfncarg, string, n);
1172   if (rc)
1173     return rc;
1174   *nbytes += n;
1175
1176   if ((arg->flags & FLAG_LEFT_JUST)
1177       && arg->width >= 0 && arg->width > n)
1178     {
1179       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
1180       if (rc)
1181         return rc;
1182     }
1183
1184   return 0;
1185 }
1186
1187
1188 /* "p" formatting.  */
1189 static int
1190 pr_pointer (estream_printf_out_t outfnc, void *outfncarg,
1191             argspec_t arg, value_t value, size_t *nbytes)
1192 {
1193   int rc;
1194 #ifdef HAVE_LONG_LONG_INT
1195   unsigned long long aulong;
1196 #else
1197   unsigned long aulong;
1198 #endif
1199   char numbuf[100];
1200   char *p, *pend;
1201
1202   if (arg->vt != VALTYPE_POINTER)
1203     return -1;
1204   /* We assume that a pointer can be converted to an unsigned long.
1205      That is not correct for a 64 bit Windows, but then we assume that
1206      long long is supported and usable for storing a pointer.  */
1207 #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P)
1208   aulong = (unsigned long long)value.a_void_ptr;
1209 #else
1210   aulong = (unsigned long)value.a_void_ptr;
1211 #endif
1212
1213   p = pend = numbuf + DIM(numbuf);
1214   do
1215     {
1216       *--p = "0123456789abcdefx"[(aulong % 16)];
1217       aulong /= 16;
1218     }
1219   while (aulong);
1220   while ((pend-p) < 2*sizeof (aulong))
1221     *--p = '0';
1222   *--p = 'x';
1223   *--p = '0';
1224
1225   rc = outfnc (outfncarg, p, pend - p);
1226   if (rc)
1227     return rc;
1228   *nbytes += pend - p;
1229
1230   return 0;
1231 }
1232
1233 /* "n" pesudo format operation.  */
1234 static int
1235 pr_bytes_so_far (estream_printf_out_t outfnc, void *outfncarg,
1236                  argspec_t arg, value_t value, size_t *nbytes)
1237 {
1238   (void)outfnc;
1239   (void)outfncarg;
1240
1241   switch (arg->vt)
1242     {
1243     case VALTYPE_SCHAR_PTR:
1244       *value.a_schar_ptr = (signed char)(unsigned int)(*nbytes);
1245       break;
1246     case VALTYPE_SHORT_PTR:
1247       *value.a_short_ptr = (short)(unsigned int)(*nbytes);
1248       break;
1249     case VALTYPE_LONG_PTR:
1250       *value.a_long_ptr = (long)(*nbytes);
1251       break;
1252 #ifdef HAVE_LONG_LONG_INT
1253     case VALTYPE_LONGLONG_PTR:
1254       *value.a_longlong_ptr = (long long)(*nbytes);
1255       break;
1256 #endif
1257 #ifdef HAVE_INTMAX_T
1258     case VALTYPE_INTMAX_PTR:
1259       *value.a_intmax_ptr = (intmax_t)(*nbytes);
1260       break;
1261 #endif
1262     case VALTYPE_SIZE_PTR:
1263       *value.a_size_ptr = (*nbytes);
1264       break;
1265 #ifdef HAVE_PTRDIFF_T
1266     case VALTYPE_PTRDIFF_PTR:
1267       *value.a_ptrdiff_ptr = (ptrdiff_t)(*nbytes);
1268       break;
1269 #endif
1270     case VALTYPE_INT_PTR:
1271       *value.a_int_ptr = (int)(*nbytes);
1272       break;
1273     default:
1274       return -1; /* An unsupported type has been used.  */
1275     }
1276
1277   return 0;
1278 }
1279
1280
1281
1282 /* Run the actual formatting.  OUTFNC and OUTFNCARG are the output
1283    functions.  FORMAT is format string ARGSPECS is the parsed format
1284    string, ARGSPECS_LEN the number of items in ARGSPECS.  VALUETABLE
1285    holds the values and may be directly addressed using the position
1286    arguments given by ARGSPECS.  MYERRNO is used for the "%m"
1287    conversion. NBYTES well be updated to reflect the number of bytes
1288    send to the output function. */
1289 static int
1290 do_format (estream_printf_out_t outfnc, void *outfncarg,
1291            const char *format, argspec_t argspecs, size_t argspecs_len,
1292            valueitem_t valuetable, int myerrno, size_t *nbytes)
1293 {
1294   int rc = 0;
1295   const char *s;
1296   argspec_t arg = argspecs;
1297   int argidx = 0; /* Only used for assertion.  */
1298   size_t n;
1299   value_t value;
1300
1301   s = format;
1302   while ( *s )
1303     {
1304       if (*s != '%')
1305         {
1306           s++;
1307           continue;
1308         }
1309       if (s != format)
1310         {
1311           rc = outfnc (outfncarg, format, (n=s-format));
1312           if (rc)
1313             return rc;
1314           *nbytes += n;
1315         }
1316       if (s[1] == '%')
1317         {
1318           /* Note that this code ignores one trailing percent escape -
1319              this is however okay as the args parser must have
1320              detected this already.  */
1321           rc = outfnc (outfncarg, s, 1);
1322           if (rc)
1323             return rc;
1324           *nbytes += 1;
1325           s += 2;
1326           format = s;
1327           continue;
1328         }
1329
1330       /* Save the next start.  */
1331       s += arg->length;
1332       format = s;
1333
1334       assert (argidx < argspecs_len);
1335       argidx++;
1336
1337       /* Apply indirect field width and precision values.  */
1338       if (arg->width == STAR_FIELD_VALUE)
1339         {
1340           assert (valuetable[arg->width_pos-1].vt == VALTYPE_INT);
1341           arg->width = valuetable[arg->width_pos-1].value.a_int;
1342           if (arg->width < 0)
1343             {
1344               arg->width = -arg->width;
1345               arg->flags |= FLAG_LEFT_JUST;
1346             }
1347         }
1348       if (arg->precision == STAR_FIELD_VALUE)
1349         {
1350           assert (valuetable[arg->precision_pos-1].vt == VALTYPE_INT);
1351           arg->precision = valuetable[arg->precision_pos-1].value.a_int;
1352           if (arg->precision < 0)
1353             arg->precision = NO_FIELD_VALUE;
1354         }
1355
1356       if (arg->arg_pos == -1 && arg->conspec == CONSPEC_STRERROR)
1357         value.a_string = strerror (myerrno);
1358       else
1359         {
1360           assert (arg->vt == valuetable[arg->arg_pos-1].vt);
1361           value = valuetable[arg->arg_pos-1].value;
1362         }
1363
1364       switch (arg->conspec)
1365         {
1366         case CONSPEC_UNKNOWN: assert (!"bug"); break;
1367
1368         case CONSPEC_DECIMAL:
1369         case CONSPEC_UNSIGNED:
1370         case CONSPEC_OCTAL:
1371         case CONSPEC_HEX:
1372         case CONSPEC_HEX_UP:
1373           rc = pr_integer (outfnc, outfncarg, arg, value, nbytes);
1374           break;
1375         case CONSPEC_FLOAT:
1376         case CONSPEC_FLOAT_UP:
1377         case CONSPEC_EXP:
1378         case CONSPEC_EXP_UP:
1379         case CONSPEC_F_OR_G:
1380         case CONSPEC_F_OR_G_UP:
1381         case CONSPEC_HEX_EXP:
1382         case CONSPEC_HEX_EXP_UP:
1383           rc = pr_float (outfnc, outfncarg, arg, value, nbytes);
1384           break;
1385         case CONSPEC_CHAR:
1386           rc = pr_char (outfnc, outfncarg, arg, value, nbytes);
1387           break;
1388         case CONSPEC_STRING:
1389         case CONSPEC_STRERROR:
1390           rc = pr_string (outfnc, outfncarg, arg, value, nbytes);
1391           break;
1392         case CONSPEC_POINTER:
1393           rc = pr_pointer (outfnc, outfncarg, arg, value, nbytes);
1394           break;
1395         case CONSPEC_BYTES_SO_FAR:
1396           rc = pr_bytes_so_far (outfnc, outfncarg, arg, value, nbytes);
1397           break;
1398         }
1399       if (rc)
1400         return rc;
1401       arg++;
1402     }
1403
1404   /* Print out any trailing stuff. */
1405   n = s - format;
1406   rc = n? outfnc (outfncarg, format, n) : 0;
1407   if (!rc)
1408     *nbytes += n;
1409
1410   return rc;
1411 }
1412
1413
1414
1415 \f
1416 /* The versatile printf formatting routine.  It expects a callback
1417    function OUTFNC and an opaque argument OUTFNCARG used for actual
1418    output of the formatted stuff.  FORMAT is the format specification
1419    and VAARGS a variable argumemt list matching the arguments of
1420    FORMAT.  */
1421 int
1422 estream_format (estream_printf_out_t outfnc,
1423                 void *outfncarg,
1424                 const char *format, va_list vaargs)
1425 {
1426   /* Buffer to hold the argspecs and a pointer to it.*/
1427   struct argspec_s argspecs_buffer[DEFAULT_MAX_ARGSPECS];
1428   argspec_t argspecs = argspecs_buffer;
1429   size_t argspecs_len;  /* Number of specifications in ARGSPECS.  */
1430
1431   /* Buffer to hold the description for the values.  */
1432   struct valueitem_s valuetable_buffer[DEFAULT_MAX_VALUES];
1433   valueitem_t valuetable = valuetable_buffer;
1434
1435   int rc;     /* Return code. */
1436   size_t argidx; /* Used to index the argspecs array.  */
1437   size_t validx; /* Used to index the valuetable.  */
1438   int max_pos;/* Highest argument position.  */
1439
1440   size_t nbytes = 0; /* Keep track of the number of bytes passed to
1441                         the output function.  */
1442
1443   int myerrno = errno; /* Save the errno for use with "%m". */
1444
1445
1446   /* Parse the arguments to come up with descriptive list.  We can't
1447      do this on the fly because we need to support positional
1448      arguments. */
1449   rc = parse_format (format, &argspecs, DIM(argspecs_buffer), &argspecs_len);
1450   if (rc)
1451     goto leave;
1452
1453   /* Check that all ARG_POS fields are set.  */
1454   for (argidx=0,max_pos=0; argidx < argspecs_len; argidx++)
1455     {
1456       if (argspecs[argidx].arg_pos != -1
1457           && argspecs[argidx].arg_pos > max_pos)
1458         max_pos = argspecs[argidx].arg_pos;
1459       if (argspecs[argidx].width_pos > max_pos)
1460         max_pos = argspecs[argidx].width_pos;
1461       if (argspecs[argidx].precision_pos > max_pos)
1462         max_pos = argspecs[argidx].precision_pos;
1463     }
1464   if (!max_pos)
1465     {
1466       /* Fill in all the positions.  */
1467       for (argidx=0; argidx < argspecs_len; argidx++)
1468         {
1469           if (argspecs[argidx].width == STAR_FIELD_VALUE)
1470             argspecs[argidx].width_pos = ++max_pos;
1471           if (argspecs[argidx].precision == STAR_FIELD_VALUE)
1472             argspecs[argidx].precision_pos = ++max_pos;
1473           if (argspecs[argidx].arg_pos != -1 )
1474             argspecs[argidx].arg_pos = ++max_pos;
1475         }
1476     }
1477   else
1478     {
1479       /* Check that they are all filled.   More test are done later.  */
1480       for (argidx=0; argidx < argspecs_len; argidx++)
1481         {
1482           if (!argspecs[argidx].arg_pos
1483               || (argspecs[argidx].width == STAR_FIELD_VALUE
1484                   && !argspecs[argidx].width_pos)
1485               || (argspecs[argidx].precision == STAR_FIELD_VALUE
1486                   && !argspecs[argidx].precision_pos))
1487             goto leave_einval;
1488         }
1489     }
1490   /* Check that there is no overflow in max_pos and that it has a
1491      reasonable length.  There may never be more elements than the
1492      number of characters in FORMAT.  */
1493   if (max_pos < 0 || max_pos >= strlen (format))
1494     goto leave_einval;
1495
1496 #ifdef DEBUG
1497     dump_argspecs (argspecs, argspecs_len);
1498 #endif
1499
1500   /* Allocate a table to hold the values.  If it is small enough we
1501      use a stack allocated buffer.  */
1502   if (max_pos > DIM(valuetable_buffer))
1503     {
1504       valuetable = calloc (max_pos, sizeof *valuetable);
1505       if (!valuetable)
1506         goto leave_error;
1507     }
1508   else
1509     {
1510       for (validx=0; validx < DIM(valuetable_buffer); validx++)
1511         valuetable[validx].vt = VALTYPE_UNSUPPORTED;
1512     }
1513   for (argidx=0; argidx < argspecs_len; argidx++)
1514     {
1515       if (argspecs[argidx].arg_pos != - 1)
1516         {
1517           validx = argspecs[argidx].arg_pos - 1;
1518           if (valuetable[validx].vt)
1519             goto leave_einval; /* Already defined. */
1520           valuetable[validx].vt = argspecs[argidx].vt;
1521         }
1522       if (argspecs[argidx].width == STAR_FIELD_VALUE)
1523         {
1524           validx = argspecs[argidx].width_pos - 1;
1525           if (valuetable[validx].vt)
1526             goto leave_einval; /* Already defined.  */
1527           valuetable[validx].vt = VALTYPE_INT;
1528         }
1529       if (argspecs[argidx].precision == STAR_FIELD_VALUE)
1530         {
1531           validx = argspecs[argidx].precision_pos - 1;
1532           if (valuetable[validx].vt)
1533             goto leave_einval; /* Already defined.  */
1534           valuetable[validx].vt = VALTYPE_INT;
1535         }
1536     }
1537
1538   /* Read all the arguments.  This will error out for unsupported
1539      types and for not given positional arguments. */
1540   rc = read_values (valuetable, max_pos, vaargs);
1541   if (rc)
1542     goto leave_einval;
1543
1544 /*   for (validx=0; validx < max_pos; validx++) */
1545 /*     fprintf (stderr, "%2d: vt=%d\n", validx, valuetable[validx].vt); */
1546
1547   /* Everything has been collected, go ahead with the formatting.  */
1548   rc = do_format (outfnc, outfncarg, format,
1549                   argspecs, argspecs_len, valuetable, myerrno, &nbytes);
1550
1551   goto leave;
1552
1553  leave_einval:
1554   errno = EINVAL;
1555  leave_error:
1556   rc = -1;
1557  leave:
1558   if (valuetable != valuetable_buffer)
1559     free (valuetable);
1560   if (argspecs != argspecs_buffer)
1561     free (argspecs);
1562   return rc;
1563 }
1564
1565
1566 \f
1567
1568 /* A simple output handler utilizing stdio.  */
1569 static int
1570 plain_stdio_out (void *outfncarg, const char *buf, size_t buflen)
1571 {
1572   FILE *fp = (FILE*)outfncarg;
1573
1574   if ( fwrite (buf, buflen, 1, fp) != 1 )
1575     return -1;
1576   return 0;
1577 }
1578
1579
1580 /* A replacement for printf.  */
1581 int
1582 estream_printf (const char *format, ...)
1583 {
1584   int rc;
1585   va_list arg_ptr;
1586
1587   va_start (arg_ptr, format);
1588   rc = estream_format (plain_stdio_out, stderr, format, arg_ptr);
1589   va_end (arg_ptr);
1590
1591   return rc;
1592 }
1593
1594 /* A replacement for fprintf.  */
1595 int
1596 estream_fprintf (FILE *fp, const char *format, ...)
1597 {
1598   int rc;
1599   va_list arg_ptr;
1600
1601   va_start (arg_ptr, format);
1602   rc = estream_format (plain_stdio_out, fp, format, arg_ptr);
1603   va_end (arg_ptr);
1604
1605   return rc;
1606 }
1607
1608 /* A replacement for vfprintf.  */
1609 int
1610 estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr)
1611 {
1612   return estream_format (plain_stdio_out, fp, format, arg_ptr);
1613 }
1614
1615
1616 \f
1617 /* Communication object used between estream_snprintf and
1618    fixed_buffer_out.  */
1619 struct fixed_buffer_parm_s
1620 {
1621   size_t size;    /* Size of the buffer.  */
1622   size_t count;   /* Number of bytes requested for output.  */
1623   size_t used;    /* Used size of the buffer.  */
1624   char *buffer;   /* Provided buffer.  */
1625 };
1626
1627 /* A simple malloced buffer output handler.  */
1628 static int
1629 fixed_buffer_out (void *outfncarg, const char *buf, size_t buflen)
1630 {
1631   struct fixed_buffer_parm_s *parm = outfncarg;
1632
1633   parm->count += buflen;
1634
1635   if (!parm->buffer)
1636     ;
1637   else if (parm->used + buflen < parm->size)
1638     {
1639       /* Handle the common case that everything fits into the buffer
1640          separately.  */
1641       memcpy (parm->buffer + parm->used, buf, buflen);
1642       parm->used += buflen;
1643     }
1644   else
1645     {
1646       /* The slow version of above.  */
1647       for ( ;buflen && parm->used < parm->size; buflen--)
1648         parm->buffer[parm->used++] = *buf++;
1649     }
1650
1651   return 0;
1652 }
1653
1654
1655 /* A replacement for vsnprintf. */
1656 int
1657 estream_vsnprintf (char *buf, size_t bufsize,
1658                    const char *format, va_list arg_ptr)
1659 {
1660   struct fixed_buffer_parm_s parm;
1661   int rc;
1662
1663   parm.size = bufsize;
1664   parm.count = 0;
1665   parm.used = 0;
1666   parm.buffer = bufsize?buf:NULL;
1667   rc = estream_format (fixed_buffer_out, &parm, format, arg_ptr);
1668   if (!rc)
1669     rc = fixed_buffer_out (&parm, "", 1); /* Print terminating Nul.  */
1670   if (rc == -1)
1671     return -1;
1672   if (bufsize && buf && parm.size && parm.count >= parm.size)
1673     buf[parm.size-1] = 0;
1674
1675   parm.count--; /* Do not count the trailing nul.  */
1676   return (int)parm.count; /* Return number of bytes which would have
1677                              been written.  */
1678 }
1679
1680 /* A replacement for snprintf.  */
1681 int
1682 estream_snprintf (char *buf, size_t bufsize, const char *format, ...)
1683 {
1684   int rc;
1685   va_list arg_ptr;
1686
1687   va_start (arg_ptr, format);
1688   rc = estream_vsnprintf (buf, bufsize, format, arg_ptr);
1689   va_end (arg_ptr);
1690
1691   return rc;
1692 }
1693
1694
1695 \f
1696 /* Communication object used between estream_asprintf and
1697    dynamic_buffer_out.  */
1698 struct dynamic_buffer_parm_s
1699 {
1700   int error_flag; /* Internal helper.  */
1701   size_t alloced; /* Allocated size of the buffer.  */
1702   size_t used;    /* Used size of the buffer.  */
1703   char *buffer;   /* Malloced buffer.  */
1704 };
1705
1706 /* A simple malloced buffer output handler.  */
1707 static int
1708 dynamic_buffer_out (void *outfncarg, const char *buf, size_t buflen)
1709 {
1710   struct dynamic_buffer_parm_s *parm = outfncarg;
1711
1712   if (parm->error_flag)
1713     {
1714       /* Just in case some formatting routine did not checked for an
1715          error. */
1716       errno = parm->error_flag;
1717       return -1;
1718     }
1719
1720   if (parm->used + buflen >= parm->alloced)
1721     {
1722       char *p;
1723
1724       parm->alloced += buflen + 512;
1725       p = realloc (parm->buffer, parm->alloced);
1726       if (!p)
1727         {
1728           parm->error_flag = errno ? errno : ENOMEM;
1729           /* Wipe out what we already accumulated.  This is useful in
1730              case sensitive data is formated.  */
1731           memset (parm->buffer, 0, parm->used);
1732           return -1;
1733         }
1734       parm->buffer = p;
1735     }
1736   memcpy (parm->buffer + parm->used, buf, buflen);
1737   parm->used += buflen;
1738
1739   return 0;
1740 }
1741
1742
1743 /* A replacement for vasprintf.  As with the BSD of vasprintf version -1
1744    will be returned on error and NULL stored at BUFP.  On success the
1745    number of bytes printed will be returned. */
1746 int
1747 estream_vasprintf (char **bufp, const char *format, va_list arg_ptr)
1748 {
1749   struct dynamic_buffer_parm_s parm;
1750   int rc;
1751
1752   parm.error_flag = 0;
1753   parm.alloced = 512;
1754   parm.used = 0;
1755   parm.buffer = my_printf_malloc (parm.alloced);
1756   if (!parm.buffer)
1757     {
1758       *bufp = NULL;
1759       return -1;
1760     }
1761
1762   rc = estream_format (dynamic_buffer_out, &parm, format, arg_ptr);
1763   if (!rc)
1764     rc = dynamic_buffer_out (&parm, "", 1); /* Print terminating Nul.  */
1765   /* Fixme: Should we shrink the resulting buffer?  */
1766   if (rc != -1 && parm.error_flag)
1767     {
1768       rc = -1;
1769       errno = parm.error_flag;
1770     }
1771   if (rc == -1)
1772     {
1773       memset (parm.buffer, 0, parm.used);
1774       my_printf_free (parm.buffer);
1775       *bufp = NULL;
1776       return -1;
1777     }
1778   assert (parm.used);   /* We have at least the terminating Nul.  */
1779   *bufp = parm.buffer;
1780   return parm.used - 1; /* Do not include that Nul. */
1781 }
1782
1783 /* A replacement for asprintf.  As with the BSD of asprintf version -1
1784    will be returned on error and NULL stored at BUFP.  On success the
1785    number of bytes printed will be returned. */
1786 int
1787 estream_asprintf (char **bufp, const char *format, ...)
1788 {
1789   int rc;
1790   va_list arg_ptr;
1791
1792   va_start (arg_ptr, format);
1793   rc = estream_vasprintf (bufp, format, arg_ptr);
1794   va_end (arg_ptr);
1795
1796   return rc;
1797 }
1798
1799