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