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