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