1 /****************************************************************************
3 * $Id: mprintf.c,v 1.1.1.1 1999-12-29 14:21:34 bagder Exp $
5 *************************************************************************
8 * A merge of Bjorn Reese's format() function and Daniel's dsprintf()
9 * 1.0. A full blooded printf() clone with full support for <num>$
10 * everywhere (parameters, widths and precisions) including variabled
11 * sized parameters (like doubles, long longs, long doubles and even
12 * void * in 64-bit architectures).
14 * Current restrictions:
15 * - Max 128 parameters
16 * - No 'long double' support.
18 *************************************************************************
23 * - Updated version number.
24 * - Corrected a static non-zero prefixed width problem.
27 * Added daprintf() and dvaprintf() for allocated printf() and vprintf().
28 * They return an allocated buffer with the result inside. The result must
33 * Converted all non-printable (and non-whitespace) characters into
34 * their decimal ASCII value preceeded by a '\' character
35 * (this only applies to snprintf family so far)
37 * Added %S (which is the same as %#s)
41 * Fixed precision and width qualifiers (%.*s)
43 * Added support for snprintf()
45 * Quoting (%#s) is disabled for the (nil) pointer
49 * %#s means that the string will be quoted with "
50 * (I was getting tired of writing \"%s\" all the time)
52 * [ERR] for strings changed to (nil)
56 * - Prepended all internal functions with dprintf_
57 * - Defined the booleans
60 * - Added dvsprintf(), dvfprintf() and dvprintf().
61 * - Made the formatting function available with the name _formatf() to enable
62 * other *printf()-inspired functions. (I considered adding a dmsprintf()
63 * that works like sprintf() but allocates the destination string and
64 * possibly enlarges it itself, but things like that should be done with the
65 * new _formatf() instead.)
68 * - Small modifications to make it compile nicely at both Daniel's and
72 * - Made it work with text to the right of the last %!
73 * - Introduced dprintf(), dsprintf() and dfprintf().
74 * - Float/double support enabled. This system is currently using the ordinary
75 * sprintf() function. NOTE that positional parameters, widths and precisions
76 * will still work like it should since the d-system takes care of that and
77 * passes that information re-formatted to the old sprintf().
80 * - Fixed space padding (i.e %d was extra padded previously)
81 * - long long output is supported
82 * - alternate output is done correct like in %#08x
84 ****************************************************************************/
86 static const char rcsid
[] = "@(#)$Id: mprintf.c,v 1.1.1.1 1999-12-29 14:21:34 bagder Exp $";
91 * Use WIDTH, PRECISION and NUMBERED ARGUMENT combined.
94 #include <sys/types.h>
102 #define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
103 #define MAX_PARAMETERS 128 /* lame static limit */
113 # define TRUE ((char)(1 == 1))
114 # define FALSE ((char)(0 == 1))
119 /* Lower-case digits. */
120 static const char lower_digits
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
122 /* Upper-case digits. */
123 static const char upper_digits
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
125 #define OUTCHAR(x) done+=(stream(x, (FILE *)data)==-1?0:1)
127 /* Data type to read from the arglist */
138 FORMAT_WIDTH
/* For internal use */
141 /* convertion and display flags */
145 FLAGS_SHOWSIGN
= 1<<1,
150 FLAGS_LONGLONG
= 1<<6,
151 FLAGS_LONGDOUBLE
= 1<<7,
152 FLAGS_PAD_NIL
= 1<<8,
153 FLAGS_UNSIGNED
= 1<<9,
157 FLAGS_WIDTH
= 1<<13, /* '*' or '*<num>$' used */
158 FLAGS_WIDTHPARAM
= 1<<14, /* width PARAMETER was specified */
159 FLAGS_PREC
= 1<<15, /* precision was specified */
160 FLAGS_PRECPARAM
= 1<<16, /* precision PARAMETER was specified */
161 FLAGS_CHAR
= 1<<17, /* %c story */
162 FLAGS_FLOATE
= 1<<18, /* %e or %E */
163 FLAGS_FLOATG
= 1<<19 /* %g or %G */
169 int width
; /* width OR width parameter number */
170 int precision
; /* precision OR precision parameter number */
175 #if SIZEOF_LONG_LONG /* if this is non-zero */
179 #if SIZEOF_LONG_DOUBLE
192 char *buffer
; /* allocated buffer */
193 size_t len
; /* length of string */
194 size_t alloc
; /* length of alloc */
197 int msprintf(char *buffer
, const char *format
, ...);
199 static int dprintf_DollarString(char *input
, char **end
)
202 while(isdigit((int)*input
)) {
204 number
+= *input
-'0';
207 if(number
&& ('$'==*input
++)) {
214 static BOOL
dprintf_IsQualifierNoDollar(char c
)
217 case '-': case '+': case ' ': case '#': case '.':
218 case '0': case '1': case '2': case '3': case '4':
219 case '5': case '6': case '7': case '8': case '9':
220 case 'h': case 'l': case 'L': case 'Z': case 'q':
227 #ifdef DPRINTF_DEBUG2
228 int dprintf_Pass1Report(va_stack_t
*vto
, int max
)
235 for(i
=0; i
<max
; i
++) {
237 switch(vto
[i
].type
) {
253 case FORMAT_LONGLONG
:
259 case FORMAT_LONGDOUBLE
:
260 type
= "long double";
267 for(bit
=0; bit
<31; bit
++) {
268 flags
= vto
[i
].flags
& (1<<bit
);
270 if(flags
& FLAGS_SPACE
)
271 strcat(buffer
, "space ");
272 else if(flags
& FLAGS_SHOWSIGN
)
273 strcat(buffer
, "plus ");
274 else if(flags
& FLAGS_LEFT
)
275 strcat(buffer
, "left ");
276 else if(flags
& FLAGS_ALT
)
277 strcat(buffer
, "alt ");
278 else if(flags
& FLAGS_SHORT
)
279 strcat(buffer
, "short ");
280 else if(flags
& FLAGS_LONG
)
281 strcat(buffer
, "long ");
282 else if(flags
& FLAGS_LONGLONG
)
283 strcat(buffer
, "longlong ");
284 else if(flags
& FLAGS_LONGDOUBLE
)
285 strcat(buffer
, "longdouble ");
286 else if(flags
& FLAGS_PAD_NIL
)
287 strcat(buffer
, "padnil ");
288 else if(flags
& FLAGS_UNSIGNED
)
289 strcat(buffer
, "unsigned ");
290 else if(flags
& FLAGS_OCTAL
)
291 strcat(buffer
, "octal ");
292 else if(flags
& FLAGS_HEX
)
293 strcat(buffer
, "hex ");
294 else if(flags
& FLAGS_UPPER
)
295 strcat(buffer
, "upper ");
296 else if(flags
& FLAGS_WIDTH
)
297 strcat(buffer
, "width ");
298 else if(flags
& FLAGS_WIDTHPARAM
)
299 strcat(buffer
, "widthparam ");
300 else if(flags
& FLAGS_PREC
)
301 strcat(buffer
, "precision ");
302 else if(flags
& FLAGS_PRECPARAM
)
303 strcat(buffer
, "precparam ");
304 else if(flags
& FLAGS_CHAR
)
305 strcat(buffer
, "char ");
306 else if(flags
& FLAGS_FLOATE
)
307 strcat(buffer
, "floate ");
308 else if(flags
& FLAGS_FLOATG
)
309 strcat(buffer
, "floatg ");
311 printf("REPORT: %d. %s [%s]\n", i
, type
, buffer
);
319 /******************************************************************
322 * Create an index with the type of each parameter entry and its
323 * value (may vary in size)
325 ******************************************************************/
327 static int dprintf_Pass1(char *format
, va_stack_t
*vto
, char **endpos
, va_list arglist
)
342 continue; /* while */
347 /* Handle the positional case (N$) */
351 this_param
= dprintf_DollarString(fmt
, &fmt
);
353 /* we got no positional, get the next counter */
354 this_param
= param_num
;
356 if (this_param
> max_param
)
357 max_param
= this_param
;
360 * The parameter with number 'i' should be used. Next, we need
361 * to get SIZE and TYPE of the parameter. Add the information
368 /* Handle the flags */
370 while (dprintf_IsQualifierNoDollar(*fmt
)) {
373 flags
|= FLAGS_SPACE
;
376 flags
|= FLAGS_SHOWSIGN
;
380 flags
&= ~FLAGS_PAD_NIL
;
388 /* The precision is picked from a specified parameter */
390 flags
|= FLAGS_PRECPARAM
;
394 i
= dprintf_DollarString(fmt
, &fmt
);
398 precision
= param_num
;
400 if (precision
> max_param
)
401 max_param
= precision
;
405 precision
= strtol(fmt
, &fmt
, 10);
409 flags
|= FLAGS_SHORT
;
412 if (flags
& FLAGS_LONG
)
413 flags
|= FLAGS_LONGLONG
;
418 flags
|= FLAGS_LONGDOUBLE
;
421 flags
|= FLAGS_LONGLONG
;
424 if (sizeof(size_t) > sizeof(unsigned long int))
425 flags
|= FLAGS_LONGLONG
;
426 if (sizeof(size_t) > sizeof(unsigned int))
430 if (!(flags
& FLAGS_LEFT
))
431 flags
|= FLAGS_PAD_NIL
;
433 case '1': case '2': case '3': case '4':
434 case '5': case '6': case '7': case '8': case '9':
435 flags
|= FLAGS_WIDTH
;
436 width
= strtol(--fmt
, &fmt
, 10);
438 case '*': /* Special case */
439 flags
|= FLAGS_WIDTHPARAM
;
442 i
= dprintf_DollarString(fmt
, &fmt
);
447 if(width
> max_param
)
455 /* Handle the specifier */
464 vto
[i
].type
= FORMAT_STRING
;
467 vto
[i
].type
= FORMAT_INTPTR
;
470 vto
[i
].type
= FORMAT_PTR
;
473 vto
[i
].type
= FORMAT_INT
;
476 vto
[i
].type
= FORMAT_INT
;
477 flags
|= FLAGS_UNSIGNED
;
480 vto
[i
].type
= FORMAT_INT
;
481 flags
|= FLAGS_OCTAL
;
484 vto
[i
].type
= FORMAT_INT
;
488 vto
[i
].type
= FORMAT_INT
;
489 flags
|= FLAGS_HEX
|FLAGS_UPPER
;
492 vto
[i
].type
= FORMAT_INT
;
496 vto
[i
].type
= FORMAT_DOUBLE
;
499 vto
[i
].type
= FORMAT_DOUBLE
;
500 flags
|= FLAGS_FLOATE
| (('E' == *fmt
)?FLAGS_UPPER
:0);
503 vto
[i
].type
= FORMAT_DOUBLE
;
504 flags
|= FLAGS_FLOATG
| (('G' == *fmt
)?FLAGS_UPPER
:0);
507 vto
[i
].type
= FORMAT_UNKNOWN
;
511 vto
[i
].flags
= flags
;
512 vto
[i
].width
= width
;
513 vto
[i
].precision
= precision
;
515 if (flags
& FLAGS_WIDTHPARAM
) {
516 /* we have the width specified from a parameter, so we make that
517 parameter's info setup properly */
518 vto
[i
].width
= width
- 1;
520 vto
[i
].type
= FORMAT_WIDTH
;
521 vto
[i
].flags
= FLAGS_NEW
;
522 vto
[i
].precision
= vto
[i
].width
= 0; /* can't use width or precision
525 if (flags
& FLAGS_PRECPARAM
) {
526 /* we have the precision specified from a parameter, so we make that
527 parameter's info setup properly */
528 vto
[i
].precision
= precision
- 1;
530 vto
[i
].type
= FORMAT_WIDTH
;
531 vto
[i
].flags
= FLAGS_NEW
;
532 vto
[i
].precision
= vto
[i
].width
= 0; /* can't use width or precision
535 *endpos
++ = fmt
+ 1; /* end of this sequence */
539 #ifdef DPRINTF_DEBUG2
540 dprintf_Pass1Report(vto
, max_param
);
543 /* Read the arg list parameters into our data list */
544 for (i
=0; i
<max_param
; i
++) {
545 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
550 vto
[i
+ 1].data
.num
= va_arg(arglist
, int);
556 vto
[i
].data
.str
= va_arg(arglist
, char *);
562 vto
[i
].data
.ptr
= va_arg(arglist
, void *);
567 if(vto
[i
].flags
& FLAGS_LONGLONG
)
568 vto
[i
].data
.lnum
= va_arg(arglist
, long long);
571 if(vto
[i
].flags
& FLAGS_LONG
)
572 vto
[i
].data
.num
= va_arg(arglist
, long);
574 vto
[i
].data
.num
= va_arg(arglist
, int);
578 #if SIZEOF_LONG_DOUBLE
579 if(vto
[i
].flags
& FLAGS_LONG
)
580 vto
[i
].data
.ldnum
= va_arg(arglist
, long double);
583 vto
[i
].data
.dnum
= va_arg(arglist
, double);
587 /* Argument has been read. Silently convert it into an integer
590 vto
[i
].type
= FORMAT_INT
;
602 static int dprintf_formatf(
603 void *data
, /* untouched by format(), just sent to the
604 stream() function in the first argument */
605 int (*stream
)(int, FILE *), /* function pointer called for each
607 const char *format
, /* %-formatted string */
608 va_list ap_save
) /* list of parameters */
610 /* Base-36 digits for numbers. */
611 const char *digits
= lower_digits
;
613 /* Pointer into the format string. */
616 /* Number of characters written. */
617 register size_t done
= 0;
619 long param
; /* current parameter to read */
620 long param_num
=0; /* parameter counter */
622 va_stack_t vto
[MAX_PARAMETERS
];
623 char *endpos
[MAX_PARAMETERS
];
630 /* Do the actual %-code parsing */
631 dprintf_Pass1((char *)format
, vto
, endpos
, ap_save
);
633 end
= &endpos
[0]; /* the initial end-position from the list dprintf_Pass1()
638 /* Format spec modifiers. */
641 /* Width of a field. */
643 /* Precision of a field. */
646 /* Decimal integer is negative. */
649 /* Base of a number to be written. */
652 /* Integral values to be written. */
654 unsigned long long num
;
661 /* This isn't a format spec, so write everything out until the next one
662 OR end of string is reached. */
665 } while(*++f
&& ('%' != *f
));
671 /* Check for "%%". Note that although the ANSI standard lists
672 '%' as a conversion specifier, it says "The complete format
673 specification shall be `%%'," so we can avoid all the width
674 and precision processing. */
681 /* If this is a positional parameter, the position must follow imediately
682 after the %, thus create a %<num>$ sequence */
683 param
=dprintf_DollarString(f
, &f
);
690 param_num
++; /* increase this always to allow "%2$s %1$s %s" and then the
691 third %s will pick the 3rd argument */
695 /* pick up the specified width */
696 if(p
->flags
& FLAGS_WIDTHPARAM
)
697 width
= vto
[p
->width
].data
.num
;
701 /* pick up the specified precision */
702 if(p
->flags
& FLAGS_PRECPARAM
)
703 prec
= vto
[p
->precision
].data
.num
;
704 else if(p
->flags
& FLAGS_PREC
)
709 alt
= p
->flags
& FLAGS_ALT
;
714 if(p
->flags
& FLAGS_CHAR
) {
716 if (!(p
->flags
& FLAGS_LEFT
))
720 if (p
->flags
& FLAGS_LEFT
)
725 if(p
->flags
& FLAGS_UNSIGNED
) {
726 /* Decimal unsigned integer. */
728 goto unsigned_number
;
730 if(p
->flags
& FLAGS_OCTAL
) {
731 /* Octal unsigned integer. */
733 goto unsigned_number
;
735 if(p
->flags
& FLAGS_HEX
) {
736 /* Hexadecimal unsigned integer. */
738 digits
= (p
->flags
& FLAGS_UPPER
)? upper_digits
: lower_digits
;
740 goto unsigned_number
;
743 /* Decimal integer. */
747 if(p
->flags
& FLAGS_LONGLONG
) {
751 num
= is_neg
? (- num
) : num
;
756 signed_num
= (long) num
;
758 is_neg
= signed_num
< 0;
759 num
= is_neg
? (- signed_num
) : signed_num
;
764 /* Unsigned number of base BASE. */
768 /* Number of base BASE. */
770 char *workend
= &work
[sizeof(work
) - 1];
773 /* Supply a default precision if none was given. */
777 /* Put the number in WORK. */
780 *w
-- = digits
[num
% base
];
783 width
-= workend
- w
;
786 if (alt
&& base
== 8 && prec
<= 0) {
797 if (alt
&& base
== 16)
800 if (is_neg
|| (p
->flags
& FLAGS_SHOWSIGN
) || (p
->flags
& FLAGS_SPACE
))
803 if (!(p
->flags
& FLAGS_LEFT
) && !(p
->flags
& FLAGS_PAD_NIL
))
809 else if (p
->flags
& FLAGS_SHOWSIGN
)
811 else if (p
->flags
& FLAGS_SPACE
)
814 if (alt
&& base
== 16) {
816 if(p
->flags
& FLAGS_UPPER
)
822 if (!(p
->flags
& FLAGS_LEFT
) && (p
->flags
& FLAGS_PAD_NIL
))
826 /* Write the number. */
827 while (++w
<= workend
) {
831 if (p
->flags
& FLAGS_LEFT
)
840 static char null
[] = "(nil)";
844 str
= (char *) p
->data
.str
;
846 /* Write null[] if there's space. */
847 if (prec
== -1 || prec
>= (long) sizeof(null
) - 1) {
849 len
= sizeof(null
) - 1;
850 /* Disable quotes around (nil) */
851 p
->flags
&= (~FLAGS_ALT
);
861 if (prec
!= -1 && (size_t) prec
< len
)
865 if (p
->flags
& FLAGS_ALT
)
868 if (!(p
->flags
&FLAGS_LEFT
))
874 if (p
->flags
&FLAGS_LEFT
)
878 if (p
->flags
& FLAGS_ALT
)
884 /* Generic pointer. */
887 ptr
= (void *) p
->data
.ptr
;
889 /* If the pointer is not NULL, write it as a %#x spec. */
891 digits
= (p
->flags
& FLAGS_UPPER
)? upper_digits
: lower_digits
;
893 num
= (unsigned long) ptr
;
898 /* Write "(nil)" for a nil pointer. */
899 static char nil
[] = "(nil)";
900 register char *point
;
902 width
-= sizeof(nil
) - 1;
903 if (p
->flags
& FLAGS_LEFT
)
906 for (point
= nil
; *point
!= '\0'; ++point
)
908 if (! (p
->flags
& FLAGS_LEFT
))
917 char formatbuf
[32]="%";
921 if (p
->flags
& FLAGS_WIDTH
)
923 else if (p
->flags
& FLAGS_WIDTHPARAM
)
924 width
= vto
[p
->width
].data
.num
;
927 if (p
->flags
& FLAGS_PREC
)
929 else if (p
->flags
& FLAGS_PRECPARAM
)
930 prec
= vto
[p
->precision
].data
.num
;
932 if (p
->flags
& FLAGS_LEFT
)
933 strcat(formatbuf
, "-");
934 if (p
->flags
& FLAGS_SHOWSIGN
)
935 strcat(formatbuf
, "+");
936 if (p
->flags
& FLAGS_SPACE
)
937 strcat(formatbuf
, " ");
938 if (p
->flags
& FLAGS_ALT
)
939 strcat(formatbuf
, "#");
941 fptr
=&formatbuf
[strlen(formatbuf
)];
944 /* RECURSIVE USAGE */
945 fptr
+= msprintf(fptr
, "%d", width
);
948 /* RECURSIVE USAGE */
949 fptr
+= msprintf(fptr
, ".%d", prec
);
951 if (p
->flags
& FLAGS_LONG
)
954 if (p
->flags
& FLAGS_FLOATE
)
955 strcat(fptr
, p
->flags
&FLAGS_UPPER
?"E":"e");
956 else if (p
->flags
& FLAGS_FLOATG
)
957 strcat(fptr
, (p
->flags
& FLAGS_UPPER
) ? "G" : "g");
961 /* NOTE NOTE NOTE!! Not all sprintf() implementations returns number
962 of output characters */
963 #if SIZEOF_LONG_DOUBLE
964 if (p
->flags
& FLAGS_LONG
)
965 /* This is for support of the 'long double' type */
966 (sprintf
)(work
, formatbuf
, p
->data
.ldnum
);
969 (sprintf
)(work
, formatbuf
, p
->data
.dnum
);
971 for(fptr
=work
; *fptr
; fptr
++)
977 /* Answer the count of characters written. */
979 if (p
->flags
& FLAGS_LONGLONG
)
980 *(long long int *) p
->data
.ptr
= done
;
983 if (p
->flags
& FLAGS_LONG
)
984 *(long int *) p
->data
.ptr
= done
;
985 else if (!(p
->flags
& FLAGS_SHORT
))
986 *(int *) p
->data
.ptr
= done
;
988 *(short int *) p
->data
.ptr
= done
;
994 f
= *end
++; /* goto end of %-code */
1000 static int StoreNonPrintable(int output
, struct nsprintf
*infop
)
1002 /* If the character isn't printable then we convert it */
1006 w
= &work
[sizeof(work
)];
1008 for(; num
> 0; num
/= 10) {
1009 *(--w
) = lower_digits
[num
% 10];
1011 if (infop
->length
+ strlen(w
) + 1 < infop
->max
)
1013 infop
->buffer
[0] = '\\';
1018 infop
->buffer
[0] = *w
;
1027 /* fputc() look-alike */
1028 static int addbyter(int output
, FILE *data
)
1030 struct nsprintf
*infop
=(struct nsprintf
*)data
;
1032 if(infop
->length
< infop
->max
) {
1033 /* only do this if we haven't reached max length yet */
1034 if (isprint(output
) || isspace(output
))
1036 infop
->buffer
[0] = (char)output
; /* store */
1037 infop
->buffer
++; /* increase pointer */
1038 infop
->length
++; /* we are now one byte larger */
1042 return StoreNonPrintable(output
, infop
);
1044 return output
; /* fputc() returns like this on success */
1049 int msnprintf(char *buffer
, size_t maxlength
, const char *format
, ...)
1051 va_list ap_save
; /* argument pointer */
1053 struct nsprintf info
;
1055 info
.buffer
= buffer
;
1057 info
.max
= maxlength
;
1059 va_start(ap_save
, format
);
1060 retcode
= dprintf_formatf(&info
, addbyter
, format
, ap_save
);
1062 info
.buffer
[0] = 0; /* we terminate this with a zero byte */
1064 /* we could even return things like */
1069 int mvsnprintf(char *buffer
, size_t maxlength
, const char *format
, va_list ap_save
)
1072 struct nsprintf info
;
1074 info
.buffer
= buffer
;
1076 info
.max
= maxlength
;
1078 retcode
= dprintf_formatf(&info
, addbyter
, format
, ap_save
);
1079 info
.buffer
[0] = 0; /* we terminate this with a zero byte */
1084 /* fputc() look-alike */
1085 static int alloc_addbyter(int output
, FILE *data
)
1087 struct asprintf
*infop
=(struct asprintf
*)data
;
1089 if(!infop
->buffer
) {
1090 infop
->buffer
=(char *)malloc(32);
1092 return -1; /* fail */
1096 else if(infop
->len
+1 >= infop
->alloc
) {
1099 newptr
= (char *)realloc(infop
->buffer
, infop
->alloc
*2);
1104 infop
->buffer
= newptr
;
1108 infop
->buffer
[ infop
->len
] = output
;
1112 return output
; /* fputc() returns like this on success */
1116 char *maprintf(const char *format
, ...)
1118 va_list ap_save
; /* argument pointer */
1120 struct asprintf info
;
1126 va_start(ap_save
, format
);
1127 retcode
= dprintf_formatf(&info
, alloc_addbyter
, format
, ap_save
);
1130 info
.buffer
[info
.len
] = 0; /* we terminate this with a zero byte */
1137 char *mvaprintf(const char *format
, va_list ap_save
)
1140 struct asprintf info
;
1146 retcode
= dprintf_formatf(&info
, alloc_addbyter
, format
, ap_save
);
1147 info
.buffer
[info
.len
] = 0; /* we terminate this with a zero byte */
1149 info
.buffer
[info
.len
] = 0; /* we terminate this with a zero byte */
1156 static int storebuffer(int output
, FILE *data
)
1158 char **buffer
= (char **)data
;
1159 **buffer
= (char)output
;
1161 return output
; /* act like fputc() ! */
1164 int msprintf(char *buffer
, const char *format
, ...)
1166 va_list ap_save
; /* argument pointer */
1168 va_start(ap_save
, format
);
1169 retcode
= dprintf_formatf(&buffer
, storebuffer
, format
, ap_save
);
1171 *buffer
=0; /* we terminate this with a zero byte */
1175 extern int fputc(int, FILE *);
1177 int mprintf(const char *format
, ...)
1180 va_list ap_save
; /* argument pointer */
1181 va_start(ap_save
, format
);
1182 retcode
= dprintf_formatf(stdout
, fputc
, format
, ap_save
);
1187 int mfprintf(FILE *whereto
, const char *format
, ...)
1190 va_list ap_save
; /* argument pointer */
1191 va_start(ap_save
, format
);
1192 retcode
= dprintf_formatf(whereto
, fputc
, format
, ap_save
);
1197 int mvsprintf(char *buffer
, const char *format
, va_list ap_save
)
1200 retcode
= dprintf_formatf(&buffer
, storebuffer
, format
, ap_save
);
1201 *buffer
=0; /* we terminate this with a zero byte */
1205 int mvprintf(const char *format
, va_list ap_save
)
1207 return dprintf_formatf(stdout
, fputc
, format
, ap_save
);
1210 int mvfprintf(FILE *whereto
, const char *format
, va_list ap_save
)
1212 return dprintf_formatf(whereto
, fputc
, format
, ap_save
);
1215 #ifdef DPRINTF_DEBUG
1220 #ifdef SIZEOF_LONG_LONG
1222 dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo
, "stenberg", 65);
1225 mprintf("%3d %5d\n", 10, 1998);
1227 ptr
=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);
1231 memset(ptr
, 55, strlen(ptr
)+1);
1236 mprintf(buffer
, "%s %s %d", "daniel", "stenberg", 19988);
1239 mfprintf(stderr
, "%s %#08x\n", "dummy", 65);
1241 printf("%s %#08x\n", "dummy", 65);
1243 double tryout
= 3.14156592;
1244 mprintf(buffer
, "%.2g %G %f %e %E", tryout
, tryout
, tryout
, tryout
, tryout
);
1246 printf("%.2g %G %f %e %E\n", tryout
, tryout
, tryout
, tryout
, tryout
);