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