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