1 /****************************************************************************
3 * $Id: mprintf.c,v 1.5 2007-03-15 19:22:13 andy Exp $
5 *************************************************************************
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.
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.
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).
23 * Current restrictions:
24 * - Max 128 parameters
25 * - No 'long double' support.
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/
34 #include <sys/types.h>
41 #if defined(DJGPP) && (DJGPP_MINOR < 4)
42 #undef _MPRINTF_REPLACE /* don't use x_was_used() here */
45 #include <curl/mprintf.h>
47 #ifndef SIZEOF_LONG_DOUBLE
48 #define SIZEOF_LONG_DOUBLE 0
52 /* default to 4 bytes for size_t unless defined in the config.h */
53 #define SIZEOF_SIZE_T 4
58 #define LONG_LONG long long
63 /* The last #include file should be: */
66 #define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
67 #define MAX_PARAMETERS 128 /* lame static limit */
77 # define TRUE ((char)(1 == 1))
78 # define FALSE ((char)(0 == 1))
86 /* Lower-case digits. */
87 static const char lower_digits
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
89 /* Upper-case digits. */
90 static const char upper_digits
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
94 if(stream((unsigned char)(x), (FILE *)data) != -1) \
97 return done; /* return immediately on failure */ \
100 /* Data type to read from the arglist */
111 FORMAT_WIDTH
/* For internal use */
114 /* convertion and display flags */
118 FLAGS_SHOWSIGN
= 1<<1,
123 FLAGS_LONGLONG
= 1<<6,
124 FLAGS_LONGDOUBLE
= 1<<7,
125 FLAGS_PAD_NIL
= 1<<8,
126 FLAGS_UNSIGNED
= 1<<9,
130 FLAGS_WIDTH
= 1<<13, /* '*' or '*<num>$' used */
131 FLAGS_WIDTHPARAM
= 1<<14, /* width PARAMETER was specified */
132 FLAGS_PREC
= 1<<15, /* precision was specified */
133 FLAGS_PRECPARAM
= 1<<16, /* precision PARAMETER was specified */
134 FLAGS_CHAR
= 1<<17, /* %c story */
135 FLAGS_FLOATE
= 1<<18, /* %e or %E */
136 FLAGS_FLOATG
= 1<<19 /* %g or %G */
142 long width
; /* width OR width parameter number */
143 long precision
; /* precision OR precision parameter number */
162 char *buffer
; /* allocated buffer */
163 size_t len
; /* length of string */
164 size_t alloc
; /* length of alloc */
165 bool fail
; /* TRUE if an alloc has failed and thus the output is not
169 int curl_msprintf(char *buffer
, const char *format
, ...);
171 static long dprintf_DollarString(char *input
, char **end
)
174 while(ISDIGIT(*input
)) {
176 number
+= *input
-'0';
179 if(number
&& ('$'==*input
++)) {
186 static BOOL
dprintf_IsQualifierNoDollar(char c
)
189 case '-': case '+': case ' ': case '#': case '.':
190 case '0': case '1': case '2': case '3': case '4':
191 case '5': case '6': case '7': case '8': case '9':
192 case 'h': case 'l': case 'L': case 'z': case 'q':
200 #ifdef DPRINTF_DEBUG2
201 int dprintf_Pass1Report(va_stack_t
*vto
, int max
)
208 for(i
=0; i
<max
; i
++) {
210 switch(vto
[i
].type
) {
226 case FORMAT_LONGLONG
:
232 case FORMAT_LONGDOUBLE
:
233 type
= "long double";
240 for(bit
=0; bit
<31; bit
++) {
241 flags
= vto
[i
].flags
& (1<<bit
);
243 if(flags
& FLAGS_SPACE
)
244 strcat(buffer
, "space ");
245 else if(flags
& FLAGS_SHOWSIGN
)
246 strcat(buffer
, "plus ");
247 else if(flags
& FLAGS_LEFT
)
248 strcat(buffer
, "left ");
249 else if(flags
& FLAGS_ALT
)
250 strcat(buffer
, "alt ");
251 else if(flags
& FLAGS_SHORT
)
252 strcat(buffer
, "short ");
253 else if(flags
& FLAGS_LONG
)
254 strcat(buffer
, "long ");
255 else if(flags
& FLAGS_LONGLONG
)
256 strcat(buffer
, "longlong ");
257 else if(flags
& FLAGS_LONGDOUBLE
)
258 strcat(buffer
, "longdouble ");
259 else if(flags
& FLAGS_PAD_NIL
)
260 strcat(buffer
, "padnil ");
261 else if(flags
& FLAGS_UNSIGNED
)
262 strcat(buffer
, "unsigned ");
263 else if(flags
& FLAGS_OCTAL
)
264 strcat(buffer
, "octal ");
265 else if(flags
& FLAGS_HEX
)
266 strcat(buffer
, "hex ");
267 else if(flags
& FLAGS_UPPER
)
268 strcat(buffer
, "upper ");
269 else if(flags
& FLAGS_WIDTH
)
270 strcat(buffer
, "width ");
271 else if(flags
& FLAGS_WIDTHPARAM
)
272 strcat(buffer
, "widthparam ");
273 else if(flags
& FLAGS_PREC
)
274 strcat(buffer
, "precision ");
275 else if(flags
& FLAGS_PRECPARAM
)
276 strcat(buffer
, "precparam ");
277 else if(flags
& FLAGS_CHAR
)
278 strcat(buffer
, "char ");
279 else if(flags
& FLAGS_FLOATE
)
280 strcat(buffer
, "floate ");
281 else if(flags
& FLAGS_FLOATG
)
282 strcat(buffer
, "floatg ");
284 printf("REPORT: %d. %s [%s]\n", i
, type
, buffer
);
292 /******************************************************************
295 * Create an index with the type of each parameter entry and its
296 * value (may vary in size)
298 ******************************************************************/
300 static long dprintf_Pass1(char *format
, va_stack_t
*vto
, char **endpos
,
316 continue; /* while */
321 /* Handle the positional case (N$) */
325 this_param
= dprintf_DollarString(fmt
, &fmt
);
327 /* we got no positional, get the next counter */
328 this_param
= param_num
;
330 if (this_param
> max_param
)
331 max_param
= this_param
;
334 * The parameter with number 'i' should be used. Next, we need
335 * to get SIZE and TYPE of the parameter. Add the information
342 /* Handle the flags */
344 while (dprintf_IsQualifierNoDollar(*fmt
)) {
347 flags
|= FLAGS_SPACE
;
350 flags
|= FLAGS_SHOWSIGN
;
354 flags
&= ~FLAGS_PAD_NIL
;
362 /* The precision is picked from a specified parameter */
364 flags
|= FLAGS_PRECPARAM
;
368 i
= dprintf_DollarString(fmt
, &fmt
);
372 precision
= param_num
;
374 if (precision
> max_param
)
375 max_param
= precision
;
379 precision
= strtol(fmt
, &fmt
, 10);
383 flags
|= FLAGS_SHORT
;
386 if (flags
& FLAGS_LONG
)
387 flags
|= FLAGS_LONGLONG
;
392 flags
|= FLAGS_LONGDOUBLE
;
395 flags
|= FLAGS_LONGLONG
;
398 /* the code below generates a warning if -Wunreachable-code is
401 flags
|= FLAGS_LONGLONG
;
407 #if SIZEOF_CURL_OFF_T > 4
408 flags
|= FLAGS_LONGLONG
;
414 if (!(flags
& FLAGS_LEFT
))
415 flags
|= FLAGS_PAD_NIL
;
417 case '1': case '2': case '3': case '4':
418 case '5': case '6': case '7': case '8': case '9':
419 flags
|= FLAGS_WIDTH
;
420 width
= strtol(fmt
-1, &fmt
, 10);
422 case '*': /* Special case */
423 flags
|= FLAGS_WIDTHPARAM
;
426 i
= dprintf_DollarString(fmt
, &fmt
);
431 if(width
> max_param
)
439 /* Handle the specifier */
448 vto
[i
].type
= FORMAT_STRING
;
451 vto
[i
].type
= FORMAT_INTPTR
;
454 vto
[i
].type
= FORMAT_PTR
;
457 vto
[i
].type
= FORMAT_INT
;
460 vto
[i
].type
= FORMAT_INT
;
461 flags
|= FLAGS_UNSIGNED
;
464 vto
[i
].type
= FORMAT_INT
;
465 flags
|= FLAGS_OCTAL
;
468 vto
[i
].type
= FORMAT_INT
;
472 vto
[i
].type
= FORMAT_INT
;
473 flags
|= FLAGS_HEX
|FLAGS_UPPER
;
476 vto
[i
].type
= FORMAT_INT
;
480 vto
[i
].type
= FORMAT_DOUBLE
;
483 vto
[i
].type
= FORMAT_DOUBLE
;
484 flags
|= FLAGS_FLOATE
;
487 vto
[i
].type
= FORMAT_DOUBLE
;
488 flags
|= FLAGS_FLOATE
|FLAGS_UPPER
;
491 vto
[i
].type
= FORMAT_DOUBLE
;
492 flags
|= FLAGS_FLOATG
;
495 vto
[i
].type
= FORMAT_DOUBLE
;
496 flags
|= FLAGS_FLOATG
|FLAGS_UPPER
;
499 vto
[i
].type
= FORMAT_UNKNOWN
;
503 vto
[i
].flags
= flags
;
504 vto
[i
].width
= width
;
505 vto
[i
].precision
= precision
;
507 if (flags
& FLAGS_WIDTHPARAM
) {
508 /* we have the width specified from a parameter, so we make that
509 parameter's info setup properly */
510 vto
[i
].width
= width
- 1;
512 vto
[i
].type
= FORMAT_WIDTH
;
513 vto
[i
].flags
= FLAGS_NEW
;
514 vto
[i
].precision
= vto
[i
].width
= 0; /* can't use width or precision
517 if (flags
& FLAGS_PRECPARAM
) {
518 /* we have the precision specified from a parameter, so we make that
519 parameter's info setup properly */
520 vto
[i
].precision
= precision
- 1;
522 vto
[i
].type
= FORMAT_WIDTH
;
523 vto
[i
].flags
= FLAGS_NEW
;
524 vto
[i
].precision
= vto
[i
].width
= 0; /* can't use width or precision
527 *endpos
++ = fmt
+ 1; /* end of this sequence */
531 #ifdef DPRINTF_DEBUG2
532 dprintf_Pass1Report(vto
, max_param
);
535 /* Read the arg list parameters into our data list */
536 for (i
=0; i
<max_param
; i
++) {
537 if ((i
+ 1 < max_param
) && (vto
[i
+ 1].type
== FORMAT_WIDTH
))
539 /* Width/precision arguments must be read before the main argument
540 * they are attached to
542 vto
[i
+ 1].data
.num
= va_arg(arglist
, int);
548 vto
[i
].data
.str
= va_arg(arglist
, char *);
554 vto
[i
].data
.ptr
= va_arg(arglist
, void *);
559 if(vto
[i
].flags
& FLAGS_LONGLONG
)
560 vto
[i
].data
.lnum
= va_arg(arglist
, LONG_LONG
);
563 if(vto
[i
].flags
& FLAGS_LONG
)
564 vto
[i
].data
.num
= va_arg(arglist
, long);
566 vto
[i
].data
.num
= va_arg(arglist
, int);
570 vto
[i
].data
.dnum
= va_arg(arglist
, double);
574 /* Argument has been read. Silently convert it into an integer
577 vto
[i
].type
= FORMAT_INT
;
589 static int dprintf_formatf(
590 void *data
, /* untouched by format(), just sent to the stream() function in
591 the second argument */
592 /* function pointer called for each output character */
593 int (*stream
)(int, FILE *),
594 const char *format
, /* %-formatted string */
595 va_list ap_save
) /* list of parameters */
597 /* Base-36 digits for numbers. */
598 const char *digits
= lower_digits
;
600 /* Pointer into the format string. */
603 /* Number of characters written. */
606 long param
; /* current parameter to read */
607 long param_num
=0; /* parameter counter */
609 va_stack_t vto
[MAX_PARAMETERS
];
610 char *endpos
[MAX_PARAMETERS
];
617 /* Do the actual %-code parsing */
618 dprintf_Pass1((char *)format
, vto
, endpos
, ap_save
);
620 end
= &endpos
[0]; /* the initial end-position from the list dprintf_Pass1()
625 /* Format spec modifiers. */
628 /* Width of a field. */
631 /* Precision of a field. */
634 /* Decimal integer is negative. */
637 /* Base of a number to be written. */
640 /* Integral values to be written. */
642 unsigned LONG_LONG num
;
649 /* This isn't a format spec, so write everything out until the next one
650 OR end of string is reached. */
653 } while(*++f
&& ('%' != *f
));
659 /* Check for "%%". Note that although the ANSI standard lists
660 '%' as a conversion specifier, it says "The complete format
661 specification shall be `%%'," so we can avoid all the width
662 and precision processing. */
669 /* If this is a positional parameter, the position must follow imediately
670 after the %, thus create a %<num>$ sequence */
671 param
=dprintf_DollarString(f
, &f
);
678 param_num
++; /* increase this always to allow "%2$s %1$s %s" and then the
679 third %s will pick the 3rd argument */
683 /* pick up the specified width */
684 if(p
->flags
& FLAGS_WIDTHPARAM
)
685 width
= vto
[p
->width
].data
.num
;
689 /* pick up the specified precision */
690 if(p
->flags
& FLAGS_PRECPARAM
)
691 prec
= vto
[p
->precision
].data
.num
;
692 else if(p
->flags
& FLAGS_PREC
)
697 alt
= (p
->flags
& FLAGS_ALT
)?TRUE
:FALSE
;
702 if(p
->flags
& FLAGS_CHAR
) {
704 if (!(p
->flags
& FLAGS_LEFT
))
708 if (p
->flags
& FLAGS_LEFT
)
713 if(p
->flags
& FLAGS_UNSIGNED
) {
714 /* Decimal unsigned integer. */
716 goto unsigned_number
;
718 if(p
->flags
& FLAGS_OCTAL
) {
719 /* Octal unsigned integer. */
721 goto unsigned_number
;
723 if(p
->flags
& FLAGS_HEX
) {
724 /* Hexadecimal unsigned integer. */
726 digits
= (p
->flags
& FLAGS_UPPER
)? upper_digits
: lower_digits
;
728 goto unsigned_number
;
731 /* Decimal integer. */
735 if(p
->flags
& FLAGS_LONGLONG
) {
737 is_neg
= p
->data
.lnum
< 0;
738 num
= is_neg
? (- p
->data
.lnum
) : p
->data
.lnum
;
743 signed_num
= (long) num
;
744 is_neg
= signed_num
< 0;
745 num
= is_neg
? (- signed_num
) : signed_num
;
750 /* Unsigned number of base BASE. */
754 /* Number of base BASE. */
756 char *workend
= &work
[sizeof(work
) - 1];
759 /* Supply a default precision if none was given. */
763 /* Put the number in WORK. */
766 *w
-- = digits
[num
% base
];
769 width
-= (long)(workend
- w
);
770 prec
-= (long)(workend
- w
);
772 if (alt
&& base
== 8 && prec
<= 0) {
783 if (alt
&& base
== 16)
786 if (is_neg
|| (p
->flags
& FLAGS_SHOWSIGN
) || (p
->flags
& FLAGS_SPACE
))
789 if (!(p
->flags
& FLAGS_LEFT
) && !(p
->flags
& FLAGS_PAD_NIL
))
795 else if (p
->flags
& FLAGS_SHOWSIGN
)
797 else if (p
->flags
& FLAGS_SPACE
)
800 if (alt
&& base
== 16) {
802 if(p
->flags
& FLAGS_UPPER
)
808 if (!(p
->flags
& FLAGS_LEFT
) && (p
->flags
& FLAGS_PAD_NIL
))
812 /* Write the number. */
813 while (++w
<= workend
) {
817 if (p
->flags
& FLAGS_LEFT
)
826 static const char null
[] = "(nil)";
830 str
= (char *) p
->data
.str
;
832 /* Write null[] if there's space. */
833 if (prec
== -1 || prec
>= (long) sizeof(null
) - 1) {
835 len
= sizeof(null
) - 1;
836 /* Disable quotes around (nil) */
837 p
->flags
&= (~FLAGS_ALT
);
847 if (prec
!= -1 && (size_t) prec
< len
)
851 if (p
->flags
& FLAGS_ALT
)
854 if (!(p
->flags
&FLAGS_LEFT
))
860 if (p
->flags
&FLAGS_LEFT
)
864 if (p
->flags
& FLAGS_ALT
)
870 /* Generic pointer. */
873 ptr
= (void *) p
->data
.ptr
;
875 /* If the pointer is not NULL, write it as a %#x spec. */
877 digits
= (p
->flags
& FLAGS_UPPER
)? upper_digits
: lower_digits
;
884 /* Write "(nil)" for a nil pointer. */
885 static const char strnil
[] = "(nil)";
888 width
-= sizeof(strnil
) - 1;
889 if (p
->flags
& FLAGS_LEFT
)
892 for (point
= strnil
; *point
!= '\0'; ++point
)
894 if (! (p
->flags
& FLAGS_LEFT
))
903 char formatbuf
[32]="%";
905 size_t left
= sizeof(formatbuf
)-strlen(formatbuf
);
909 if (p
->flags
& FLAGS_WIDTH
)
911 else if (p
->flags
& FLAGS_WIDTHPARAM
)
912 width
= vto
[p
->width
].data
.num
;
915 if (p
->flags
& FLAGS_PREC
)
917 else if (p
->flags
& FLAGS_PRECPARAM
)
918 prec
= vto
[p
->precision
].data
.num
;
920 if (p
->flags
& FLAGS_LEFT
)
921 strcat(formatbuf
, "-");
922 if (p
->flags
& FLAGS_SHOWSIGN
)
923 strcat(formatbuf
, "+");
924 if (p
->flags
& FLAGS_SPACE
)
925 strcat(formatbuf
, " ");
926 if (p
->flags
& FLAGS_ALT
)
927 strcat(formatbuf
, "#");
929 fptr
=&formatbuf
[strlen(formatbuf
)];
932 /* RECURSIVE USAGE */
933 len
= curl_msnprintf(fptr
, left
, "%ld", width
);
938 /* RECURSIVE USAGE */
939 len
= curl_msnprintf(fptr
, left
, ".%ld", prec
);
943 if (p
->flags
& FLAGS_LONG
)
946 if (p
->flags
& FLAGS_FLOATE
)
947 *fptr
++ = p
->flags
&FLAGS_UPPER
? 'E':'e';
948 else if (p
->flags
& FLAGS_FLOATG
)
949 *fptr
++ = p
->flags
& FLAGS_UPPER
? 'G' : 'g';
953 *fptr
= 0; /* and a final zero termination */
955 /* NOTE NOTE NOTE!! Not all sprintf() implementations returns number
956 of output characters */
957 (sprintf
)(work
, formatbuf
, p
->data
.dnum
);
959 for(fptr
=work
; *fptr
; fptr
++)
965 /* Answer the count of characters written. */
967 if (p
->flags
& FLAGS_LONGLONG
)
968 *(LONG_LONG
*) p
->data
.ptr
= (LONG_LONG
)done
;
971 if (p
->flags
& FLAGS_LONG
)
972 *(long *) p
->data
.ptr
= (long)done
;
973 else if (!(p
->flags
& FLAGS_SHORT
))
974 *(int *) p
->data
.ptr
= (int)done
;
976 *(short *) p
->data
.ptr
= (short)done
;
982 f
= *end
++; /* goto end of %-code */
988 /* fputc() look-alike */
989 static int addbyter(int output
, FILE *data
)
991 struct nsprintf
*infop
=(struct nsprintf
*)data
;
992 unsigned char outc
= (unsigned char)output
;
994 if(infop
->length
< infop
->max
) {
995 /* only do this if we haven't reached max length yet */
996 infop
->buffer
[0] = outc
; /* store */
997 infop
->buffer
++; /* increase pointer */
998 infop
->length
++; /* we are now one byte larger */
999 return outc
; /* fputc() returns like this on success */
1004 int curl_mvsnprintf(char *buffer
, size_t maxlength
, const char *format
,
1008 struct nsprintf info
;
1010 info
.buffer
= buffer
;
1012 info
.max
= maxlength
;
1014 retcode
= dprintf_formatf(&info
, addbyter
, format
, ap_save
);
1016 /* we terminate this with a zero byte */
1017 if(info
.max
== info
.length
)
1018 /* we're at maximum, scrap the last letter */
1019 info
.buffer
[-1] = 0;
1026 int curl_msnprintf(char *buffer
, size_t maxlength
, const char *format
, ...)
1029 va_list ap_save
; /* argument pointer */
1030 va_start(ap_save
, format
);
1031 retcode
= curl_mvsnprintf(buffer
, maxlength
, format
, ap_save
);
1036 /* fputc() look-alike */
1037 static int alloc_addbyter(int output
, FILE *data
)
1039 struct asprintf
*infop
=(struct asprintf
*)data
;
1040 unsigned char outc
= (unsigned char)output
;
1042 if(!infop
->buffer
) {
1043 infop
->buffer
=(char *)malloc(32);
1044 if(!infop
->buffer
) {
1046 return -1; /* fail */
1051 else if(infop
->len
+1 >= infop
->alloc
) {
1054 newptr
= (char *)realloc(infop
->buffer
, infop
->alloc
*2);
1060 infop
->buffer
= newptr
;
1064 infop
->buffer
[ infop
->len
] = outc
;
1068 return outc
; /* fputc() returns like this on success */
1071 char *curl_maprintf(const char *format
, ...)
1073 va_list ap_save
; /* argument pointer */
1075 struct asprintf info
;
1082 va_start(ap_save
, format
);
1083 retcode
= dprintf_formatf(&info
, alloc_addbyter
, format
, ap_save
);
1085 if((-1 == retcode
) || info
.fail
) {
1091 info
.buffer
[info
.len
] = 0; /* we terminate this with a zero byte */
1098 char *curl_mvaprintf(const char *format
, va_list ap_save
)
1101 struct asprintf info
;
1108 retcode
= dprintf_formatf(&info
, alloc_addbyter
, format
, ap_save
);
1109 if((-1 == retcode
) || info
.fail
) {
1116 info
.buffer
[info
.len
] = 0; /* we terminate this with a zero byte */
1123 static int storebuffer(int output
, FILE *data
)
1125 char **buffer
= (char **)data
;
1126 unsigned char outc
= (unsigned char)output
;
1129 return outc
; /* act like fputc() ! */
1132 int curl_msprintf(char *buffer
, const char *format
, ...)
1134 va_list ap_save
; /* argument pointer */
1136 va_start(ap_save
, format
);
1137 retcode
= dprintf_formatf(&buffer
, storebuffer
, format
, ap_save
);
1139 *buffer
=0; /* we terminate this with a zero byte */
1143 int curl_mprintf(const char *format
, ...)
1146 va_list ap_save
; /* argument pointer */
1147 va_start(ap_save
, format
);
1149 retcode
= dprintf_formatf(stdout
, fputc
, format
, ap_save
);
1154 int curl_mfprintf(FILE *whereto
, const char *format
, ...)
1157 va_list ap_save
; /* argument pointer */
1158 va_start(ap_save
, format
);
1159 retcode
= dprintf_formatf(whereto
, fputc
, format
, ap_save
);
1164 int curl_mvsprintf(char *buffer
, const char *format
, va_list ap_save
)
1167 retcode
= dprintf_formatf(&buffer
, storebuffer
, format
, ap_save
);
1168 *buffer
=0; /* we terminate this with a zero byte */
1172 int curl_mvprintf(const char *format
, va_list ap_save
)
1174 return dprintf_formatf(stdout
, fputc
, format
, ap_save
);
1177 int curl_mvfprintf(FILE *whereto
, const char *format
, va_list ap_save
)
1179 return dprintf_formatf(whereto
, fputc
, format
, ap_save
);
1182 #ifdef DPRINTF_DEBUG
1190 long long test
= 0x1000000000LL
;
1191 curl_mprintf("%lld %lld %lld\n", one
, two
, test
);
1194 curl_mprintf("%3d %5d\n", 10, 1998);
1196 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);
1200 memset(ptr
, 55, strlen(ptr
)+1);
1205 curl_mprintf(buffer
, "%s %s %d", "daniel", "stenberg", 19988);
1208 curl_mfprintf(stderr
, "%s %#08x\n", "dummy", 65);
1210 printf("%s %#08x\n", "dummy", 65);
1212 double tryout
= 3.14156592;
1213 curl_mprintf(buffer
, "%.2g %G %f %e %E", tryout
, tryout
, tryout
, tryout
, tryout
);
1215 printf("%.2g %G %f %e %E\n", tryout
, tryout
, tryout
, tryout
, tryout
);