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