Imported Upstream version 7.50.2
[platform/upstream/curl.git] / lib / mprintf.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1999 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  *
22  * Purpose:
23  *  A merge of Bjorn Reese's format() function and Daniel's dsprintf()
24  *  1.0. A full blooded printf() clone with full support for <num>$
25  *  everywhere (parameters, widths and precisions) including variabled
26  *  sized parameters (like doubles, long longs, long doubles and even
27  *  void * in 64-bit architectures).
28  *
29  * Current restrictions:
30  * - Max 128 parameters
31  * - No 'long double' support.
32  *
33  * If you ever want truly portable and good *printf() clones, the project that
34  * took on from here is named 'Trio' and you find more details on the trio web
35  * page at https://daniel.haxx.se/projects/trio/
36  */
37
38 #include "curl_setup.h"
39 #include <curl/mprintf.h>
40
41 #include "curl_memory.h"
42 /* The last #include file should be: */
43 #include "memdebug.h"
44
45 #ifndef SIZEOF_LONG_DOUBLE
46 #define SIZEOF_LONG_DOUBLE 0
47 #endif
48
49 /*
50  * If SIZEOF_SIZE_T has not been defined, default to the size of long.
51  */
52
53 #ifndef SIZEOF_SIZE_T
54 #  define SIZEOF_SIZE_T CURL_SIZEOF_LONG
55 #endif
56
57 #ifdef HAVE_LONGLONG
58 #  define LONG_LONG_TYPE long long
59 #  define HAVE_LONG_LONG_TYPE
60 #else
61 #  if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
62 #    define LONG_LONG_TYPE __int64
63 #    define HAVE_LONG_LONG_TYPE
64 #  else
65 #    undef LONG_LONG_TYPE
66 #    undef HAVE_LONG_LONG_TYPE
67 #  endif
68 #endif
69
70 /*
71  * Non-ANSI integer extensions
72  */
73
74 #if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
75     (defined(__WATCOMC__) && defined(__386__)) || \
76     (defined(__POCC__) && defined(_MSC_VER)) || \
77     (defined(_WIN32_WCE)) || \
78     (defined(__MINGW32__)) || \
79     (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
80 #  define MP_HAVE_INT_EXTENSIONS
81 #endif
82
83 /*
84  * Max integer data types that mprintf.c is capable
85  */
86
87 #ifdef HAVE_LONG_LONG_TYPE
88 #  define mp_intmax_t LONG_LONG_TYPE
89 #  define mp_uintmax_t unsigned LONG_LONG_TYPE
90 #else
91 #  define mp_intmax_t long
92 #  define mp_uintmax_t unsigned long
93 #endif
94
95 #define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
96 #define MAX_PARAMETERS 128 /* lame static limit */
97
98 #ifdef __AMIGA__
99 # undef FORMAT_INT
100 #endif
101
102 /* Lower-case digits.  */
103 static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
104
105 /* Upper-case digits.  */
106 static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
107
108 #define OUTCHAR(x) \
109   do{ \
110     if(stream((unsigned char)(x), (FILE *)data) != -1) \
111       done++; \
112     else \
113      return done; /* return immediately on failure */ \
114   } WHILE_FALSE
115
116 /* Data type to read from the arglist */
117 typedef enum  {
118   FORMAT_UNKNOWN = 0,
119   FORMAT_STRING,
120   FORMAT_PTR,
121   FORMAT_INT,
122   FORMAT_INTPTR,
123   FORMAT_LONG,
124   FORMAT_LONGLONG,
125   FORMAT_DOUBLE,
126   FORMAT_LONGDOUBLE,
127   FORMAT_WIDTH /* For internal use */
128 } FormatType;
129
130 /* conversion and display flags */
131 enum {
132   FLAGS_NEW        = 0,
133   FLAGS_SPACE      = 1<<0,
134   FLAGS_SHOWSIGN   = 1<<1,
135   FLAGS_LEFT       = 1<<2,
136   FLAGS_ALT        = 1<<3,
137   FLAGS_SHORT      = 1<<4,
138   FLAGS_LONG       = 1<<5,
139   FLAGS_LONGLONG   = 1<<6,
140   FLAGS_LONGDOUBLE = 1<<7,
141   FLAGS_PAD_NIL    = 1<<8,
142   FLAGS_UNSIGNED   = 1<<9,
143   FLAGS_OCTAL      = 1<<10,
144   FLAGS_HEX        = 1<<11,
145   FLAGS_UPPER      = 1<<12,
146   FLAGS_WIDTH      = 1<<13, /* '*' or '*<num>$' used */
147   FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */
148   FLAGS_PREC       = 1<<15, /* precision was specified */
149   FLAGS_PRECPARAM  = 1<<16, /* precision PARAMETER was specified */
150   FLAGS_CHAR       = 1<<17, /* %c story */
151   FLAGS_FLOATE     = 1<<18, /* %e or %E */
152   FLAGS_FLOATG     = 1<<19  /* %g or %G */
153 };
154
155 typedef struct {
156   FormatType type;
157   int flags;
158   long width;     /* width OR width parameter number */
159   long precision; /* precision OR precision parameter number */
160   union {
161     char *str;
162     void *ptr;
163     union {
164       mp_intmax_t as_signed;
165       mp_uintmax_t as_unsigned;
166     } num;
167     double dnum;
168   } data;
169 } va_stack_t;
170
171 struct nsprintf {
172   char *buffer;
173   size_t length;
174   size_t max;
175 };
176
177 struct asprintf {
178   char *buffer; /* allocated buffer */
179   size_t len;   /* length of string */
180   size_t alloc; /* length of alloc */
181   int fail;     /* (!= 0) if an alloc has failed and thus
182                    the output is not the complete data */
183 };
184
185 static long dprintf_DollarString(char *input, char **end)
186 {
187   int number=0;
188   while(ISDIGIT(*input)) {
189     number *= 10;
190     number += *input-'0';
191     input++;
192   }
193   if(number && ('$'==*input++)) {
194     *end = input;
195     return number;
196   }
197   return 0;
198 }
199
200 static bool dprintf_IsQualifierNoDollar(const char *fmt)
201 {
202 #if defined(MP_HAVE_INT_EXTENSIONS)
203   if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
204     return TRUE;
205   }
206 #endif
207
208   switch(*fmt) {
209   case '-': case '+': case ' ': case '#': case '.':
210   case '0': case '1': case '2': case '3': case '4':
211   case '5': case '6': case '7': case '8': case '9':
212   case 'h': case 'l': case 'L': case 'z': case 'q':
213   case '*': case 'O':
214 #if defined(MP_HAVE_INT_EXTENSIONS)
215   case 'I':
216 #endif
217     return TRUE;
218
219   default:
220     return FALSE;
221   }
222 }
223
224 /******************************************************************
225  *
226  * Pass 1:
227  * Create an index with the type of each parameter entry and its
228  * value (may vary in size)
229  *
230  ******************************************************************/
231
232 static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
233                           va_list arglist)
234 {
235   char *fmt = (char *)format;
236   int param_num = 0;
237   long this_param;
238   long width;
239   long precision;
240   int flags;
241   long max_param=0;
242   long i;
243
244   while(*fmt) {
245     if(*fmt++ == '%') {
246       if(*fmt == '%') {
247         fmt++;
248         continue; /* while */
249       }
250
251       flags = FLAGS_NEW;
252
253       /* Handle the positional case (N$) */
254
255       param_num++;
256
257       this_param = dprintf_DollarString(fmt, &fmt);
258       if(0 == this_param)
259         /* we got no positional, get the next counter */
260         this_param = param_num;
261
262       if(this_param > max_param)
263         max_param = this_param;
264
265       /*
266        * The parameter with number 'i' should be used. Next, we need
267        * to get SIZE and TYPE of the parameter. Add the information
268        * to our array.
269        */
270
271       width = 0;
272       precision = 0;
273
274       /* Handle the flags */
275
276       while(dprintf_IsQualifierNoDollar(fmt)) {
277 #if defined(MP_HAVE_INT_EXTENSIONS)
278         if(!strncmp(fmt, "I32", 3)) {
279           flags |= FLAGS_LONG;
280           fmt += 3;
281         }
282         else if(!strncmp(fmt, "I64", 3)) {
283           flags |= FLAGS_LONGLONG;
284           fmt += 3;
285         }
286         else
287 #endif
288
289         switch(*fmt++) {
290         case ' ':
291           flags |= FLAGS_SPACE;
292           break;
293         case '+':
294           flags |= FLAGS_SHOWSIGN;
295           break;
296         case '-':
297           flags |= FLAGS_LEFT;
298           flags &= ~FLAGS_PAD_NIL;
299           break;
300         case '#':
301           flags |= FLAGS_ALT;
302           break;
303         case '.':
304           flags |= FLAGS_PREC;
305           if('*' == *fmt) {
306             /* The precision is picked from a specified parameter */
307
308             flags |= FLAGS_PRECPARAM;
309             fmt++;
310             param_num++;
311
312             i = dprintf_DollarString(fmt, &fmt);
313             if(i)
314               precision = i;
315             else
316               precision = param_num;
317
318             if(precision > max_param)
319               max_param = precision;
320           }
321           else {
322             flags |= FLAGS_PREC;
323             precision = strtol(fmt, &fmt, 10);
324           }
325           break;
326         case 'h':
327           flags |= FLAGS_SHORT;
328           break;
329 #if defined(MP_HAVE_INT_EXTENSIONS)
330         case 'I':
331 #if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
332           flags |= FLAGS_LONGLONG;
333 #else
334           flags |= FLAGS_LONG;
335 #endif
336           break;
337 #endif
338         case 'l':
339           if(flags & FLAGS_LONG)
340             flags |= FLAGS_LONGLONG;
341           else
342             flags |= FLAGS_LONG;
343           break;
344         case 'L':
345           flags |= FLAGS_LONGDOUBLE;
346           break;
347         case 'q':
348           flags |= FLAGS_LONGLONG;
349           break;
350         case 'z':
351           /* the code below generates a warning if -Wunreachable-code is
352              used */
353 #if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG)
354           flags |= FLAGS_LONGLONG;
355 #else
356           flags |= FLAGS_LONG;
357 #endif
358           break;
359         case 'O':
360 #if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
361           flags |= FLAGS_LONGLONG;
362 #else
363           flags |= FLAGS_LONG;
364 #endif
365           break;
366         case '0':
367           if(!(flags & FLAGS_LEFT))
368             flags |= FLAGS_PAD_NIL;
369           /* FALLTHROUGH */
370         case '1': case '2': case '3': case '4':
371         case '5': case '6': case '7': case '8': case '9':
372           flags |= FLAGS_WIDTH;
373           width = strtol(fmt-1, &fmt, 10);
374           break;
375         case '*':  /* Special case */
376           flags |= FLAGS_WIDTHPARAM;
377           param_num++;
378
379           i = dprintf_DollarString(fmt, &fmt);
380           if(i)
381             width = i;
382           else
383             width = param_num;
384           if(width > max_param)
385             max_param=width;
386           break;
387         default:
388           break;
389         }
390       } /* switch */
391
392       /* Handle the specifier */
393
394       i = this_param - 1;
395
396       switch (*fmt) {
397       case 'S':
398         flags |= FLAGS_ALT;
399         /* FALLTHROUGH */
400       case 's':
401         vto[i].type = FORMAT_STRING;
402         break;
403       case 'n':
404         vto[i].type = FORMAT_INTPTR;
405         break;
406       case 'p':
407         vto[i].type = FORMAT_PTR;
408         break;
409       case 'd': case 'i':
410         vto[i].type = FORMAT_INT;
411         break;
412       case 'u':
413         vto[i].type = FORMAT_INT;
414         flags |= FLAGS_UNSIGNED;
415         break;
416       case 'o':
417         vto[i].type = FORMAT_INT;
418         flags |= FLAGS_OCTAL;
419         break;
420       case 'x':
421         vto[i].type = FORMAT_INT;
422         flags |= FLAGS_HEX|FLAGS_UNSIGNED;
423         break;
424       case 'X':
425         vto[i].type = FORMAT_INT;
426         flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
427         break;
428       case 'c':
429         vto[i].type = FORMAT_INT;
430         flags |= FLAGS_CHAR;
431         break;
432       case 'f':
433         vto[i].type = FORMAT_DOUBLE;
434         break;
435       case 'e':
436         vto[i].type = FORMAT_DOUBLE;
437         flags |= FLAGS_FLOATE;
438         break;
439       case 'E':
440         vto[i].type = FORMAT_DOUBLE;
441         flags |= FLAGS_FLOATE|FLAGS_UPPER;
442         break;
443       case 'g':
444         vto[i].type = FORMAT_DOUBLE;
445         flags |= FLAGS_FLOATG;
446         break;
447       case 'G':
448         vto[i].type = FORMAT_DOUBLE;
449         flags |= FLAGS_FLOATG|FLAGS_UPPER;
450         break;
451       default:
452         vto[i].type = FORMAT_UNKNOWN;
453         break;
454       } /* switch */
455
456       vto[i].flags = flags;
457       vto[i].width = width;
458       vto[i].precision = precision;
459
460       if(flags & FLAGS_WIDTHPARAM) {
461         /* we have the width specified from a parameter, so we make that
462            parameter's info setup properly */
463         long k = width - 1;
464         vto[i].width = k;
465         vto[k].type = FORMAT_WIDTH;
466         vto[k].flags = FLAGS_NEW;
467         /* can't use width or precision of width! */
468         vto[k].width = 0;
469         vto[k].precision = 0;
470       }
471       if(flags & FLAGS_PRECPARAM) {
472         /* we have the precision specified from a parameter, so we make that
473            parameter's info setup properly */
474         long k = precision - 1;
475         vto[i].precision = k;
476         vto[k].type = FORMAT_WIDTH;
477         vto[k].flags = FLAGS_NEW;
478         /* can't use width or precision of width! */
479         vto[k].width = 0;
480         vto[k].precision = 0;
481       }
482       *endpos++ = fmt + 1; /* end of this sequence */
483     }
484   }
485
486   /* Read the arg list parameters into our data list */
487   for(i=0; i<max_param; i++) {
488     /* Width/precision arguments must be read before the main argument
489        they are attached to */
490     if(vto[i].flags & FLAGS_WIDTHPARAM) {
491       vto[vto[i].width].data.num.as_signed =
492         (mp_intmax_t)va_arg(arglist, int);
493     }
494     if(vto[i].flags & FLAGS_PRECPARAM) {
495       vto[vto[i].precision].data.num.as_signed =
496         (mp_intmax_t)va_arg(arglist, int);
497     }
498
499     switch (vto[i].type) {
500     case FORMAT_STRING:
501       vto[i].data.str = va_arg(arglist, char *);
502       break;
503
504     case FORMAT_INTPTR:
505     case FORMAT_UNKNOWN:
506     case FORMAT_PTR:
507       vto[i].data.ptr = va_arg(arglist, void *);
508       break;
509
510     case FORMAT_INT:
511 #ifdef HAVE_LONG_LONG_TYPE
512       if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
513         vto[i].data.num.as_unsigned =
514           (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
515       else if(vto[i].flags & FLAGS_LONGLONG)
516         vto[i].data.num.as_signed =
517           (mp_intmax_t)va_arg(arglist, mp_intmax_t);
518       else
519 #endif
520       {
521         if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
522           vto[i].data.num.as_unsigned =
523             (mp_uintmax_t)va_arg(arglist, unsigned long);
524         else if(vto[i].flags & FLAGS_LONG)
525           vto[i].data.num.as_signed =
526             (mp_intmax_t)va_arg(arglist, long);
527         else if(vto[i].flags & FLAGS_UNSIGNED)
528           vto[i].data.num.as_unsigned =
529             (mp_uintmax_t)va_arg(arglist, unsigned int);
530         else
531           vto[i].data.num.as_signed =
532             (mp_intmax_t)va_arg(arglist, int);
533       }
534       break;
535
536     case FORMAT_DOUBLE:
537       vto[i].data.dnum = va_arg(arglist, double);
538       break;
539
540     case FORMAT_WIDTH:
541       /* Argument has been read. Silently convert it into an integer
542        * for later use
543        */
544       vto[i].type = FORMAT_INT;
545       break;
546
547     default:
548       break;
549     }
550   }
551
552   return max_param;
553
554 }
555
556 static int dprintf_formatf(
557   void *data, /* untouched by format(), just sent to the stream() function in
558                  the second argument */
559   /* function pointer called for each output character */
560   int (*stream)(int, FILE *),
561   const char *format,    /* %-formatted string */
562   va_list ap_save) /* list of parameters */
563 {
564   /* Base-36 digits for numbers.  */
565   const char *digits = lower_digits;
566
567   /* Pointer into the format string.  */
568   char *f;
569
570   /* Number of characters written.  */
571   int done = 0;
572
573   long param; /* current parameter to read */
574   long param_num=0; /* parameter counter */
575
576   va_stack_t vto[MAX_PARAMETERS];
577   char *endpos[MAX_PARAMETERS];
578   char **end;
579
580   char work[BUFFSIZE];
581
582   va_stack_t *p;
583
584   /* 'workend' points to the final buffer byte position, but with an extra
585      byte as margin to avoid the (false?) warning Coverity gives us
586      otherwise */
587   char *workend = &work[sizeof(work) - 2];
588
589   /* Do the actual %-code parsing */
590   dprintf_Pass1(format, vto, endpos, ap_save);
591
592   end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
593                        created for us */
594
595   f = (char *)format;
596   while(*f != '\0') {
597     /* Format spec modifiers.  */
598     int is_alt;
599
600     /* Width of a field.  */
601     long width;
602
603     /* Precision of a field.  */
604     long prec;
605
606     /* Decimal integer is negative.  */
607     int is_neg;
608
609     /* Base of a number to be written.  */
610     long base;
611
612     /* Integral values to be written.  */
613     mp_uintmax_t num;
614
615     /* Used to convert negative in positive.  */
616     mp_intmax_t signed_num;
617
618     char *w;
619
620     if(*f != '%') {
621       /* This isn't a format spec, so write everything out until the next one
622          OR end of string is reached.  */
623       do {
624         OUTCHAR(*f);
625       } while(*++f && ('%' != *f));
626       continue;
627     }
628
629     ++f;
630
631     /* Check for "%%".  Note that although the ANSI standard lists
632        '%' as a conversion specifier, it says "The complete format
633        specification shall be `%%'," so we can avoid all the width
634        and precision processing.  */
635     if(*f == '%') {
636       ++f;
637       OUTCHAR('%');
638       continue;
639     }
640
641     /* If this is a positional parameter, the position must follow immediately
642        after the %, thus create a %<num>$ sequence */
643     param=dprintf_DollarString(f, &f);
644
645     if(!param)
646       param = param_num;
647     else
648       --param;
649
650     param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
651                     third %s will pick the 3rd argument */
652
653     p = &vto[param];
654
655     /* pick up the specified width */
656     if(p->flags & FLAGS_WIDTHPARAM) {
657       width = (long)vto[p->width].data.num.as_signed;
658       param_num++; /* since the width is extracted from a parameter, we
659                       must skip that to get to the next one properly */
660       if(width < 0) {
661         /* "A negative field width is taken as a '-' flag followed by a
662            positive field width." */
663         width = -width;
664         p->flags |= FLAGS_LEFT;
665         p->flags &= ~FLAGS_PAD_NIL;
666       }
667     }
668     else
669       width = p->width;
670
671     /* pick up the specified precision */
672     if(p->flags & FLAGS_PRECPARAM) {
673       prec = (long)vto[p->precision].data.num.as_signed;
674       param_num++; /* since the precision is extracted from a parameter, we
675                       must skip that to get to the next one properly */
676       if(prec < 0)
677         /* "A negative precision is taken as if the precision were
678            omitted." */
679         prec = -1;
680     }
681     else if(p->flags & FLAGS_PREC)
682       prec = p->precision;
683     else
684       prec = -1;
685
686     is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
687
688     switch (p->type) {
689     case FORMAT_INT:
690       num = p->data.num.as_unsigned;
691       if(p->flags & FLAGS_CHAR) {
692         /* Character.  */
693         if(!(p->flags & FLAGS_LEFT))
694           while(--width > 0)
695             OUTCHAR(' ');
696         OUTCHAR((char) num);
697         if(p->flags & FLAGS_LEFT)
698           while(--width > 0)
699             OUTCHAR(' ');
700         break;
701       }
702       if(p->flags & FLAGS_OCTAL) {
703         /* Octal unsigned integer.  */
704         base = 8;
705         goto unsigned_number;
706       }
707       else if(p->flags & FLAGS_HEX) {
708         /* Hexadecimal unsigned integer.  */
709
710         digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
711         base = 16;
712         goto unsigned_number;
713       }
714       else if(p->flags & FLAGS_UNSIGNED) {
715         /* Decimal unsigned integer.  */
716         base = 10;
717         goto unsigned_number;
718       }
719
720       /* Decimal integer.  */
721       base = 10;
722
723       is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
724       if(is_neg) {
725         /* signed_num might fail to hold absolute negative minimum by 1 */
726         signed_num = p->data.num.as_signed + (mp_intmax_t)1;
727         signed_num = -signed_num;
728         num = (mp_uintmax_t)signed_num;
729         num += (mp_uintmax_t)1;
730       }
731
732       goto number;
733
734       unsigned_number:
735       /* Unsigned number of base BASE.  */
736       is_neg = 0;
737
738       number:
739       /* Number of base BASE.  */
740
741       /* Supply a default precision if none was given.  */
742       if(prec == -1)
743         prec = 1;
744
745       /* Put the number in WORK.  */
746       w = workend;
747       while(num > 0) {
748         *w-- = digits[num % base];
749         num /= base;
750       }
751       width -= (long)(workend - w);
752       prec -= (long)(workend - w);
753
754       if(is_alt && base == 8 && prec <= 0) {
755         *w-- = '0';
756         --width;
757       }
758
759       if(prec > 0) {
760         width -= prec;
761         while(prec-- > 0)
762           *w-- = '0';
763       }
764
765       if(is_alt && base == 16)
766         width -= 2;
767
768       if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
769         --width;
770
771       if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
772         while(width-- > 0)
773           OUTCHAR(' ');
774
775       if(is_neg)
776         OUTCHAR('-');
777       else if(p->flags & FLAGS_SHOWSIGN)
778         OUTCHAR('+');
779       else if(p->flags & FLAGS_SPACE)
780         OUTCHAR(' ');
781
782       if(is_alt && base == 16) {
783         OUTCHAR('0');
784         if(p->flags & FLAGS_UPPER)
785           OUTCHAR('X');
786         else
787           OUTCHAR('x');
788       }
789
790       if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
791         while(width-- > 0)
792           OUTCHAR('0');
793
794       /* Write the number.  */
795       while(++w <= workend) {
796         OUTCHAR(*w);
797       }
798
799       if(p->flags & FLAGS_LEFT)
800         while(width-- > 0)
801           OUTCHAR(' ');
802       break;
803
804     case FORMAT_STRING:
805             /* String.  */
806       {
807         static const char null[] = "(nil)";
808         const char *str;
809         size_t len;
810
811         str = (char *) p->data.str;
812         if(str == NULL) {
813           /* Write null[] if there's space.  */
814           if(prec == -1 || prec >= (long) sizeof(null) - 1) {
815             str = null;
816             len = sizeof(null) - 1;
817             /* Disable quotes around (nil) */
818             p->flags &= (~FLAGS_ALT);
819           }
820           else {
821             str = "";
822             len = 0;
823           }
824         }
825         else if(prec != -1)
826           len = (size_t)prec;
827         else
828           len = strlen(str);
829
830         width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
831
832         if(p->flags & FLAGS_ALT)
833           OUTCHAR('"');
834
835         if(!(p->flags&FLAGS_LEFT))
836           while(width-- > 0)
837             OUTCHAR(' ');
838
839         while((len-- > 0) && *str)
840           OUTCHAR(*str++);
841         if(p->flags&FLAGS_LEFT)
842           while(width-- > 0)
843             OUTCHAR(' ');
844
845         if(p->flags & FLAGS_ALT)
846           OUTCHAR('"');
847       }
848       break;
849
850     case FORMAT_PTR:
851       /* Generic pointer.  */
852       {
853         void *ptr;
854         ptr = (void *) p->data.ptr;
855         if(ptr != NULL) {
856           /* If the pointer is not NULL, write it as a %#x spec.  */
857           base = 16;
858           digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
859           is_alt = 1;
860           num = (size_t) ptr;
861           is_neg = 0;
862           goto number;
863         }
864         else {
865           /* Write "(nil)" for a nil pointer.  */
866           static const char strnil[] = "(nil)";
867           const char *point;
868
869           width -= (long)(sizeof(strnil) - 1);
870           if(p->flags & FLAGS_LEFT)
871             while(width-- > 0)
872               OUTCHAR(' ');
873           for(point = strnil; *point != '\0'; ++point)
874             OUTCHAR(*point);
875           if(! (p->flags & FLAGS_LEFT))
876             while(width-- > 0)
877               OUTCHAR(' ');
878         }
879       }
880       break;
881
882     case FORMAT_DOUBLE:
883       {
884         char formatbuf[32]="%";
885         char *fptr = &formatbuf[1];
886         size_t left = sizeof(formatbuf)-strlen(formatbuf);
887         int len;
888
889         width = -1;
890         if(p->flags & FLAGS_WIDTH)
891           width = p->width;
892         else if(p->flags & FLAGS_WIDTHPARAM)
893           width = (long)vto[p->width].data.num.as_signed;
894
895         prec = -1;
896         if(p->flags & FLAGS_PREC)
897           prec = p->precision;
898         else if(p->flags & FLAGS_PRECPARAM)
899           prec = (long)vto[p->precision].data.num.as_signed;
900
901         if(p->flags & FLAGS_LEFT)
902           *fptr++ = '-';
903         if(p->flags & FLAGS_SHOWSIGN)
904           *fptr++ = '+';
905         if(p->flags & FLAGS_SPACE)
906           *fptr++ = ' ';
907         if(p->flags & FLAGS_ALT)
908           *fptr++ = '#';
909
910         *fptr = 0;
911
912         if(width >= 0) {
913           /* RECURSIVE USAGE */
914           len = curl_msnprintf(fptr, left, "%ld", width);
915           fptr += len;
916           left -= len;
917         }
918         if(prec >= 0) {
919           /* RECURSIVE USAGE */
920           len = curl_msnprintf(fptr, left, ".%ld", prec);
921           fptr += len;
922         }
923         if(p->flags & FLAGS_LONG)
924           *fptr++ = 'l';
925
926         if(p->flags & FLAGS_FLOATE)
927           *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
928         else if(p->flags & FLAGS_FLOATG)
929           *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
930         else
931           *fptr++ = 'f';
932
933         *fptr = 0; /* and a final zero termination */
934
935         /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
936            output characters */
937         (sprintf)(work, formatbuf, p->data.dnum);
938
939         for(fptr=work; *fptr; fptr++)
940           OUTCHAR(*fptr);
941       }
942       break;
943
944     case FORMAT_INTPTR:
945       /* Answer the count of characters written.  */
946 #ifdef HAVE_LONG_LONG_TYPE
947       if(p->flags & FLAGS_LONGLONG)
948         *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
949       else
950 #endif
951         if(p->flags & FLAGS_LONG)
952           *(long *) p->data.ptr = (long)done;
953       else if(!(p->flags & FLAGS_SHORT))
954         *(int *) p->data.ptr = (int)done;
955       else
956         *(short *) p->data.ptr = (short)done;
957       break;
958
959     default:
960       break;
961     }
962     f = *end++; /* goto end of %-code */
963
964   }
965   return done;
966 }
967
968 /* fputc() look-alike */
969 static int addbyter(int output, FILE *data)
970 {
971   struct nsprintf *infop=(struct nsprintf *)data;
972   unsigned char outc = (unsigned char)output;
973
974   if(infop->length < infop->max) {
975     /* only do this if we haven't reached max length yet */
976     infop->buffer[0] = outc; /* store */
977     infop->buffer++; /* increase pointer */
978     infop->length++; /* we are now one byte larger */
979     return outc;     /* fputc() returns like this on success */
980   }
981   return -1;
982 }
983
984 int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
985                     va_list ap_save)
986 {
987   int retcode;
988   struct nsprintf info;
989
990   info.buffer = buffer;
991   info.length = 0;
992   info.max = maxlength;
993
994   retcode = dprintf_formatf(&info, addbyter, format, ap_save);
995   if(info.max) {
996     /* we terminate this with a zero byte */
997     if(info.max == info.length)
998       /* we're at maximum, scrap the last letter */
999       info.buffer[-1] = 0;
1000     else
1001       info.buffer[0] = 0;
1002   }
1003   return retcode;
1004 }
1005
1006 int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
1007 {
1008   int retcode;
1009   va_list ap_save; /* argument pointer */
1010   va_start(ap_save, format);
1011   retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
1012   va_end(ap_save);
1013   return retcode;
1014 }
1015
1016 /* fputc() look-alike */
1017 static int alloc_addbyter(int output, FILE *data)
1018 {
1019   struct asprintf *infop=(struct asprintf *)data;
1020   unsigned char outc = (unsigned char)output;
1021
1022   if(!infop->buffer) {
1023     infop->buffer = malloc(32);
1024     if(!infop->buffer) {
1025       infop->fail = 1;
1026       return -1; /* fail */
1027     }
1028     infop->alloc = 32;
1029     infop->len =0;
1030   }
1031   else if(infop->len+1 >= infop->alloc) {
1032     char *newptr;
1033
1034     newptr = realloc(infop->buffer, infop->alloc*2);
1035
1036     if(!newptr) {
1037       infop->fail = 1;
1038       return -1; /* fail */
1039     }
1040     infop->buffer = newptr;
1041     infop->alloc *= 2;
1042   }
1043
1044   infop->buffer[ infop->len ] = outc;
1045
1046   infop->len++;
1047
1048   return outc; /* fputc() returns like this on success */
1049 }
1050
1051 char *curl_maprintf(const char *format, ...)
1052 {
1053   va_list ap_save; /* argument pointer */
1054   int retcode;
1055   struct asprintf info;
1056
1057   info.buffer = NULL;
1058   info.len = 0;
1059   info.alloc = 0;
1060   info.fail = 0;
1061
1062   va_start(ap_save, format);
1063   retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
1064   va_end(ap_save);
1065   if((-1 == retcode) || info.fail) {
1066     if(info.alloc)
1067       free(info.buffer);
1068     return NULL;
1069   }
1070   if(info.alloc) {
1071     info.buffer[info.len] = 0; /* we terminate this with a zero byte */
1072     return info.buffer;
1073   }
1074   else
1075     return strdup("");
1076 }
1077
1078 char *curl_mvaprintf(const char *format, va_list ap_save)
1079 {
1080   int retcode;
1081   struct asprintf info;
1082
1083   info.buffer = NULL;
1084   info.len = 0;
1085   info.alloc = 0;
1086   info.fail = 0;
1087
1088   retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
1089   if((-1 == retcode) || info.fail) {
1090     if(info.alloc)
1091       free(info.buffer);
1092     return NULL;
1093   }
1094
1095   if(info.alloc) {
1096     info.buffer[info.len] = 0; /* we terminate this with a zero byte */
1097     return info.buffer;
1098   }
1099   else
1100     return strdup("");
1101 }
1102
1103 static int storebuffer(int output, FILE *data)
1104 {
1105   char **buffer = (char **)data;
1106   unsigned char outc = (unsigned char)output;
1107   **buffer = outc;
1108   (*buffer)++;
1109   return outc; /* act like fputc() ! */
1110 }
1111
1112 int curl_msprintf(char *buffer, const char *format, ...)
1113 {
1114   va_list ap_save; /* argument pointer */
1115   int retcode;
1116   va_start(ap_save, format);
1117   retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
1118   va_end(ap_save);
1119   *buffer=0; /* we terminate this with a zero byte */
1120   return retcode;
1121 }
1122
1123 int curl_mprintf(const char *format, ...)
1124 {
1125   int retcode;
1126   va_list ap_save; /* argument pointer */
1127   va_start(ap_save, format);
1128
1129   retcode = dprintf_formatf(stdout, fputc, format, ap_save);
1130   va_end(ap_save);
1131   return retcode;
1132 }
1133
1134 int curl_mfprintf(FILE *whereto, const char *format, ...)
1135 {
1136   int retcode;
1137   va_list ap_save; /* argument pointer */
1138   va_start(ap_save, format);
1139   retcode = dprintf_formatf(whereto, fputc, format, ap_save);
1140   va_end(ap_save);
1141   return retcode;
1142 }
1143
1144 int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
1145 {
1146   int retcode;
1147   retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
1148   *buffer=0; /* we terminate this with a zero byte */
1149   return retcode;
1150 }
1151
1152 int curl_mvprintf(const char *format, va_list ap_save)
1153 {
1154   return dprintf_formatf(stdout, fputc, format, ap_save);
1155 }
1156
1157 int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
1158 {
1159   return dprintf_formatf(whereto, fputc, format, ap_save);
1160 }