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