File Coverage

printf.c
Criterion Covered Total %
statement 161 338 47.6
branch 108 324 33.3
condition n/a
subroutine n/a
pod n/a
total 269 662 40.6


line stmt bran cond sub pod time code
1             /*
2             ** The "printf" code that follows dates from the 1980's. It is in
3             ** the public domain. The original comments are included here for
4             ** completeness. They are very out-of-date but might be useful as
5             ** an historical reference. Most of the "enhancements" have been backed
6             ** out so that the functionality is now the same as standard printf().
7             **
8             **************************************************************************
9             **
10             ** The following modules is an enhanced replacement for the "printf" subroutines
11             ** found in the standard C library. The following enhancements are
12             ** supported:
13             **
14             ** + Additional functions. The standard set of "printf" functions
15             ** includes printf, fprintf, sprintf, vprintf, vfprintf, and
16             ** vsprintf. This module adds the following:
17             **
18             ** * snprintf -- Works like sprintf, but has an extra argument
19             ** which is the size of the buffer written to.
20             **
21             ** * mprintf -- Similar to sprintf. Writes output to memory
22             ** obtained from malloc.
23             **
24             ** * xprintf -- Calls a function to dispose of output.
25             **
26             ** * nprintf -- No output, but returns the number of characters
27             ** that would have been output by printf.
28             **
29             ** * A v- version (ex: vsnprintf) of every function is also
30             ** supplied.
31             **
32             ** + A few extensions to the formatting notation are supported:
33             **
34             ** * The "=" flag (similar to "-") causes the output to be
35             ** be centered in the appropriately sized field.
36             **
37             ** * The %b field outputs an integer in binary notation.
38             **
39             ** * The %c field now accepts a precision. The character output
40             ** is repeated by the number of times the precision specifies.
41             **
42             ** * The %' field works like %c, but takes as its character the
43             ** next character of the format string, instead of the next
44             ** argument. For example, printf("%.78'-") prints 78 minus
45             ** signs, the same as printf("%.78c",'-').
46             **
47             ** + When compiled using GCC on a SPARC, this version of printf is
48             ** faster than the library printf for SUN OS 4.1.
49             **
50             ** + All functions are fully reentrant.
51             **
52             */
53             #include "sqliteInt.h"
54              
55             /*
56             ** Conversion types fall into various categories as defined by the
57             ** following enumeration.
58             */
59             #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
60             #define etFLOAT 2 /* Floating point. %f */
61             #define etEXP 3 /* Exponentional notation. %e and %E */
62             #define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
63             #define etSIZE 5 /* Return number of characters processed so far. %n */
64             #define etSTRING 6 /* Strings. %s */
65             #define etDYNSTRING 7 /* Dynamically allocated strings. %z */
66             #define etPERCENT 8 /* Percent symbol. %% */
67             #define etCHARX 9 /* Characters. %c */
68             #define etERROR 10 /* Used to indicate no such conversion type */
69             /* The rest are extensions, not normally found in printf() */
70             #define etCHARLIT 11 /* Literal characters. %' */
71             #define etSQLESCAPE 12 /* Strings with '\'' doubled. %q */
72             #define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '',
73             NULL pointers replaced by SQL NULL. %Q */
74             #define etTOKEN 14 /* a pointer to a Token structure */
75             #define etSRCLIST 15 /* a pointer to a SrcList */
76              
77              
78             /*
79             ** An "etByte" is an 8-bit unsigned value.
80             */
81             typedef unsigned char etByte;
82              
83             /*
84             ** Each builtin conversion character (ex: the 'd' in "%d") is described
85             ** by an instance of the following structure
86             */
87             typedef struct et_info { /* Information about each format field */
88             char fmttype; /* The format field code letter */
89             etByte base; /* The base for radix conversion */
90             etByte flags; /* One or more of FLAG_ constants below */
91             etByte type; /* Conversion paradigm */
92             char *charset; /* The character set for conversion */
93             char *prefix; /* Prefix on non-zero values in alt format */
94             } et_info;
95              
96             /*
97             ** Allowed values for et_info.flags
98             */
99             #define FLAG_SIGNED 1 /* True if the value to convert is signed */
100             #define FLAG_INTERN 2 /* True if for internal use only */
101              
102              
103             /*
104             ** The following table is searched linearly, so it is good to put the
105             ** most frequently used conversion types first.
106             */
107             static et_info fmtinfo[] = {
108             { 'd', 10, 1, etRADIX, "0123456789", 0 },
109             { 's', 0, 0, etSTRING, 0, 0 },
110             { 'z', 0, 2, etDYNSTRING, 0, 0 },
111             { 'q', 0, 0, etSQLESCAPE, 0, 0 },
112             { 'Q', 0, 0, etSQLESCAPE2, 0, 0 },
113             { 'c', 0, 0, etCHARX, 0, 0 },
114             { 'o', 8, 0, etRADIX, "01234567", "0" },
115             { 'u', 10, 0, etRADIX, "0123456789", 0 },
116             { 'x', 16, 0, etRADIX, "0123456789abcdef", "x0" },
117             { 'X', 16, 0, etRADIX, "0123456789ABCDEF", "X0" },
118             { 'f', 0, 1, etFLOAT, 0, 0 },
119             { 'e', 0, 1, etEXP, "e", 0 },
120             { 'E', 0, 1, etEXP, "E", 0 },
121             { 'g', 0, 1, etGENERIC, "e", 0 },
122             { 'G', 0, 1, etGENERIC, "E", 0 },
123             { 'i', 10, 1, etRADIX, "0123456789", 0 },
124             { 'n', 0, 0, etSIZE, 0, 0 },
125             { '%', 0, 0, etPERCENT, 0, 0 },
126             { 'p', 10, 0, etRADIX, "0123456789", 0 },
127             { 'T', 0, 2, etTOKEN, 0, 0 },
128             { 'S', 0, 2, etSRCLIST, 0, 0 },
129             };
130             #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
131              
132             /*
133             ** If NOFLOATINGPOINT is defined, then none of the floating point
134             ** conversions will work.
135             */
136             #ifndef etNOFLOATINGPOINT
137             /*
138             ** "*val" is a double such that 0.1 <= *val < 10.0
139             ** Return the ascii code for the leading digit of *val, then
140             ** multiply "*val" by 10.0 to renormalize.
141             **
142             ** Example:
143             ** input: *val = 3.14159
144             ** output: *val = 1.4159 function return = '3'
145             **
146             ** The counter *cnt is incremented each time. After counter exceeds
147             ** 16 (the number of significant digits in a 64-bit float) '0' is
148             ** always returned.
149             */
150 30           static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
151             int digit;
152             LONGDOUBLE_TYPE d;
153 30 50         if( (*cnt)++ >= 16 ) return '0';
154 30           digit = (int)*val;
155 30           d = digit;
156 30           digit += '0';
157 30           *val = (*val - d)*10.0;
158 30           return digit;
159             }
160             #endif
161              
162             #define etBUFSIZE 1000 /* Size of the output buffer */
163              
164             /*
165             ** The root program. All variations call this core.
166             **
167             ** INPUTS:
168             ** func This is a pointer to a function taking three arguments
169             ** 1. A pointer to anything. Same as the "arg" parameter.
170             ** 2. A pointer to the list of characters to be output
171             ** (Note, this list is NOT null terminated.)
172             ** 3. An integer number of characters to be output.
173             ** (Note: This number might be zero.)
174             **
175             ** arg This is the pointer to anything which will be passed as the
176             ** first argument to "func". Use it for whatever you like.
177             **
178             ** fmt This is the format string, as in the usual print.
179             **
180             ** ap This is a pointer to a list of arguments. Same as in
181             ** vfprint.
182             **
183             ** OUTPUTS:
184             ** The return value is the total number of characters sent to
185             ** the function "func". Returns -1 on a error.
186             **
187             ** Note that the order in which automatic variables are declared below
188             ** seems to make a big difference in determining how fast this beast
189             ** will run.
190             */
191 52           static int vxprintf(
192             void (*func)(void*,const char*,int), /* Consumer of text */
193             void *arg, /* First argument to the consumer */
194             int useExtended, /* Allow extended %-conversions */
195             const char *fmt, /* Format string */
196             va_list ap /* arguments */
197             ){
198             int c; /* Next character in the format string */
199             char *bufpt; /* Pointer to the conversion buffer */
200             int precision; /* Precision of the current field */
201             int length; /* Length of the field */
202             int idx; /* A general purpose loop counter */
203             int count; /* Total number of characters output */
204             int width; /* Width of the current field */
205             etByte flag_leftjustify; /* True if "-" flag is present */
206             etByte flag_plussign; /* True if "+" flag is present */
207             etByte flag_blanksign; /* True if " " flag is present */
208             etByte flag_alternateform; /* True if "#" flag is present */
209             etByte flag_zeropad; /* True if field width constant starts with zero */
210             etByte flag_long; /* True if "l" flag is present */
211             unsigned long longvalue; /* Value for integer types */
212             LONGDOUBLE_TYPE realvalue; /* Value for real types */
213             et_info *infop; /* Pointer to the appropriate info structure */
214             char buf[etBUFSIZE]; /* Conversion buffer */
215             char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
216 52           etByte errorflag = 0; /* True if an error is encountered */
217             etByte xtype; /* Conversion paradigm */
218             char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
219             static char spaces[] = " ";
220             #define etSPACESIZE (sizeof(spaces)-1)
221             #ifndef etNOFLOATINGPOINT
222             int exp; /* exponent of real numbers */
223             double rounder; /* Used for rounding floating point values */
224             etByte flag_dp; /* True if decimal point should be shown */
225             etByte flag_rtz; /* True if trailing zeros should be removed */
226             etByte flag_exp; /* True to force display of the exponent */
227             int nsd; /* Number of significant digits returned */
228             #endif
229              
230 52           func(arg,"",0);
231 52           count = length = 0;
232 52           bufpt = 0;
233 104 100         for(; (c=(*fmt))!=0; ++fmt){
234 53 100         if( c!='%' ){
235             int amt;
236 8           bufpt = (char *)fmt;
237 8           amt = 1;
238 111 100         while( (c=(*++fmt))!='%' && c!=0 ) amt++;
    100          
239 8           (*func)(arg,bufpt,amt);
240 8           count += amt;
241 8 100         if( c==0 ) break;
242             }
243 52 50         if( (c=(*++fmt))==0 ){
244 0           errorflag = 1;
245 0           (*func)(arg,"%",1);
246 0           count++;
247 0           break;
248             }
249             /* Find out what flags are present */
250 52           flag_leftjustify = flag_plussign = flag_blanksign =
251 52           flag_alternateform = flag_zeropad = 0;
252             do{
253 52           switch( c ){
254 0           case '-': flag_leftjustify = 1; c = 0; break;
255 0           case '+': flag_plussign = 1; c = 0; break;
256 0           case ' ': flag_blanksign = 1; c = 0; break;
257 0           case '#': flag_alternateform = 1; c = 0; break;
258 0           case '0': flag_zeropad = 1; c = 0; break;
259 52           default: break;
260             }
261 52 50         }while( c==0 && (c=(*++fmt))!=0 );
    0          
262             /* Get the field width */
263 52           width = 0;
264 52 50         if( c=='*' ){
265 0 0         width = va_arg(ap,int);
266 0 0         if( width<0 ){
267 0           flag_leftjustify = 1;
268 0           width = -width;
269             }
270 0           c = *++fmt;
271             }else{
272 52 100         while( c>='0' && c<='9' ){
    50          
273 0           width = width*10 + c - '0';
274 0           c = *++fmt;
275             }
276             }
277 52 50         if( width > etBUFSIZE-10 ){
278 0           width = etBUFSIZE-10;
279             }
280             /* Get the precision */
281 52 100         if( c=='.' ){
282 2           precision = 0;
283 2           c = *++fmt;
284 2 50         if( c=='*' ){
285 0 0         precision = va_arg(ap,int);
286 0 0         if( precision<0 ) precision = -precision;
287 0           c = *++fmt;
288             }else{
289 6 50         while( c>='0' && c<='9' ){
    100          
290 4           precision = precision*10 + c - '0';
291 4           c = *++fmt;
292             }
293             }
294             /* Limit the precision to prevent overflowing buf[] during conversion */
295 2 50         if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40;
296             }else{
297 50           precision = -1;
298             }
299             /* Get the conversion type modifier */
300 52 50         if( c=='l' ){
301 0           flag_long = 1;
302 0           c = *++fmt;
303             }else{
304 52           flag_long = 0;
305             }
306             /* Fetch the info entry for the field */
307 52           infop = 0;
308 52           xtype = etERROR;
309 211 50         for(idx=0; idx
310 211 100         if( c==fmtinfo[idx].fmttype ){
311 52           infop = &fmtinfo[idx];
312 52 100         if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
    50          
313 52           xtype = infop->type;
314             }
315 52           break;
316             }
317             }
318 52           zExtra = 0;
319              
320             /*
321             ** At this point, variables are initialized as follows:
322             **
323             ** flag_alternateform TRUE if a '#' is present.
324             ** flag_plussign TRUE if a '+' is present.
325             ** flag_leftjustify TRUE if a '-' is present or if the
326             ** field width was negative.
327             ** flag_zeropad TRUE if the width began with 0.
328             ** flag_long TRUE if the letter 'l' (ell) prefixed
329             ** the conversion character.
330             ** flag_blanksign TRUE if a ' ' is present.
331             ** width The specified field width. This is
332             ** always non-negative. Zero is the default.
333             ** precision The specified precision. The default
334             ** is -1.
335             ** xtype The class of the conversion.
336             ** infop Pointer to the appropriate info struct.
337             */
338 52           switch( xtype ){
339             case etRADIX:
340 43 50         if( flag_long ) longvalue = va_arg(ap,long);
    0          
341 43 50         else longvalue = va_arg(ap,int);
342             #if 1
343             /* For the format %#x, the value zero is printed "0" not "0x0".
344             ** I think this is stupid. */
345 43 100         if( longvalue==0 ) flag_alternateform = 0;
346             #else
347             /* More sensible: turn off the prefix for octal (to prevent "00"),
348             ** but leave the prefix for hex. */
349             if( longvalue==0 && infop->base==8 ) flag_alternateform = 0;
350             #endif
351 43 50         if( infop->flags & FLAG_SIGNED ){
352 43 50         if( *(long*)&longvalue<0 ){
353 0           longvalue = -*(long*)&longvalue;
354 0           prefix = '-';
355 43 50         }else if( flag_plussign ) prefix = '+';
356 43 50         else if( flag_blanksign ) prefix = ' ';
357 43           else prefix = 0;
358 0           }else prefix = 0;
359 43 50         if( flag_zeropad && precision
    0          
360 0           precision = width-(prefix!=0);
361             }
362 43           bufpt = &buf[etBUFSIZE-1];
363             {
364             register char *cset; /* Use registers for speed */
365             register int base;
366 43           cset = infop->charset;
367 43           base = infop->base;
368             do{ /* Convert to ascii */
369 58           *(--bufpt) = cset[longvalue%base];
370 58           longvalue = longvalue/base;
371 58 100         }while( longvalue>0 );
372             }
373 43           length = &buf[etBUFSIZE-1]-bufpt;
374 43 50         for(idx=precision-length; idx>0; idx--){
375 0           *(--bufpt) = '0'; /* Zero pad */
376             }
377 43 50         if( prefix ) *(--bufpt) = prefix; /* Add sign */
378 43 50         if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
    0          
379             char *pre, x;
380 0           pre = infop->prefix;
381 0 0         if( *bufpt!=pre[0] ){
382 0 0         for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
383             }
384             }
385 43           length = &buf[etBUFSIZE-1]-bufpt;
386 43           break;
387             case etFLOAT:
388             case etEXP:
389             case etGENERIC:
390 2 50         realvalue = va_arg(ap,double);
391             #ifndef etNOFLOATINGPOINT
392 2 50         if( precision<0 ) precision = 6; /* Set default precision */
393 2 50         if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10;
394 2 50         if( realvalue<0.0 ){
395 0           realvalue = -realvalue;
396 0           prefix = '-';
397             }else{
398 2 50         if( flag_plussign ) prefix = '+';
399 2 50         else if( flag_blanksign ) prefix = ' ';
400 2           else prefix = 0;
401             }
402 2 50         if( infop->type==etGENERIC && precision>0 ) precision--;
    50          
403 2           rounder = 0.0;
404             #if 0
405             /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
406             for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
407             #else
408             /* It makes more sense to use 0.5 */
409 30 100         for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
410             #endif
411 2 50         if( infop->type==etFLOAT ) realvalue += rounder;
412             /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
413 2           exp = 0;
414 2 50         if( realvalue>0.0 ){
415 3 100         while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
    50          
416 3 100         while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
    50          
417 2 50         while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
    0          
418 2 50         while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
    0          
419 2 50         if( exp>350 || exp<-350 ){
    50          
420 0           bufpt = "NaN";
421 0           length = 3;
422 0           break;
423             }
424             }
425 2           bufpt = buf;
426             /*
427             ** If the field type is etGENERIC, then convert to either etEXP
428             ** or etFLOAT, as appropriate.
429             */
430 2           flag_exp = xtype==etEXP;
431 2 50         if( xtype!=etFLOAT ){
432 2           realvalue += rounder;
433 2 50         if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
434             }
435 2 50         if( xtype==etGENERIC ){
436 2           flag_rtz = !flag_alternateform;
437 2 50         if( exp<-4 || exp>precision ){
    50          
438 0           xtype = etEXP;
439             }else{
440 2           precision = precision - exp;
441 2           xtype = etFLOAT;
442             }
443             }else{
444 0           flag_rtz = 0;
445             }
446             /*
447             ** The "exp+precision" test causes output to be of type etEXP if
448             ** the precision is too large to fit in buf[].
449             */
450 2           nsd = 0;
451 2 50         if( xtype==etFLOAT && exp+precision
    50          
452 2 50         flag_dp = (precision>0 || flag_alternateform);
    0          
453 2 50         if( prefix ) *(bufpt++) = prefix; /* Sign */
454 2 50         if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */
455 13 100         else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd);
456 2 50         if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */
457 2 50         for(exp++; exp<0 && precision>0; precision--, exp++){
    0          
458 0           *(bufpt++) = '0';
459             }
460 21 100         while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
461 2           *(bufpt--) = 0; /* Null terminate */
462 2 50         if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */
    50          
463 20 50         while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
    100          
464 2 50         if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
    100          
465             }
466 2           bufpt++; /* point to next free slot */
467             }else{ /* etEXP or etGENERIC */
468 0 0         flag_dp = (precision>0 || flag_alternateform);
    0          
469 0 0         if( prefix ) *(bufpt++) = prefix; /* Sign */
470 0           *(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */
471 0 0         if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */
472 0 0         while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
473 0           bufpt--; /* point to last digit */
474 0 0         if( flag_rtz && flag_dp ){ /* Remove tail zeros */
    0          
475 0 0         while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
    0          
476 0 0         if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
    0          
477             }
478 0           bufpt++; /* point to next free slot */
479 0 0         if( exp || flag_exp ){
    0          
480 0           *(bufpt++) = infop->charset[0];
481 0 0         if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
482 0           else { *(bufpt++) = '+'; }
483 0 0         if( exp>=100 ){
484 0           *(bufpt++) = (exp/100)+'0'; /* 100's digit */
485 0           exp %= 100;
486             }
487 0           *(bufpt++) = exp/10+'0'; /* 10's digit */
488 0           *(bufpt++) = exp%10+'0'; /* 1's digit */
489             }
490             }
491             /* The converted number is in buf[] and zero terminated. Output it.
492             ** Note that the number is in the usual order, not reversed as with
493             ** integer conversions. */
494 2           length = bufpt-buf;
495 2           bufpt = buf;
496              
497             /* Special case: Add leading zeros if the flag_zeropad flag is
498             ** set and we are not left justified */
499 2 50         if( flag_zeropad && !flag_leftjustify && length < width){
    0          
    0          
500             int i;
501 0           int nPad = width - length;
502 0 0         for(i=width; i>=nPad; i--){
503 0           bufpt[i] = bufpt[i-nPad];
504             }
505 0           i = prefix!=0;
506 0 0         while( nPad-- ) bufpt[i++] = '0';
507 0           length = width;
508             }
509             #endif
510 2           break;
511             case etSIZE:
512 0 0         *(va_arg(ap,int*)) = count;
513 0           length = width = 0;
514 0           break;
515             case etPERCENT:
516 0           buf[0] = '%';
517 0           bufpt = buf;
518 0           length = 1;
519 0           break;
520             case etCHARLIT:
521             case etCHARX:
522 0 0         c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt);
    0          
523 0 0         if( precision>=0 ){
524 0 0         for(idx=1; idx
525 0           length = precision;
526             }else{
527 0           length =1;
528             }
529 0           bufpt = buf;
530 0           break;
531             case etSTRING:
532             case etDYNSTRING:
533 0 0         bufpt = va_arg(ap,char*);
534 0 0         if( bufpt==0 ){
535 0           bufpt = "";
536 0 0         }else if( xtype==etDYNSTRING ){
537 0           zExtra = bufpt;
538             }
539 0           length = strlen(bufpt);
540 0 0         if( precision>=0 && precision
    0          
541 0           break;
542             case etSQLESCAPE:
543             case etSQLESCAPE2:
544             {
545             int i, j, n, c, isnull;
546 0 0         char *arg = va_arg(ap,char*);
547 0           isnull = arg==0;
548 0 0         if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
    0          
549 0 0         for(i=n=0; (c=arg[i])!=0; i++){
550 0 0         if( c=='\'' ) n++;
551             }
552 0 0         n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0);
    0          
553 0 0         if( n>etBUFSIZE ){
554 0           bufpt = zExtra = sqliteMalloc( n );
555 0 0         if( bufpt==0 ) return -1;
556             }else{
557 0           bufpt = buf;
558             }
559 0           j = 0;
560 0 0         if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
    0          
561 0 0         for(i=0; (c=arg[i])!=0; i++){
562 0           bufpt[j++] = c;
563 0 0         if( c=='\'' ) bufpt[j++] = c;
564             }
565 0 0         if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
    0          
566 0           bufpt[j] = 0;
567 0           length = j;
568 0 0         if( precision>=0 && precision
    0          
569             }
570 0           break;
571             case etTOKEN: {
572 7 50         Token *pToken = va_arg(ap, Token*);
573 7           (*func)(arg, pToken->z, pToken->n);
574 7           length = width = 0;
575 7           break;
576             }
577             case etSRCLIST: {
578 0 0         SrcList *pSrc = va_arg(ap, SrcList*);
579 0 0         int k = va_arg(ap, int);
580 0           struct SrcList_item *pItem = &pSrc->a[k];
581             assert( k>=0 && knSrc );
582 0 0         if( pItem->zDatabase && pItem->zDatabase[0] ){
    0          
583 0           (*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase));
584 0           (*func)(arg, ".", 1);
585             }
586 0           (*func)(arg, pItem->zName, strlen(pItem->zName));
587 0           length = width = 0;
588 0           break;
589             }
590             case etERROR:
591 0           buf[0] = '%';
592 0           buf[1] = c;
593 0           errorflag = 0;
594 0 0         idx = 1+(c!=0);
595 0           (*func)(arg,"%",idx);
596 0           count += idx;
597 0 0         if( c==0 ) fmt--;
598 0           break;
599             }/* End switch over the format type */
600             /*
601             ** The text of the conversion is pointed to by "bufpt" and is
602             ** "length" characters long. The field width is "width". Do
603             ** the output.
604             */
605 52 50         if( !flag_leftjustify ){
606             register int nspace;
607 52           nspace = width-length;
608 52 50         if( nspace>0 ){
609 0           count += nspace;
610 0 0         while( nspace>=etSPACESIZE ){
611 0           (*func)(arg,spaces,etSPACESIZE);
612 0           nspace -= etSPACESIZE;
613             }
614 0 0         if( nspace>0 ) (*func)(arg,spaces,nspace);
615             }
616             }
617 52 100         if( length>0 ){
618 45           (*func)(arg,bufpt,length);
619 45           count += length;
620             }
621 52 50         if( flag_leftjustify ){
622             register int nspace;
623 0           nspace = width-length;
624 0 0         if( nspace>0 ){
625 0           count += nspace;
626 0 0         while( nspace>=etSPACESIZE ){
627 0           (*func)(arg,spaces,etSPACESIZE);
628 0           nspace -= etSPACESIZE;
629             }
630 0 0         if( nspace>0 ) (*func)(arg,spaces,nspace);
631             }
632             }
633 52 50         if( zExtra ){
634 0           sqliteFree(zExtra);
635             }
636             }/* End for loop over the format string */
637 52 50         return errorflag ? -1 : count;
638             } /* End of function */
639              
640              
641             /* This structure is used to store state information about the
642             ** write to memory that is currently in progress.
643             */
644             struct sgMprintf {
645             char *zBase; /* A base allocation */
646             char *zText; /* The string collected so far */
647             int nChar; /* Length of the string so far */
648             int nTotal; /* Output size if unconstrained */
649             int nAlloc; /* Amount of space allocated in zText */
650             void *(*xRealloc)(void*,int); /* Function used to realloc memory */
651             };
652              
653             /*
654             ** This function implements the callback from vxprintf.
655             **
656             ** This routine add nNewChar characters of text in zNewText to
657             ** the sgMprintf structure pointed to by "arg".
658             */
659 112           static void mout(void *arg, const char *zNewText, int nNewChar){
660 112           struct sgMprintf *pM = (struct sgMprintf*)arg;
661 112           pM->nTotal += nNewChar;
662 112 50         if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
663 0 0         if( pM->xRealloc==0 ){
664 0           nNewChar = pM->nAlloc - pM->nChar - 1;
665             }else{
666 0           pM->nAlloc = pM->nChar + nNewChar*2 + 1;
667 0 0         if( pM->zText==pM->zBase ){
668 0           pM->zText = pM->xRealloc(0, pM->nAlloc);
669 0 0         if( pM->zText && pM->nChar ){
    0          
670 0           memcpy(pM->zText, pM->zBase, pM->nChar);
671             }
672             }else{
673 0           pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
674             }
675             }
676             }
677 112 50         if( pM->zText ){
678 112 100         if( nNewChar>0 ){
679 60           memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
680 60           pM->nChar += nNewChar;
681             }
682 112           pM->zText[pM->nChar] = 0;
683             }
684 112           }
685              
686             /*
687             ** This routine is a wrapper around xprintf() that invokes mout() as
688             ** the consumer.
689             */
690 52           static char *base_vprintf(
691             void *(*xRealloc)(void*,int), /* Routine to realloc memory. May be NULL */
692             int useInternal, /* Use internal %-conversions if true */
693             char *zInitBuf, /* Initially write here, before mallocing */
694             int nInitBuf, /* Size of zInitBuf[] */
695             const char *zFormat, /* format string */
696             va_list ap /* arguments */
697             ){
698             struct sgMprintf sM;
699 52           sM.zBase = sM.zText = zInitBuf;
700 52           sM.nChar = sM.nTotal = 0;
701 52           sM.nAlloc = nInitBuf;
702 52           sM.xRealloc = xRealloc;
703 52           vxprintf(mout, &sM, useInternal, zFormat, ap);
704 52 100         if( xRealloc ){
705 7 50         if( sM.zText==sM.zBase ){
706 7           sM.zText = xRealloc(0, sM.nChar+1);
707 7           memcpy(sM.zText, sM.zBase, sM.nChar+1);
708 0 0         }else if( sM.nAlloc>sM.nChar+10 ){
709 0           sM.zText = xRealloc(sM.zText, sM.nChar+1);
710             }
711             }
712 52           return sM.zText;
713             }
714              
715             /*
716             ** Realloc that is a real function, not a macro.
717             */
718 7           static void *printf_realloc(void *old, int size){
719 7           return sqliteRealloc(old,size);
720             }
721              
722             /*
723             ** Print into memory obtained from sqliteMalloc(). Use the internal
724             ** %-conversion extensions.
725             */
726 7           char *sqliteVMPrintf(const char *zFormat, va_list ap){
727             char zBase[1000];
728 7           return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
729             }
730              
731             /*
732             ** Print into memory obtained from sqliteMalloc(). Use the internal
733             ** %-conversion extensions.
734             */
735 0           char *sqliteMPrintf(const char *zFormat, ...){
736             va_list ap;
737             char *z;
738             char zBase[1000];
739 0           va_start(ap, zFormat);
740 0           z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
741 0           va_end(ap);
742 0           return z;
743             }
744              
745             /*
746             ** Print into memory obtained from malloc(). Do not use the internal
747             ** %-conversion extensions. This routine is for use by external users.
748             */
749 0           char *sqlite_mprintf(const char *zFormat, ...){
750             va_list ap;
751             char *z;
752             char zBuf[200];
753              
754 0           va_start(ap,zFormat);
755 0           z = base_vprintf((void*(*)(void*,int))realloc, 0,
756             zBuf, sizeof(zBuf), zFormat, ap);
757 0           va_end(ap);
758 0           return z;
759             }
760              
761             /* This is the varargs version of sqlite_mprintf.
762             */
763 0           char *sqlite_vmprintf(const char *zFormat, va_list ap){
764             char zBuf[200];
765 0           return base_vprintf((void*(*)(void*,int))realloc, 0,
766             zBuf, sizeof(zBuf), zFormat, ap);
767             }
768              
769             /*
770             ** sqlite_snprintf() works like snprintf() except that it ignores the
771             ** current locale settings. This is important for SQLite because we
772             ** are not able to use a "," as the decimal point in place of "." as
773             ** specified by some locales.
774             */
775 45           char *sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){
776             char *z;
777             va_list ap;
778              
779 45           va_start(ap,zFormat);
780 45           z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
781 45           va_end(ap);
782 45           return z;
783             }
784              
785             /*
786             ** The following four routines implement the varargs versions of the
787             ** sqlite_exec() and sqlite_get_table() interfaces. See the sqlite.h
788             ** header files for a more detailed description of how these interfaces
789             ** work.
790             **
791             ** These routines are all just simple wrappers.
792             */
793 0           int sqlite_exec_printf(
794             sqlite *db, /* An open database */
795             const char *sqlFormat, /* printf-style format string for the SQL */
796             sqlite_callback xCallback, /* Callback function */
797             void *pArg, /* 1st argument to callback function */
798             char **errmsg, /* Error msg written here */
799             ... /* Arguments to the format string. */
800             ){
801             va_list ap;
802             int rc;
803              
804 0           va_start(ap, errmsg);
805 0           rc = sqlite_exec_vprintf(db, sqlFormat, xCallback, pArg, errmsg, ap);
806 0           va_end(ap);
807 0           return rc;
808             }
809 0           int sqlite_exec_vprintf(
810             sqlite *db, /* An open database */
811             const char *sqlFormat, /* printf-style format string for the SQL */
812             sqlite_callback xCallback, /* Callback function */
813             void *pArg, /* 1st argument to callback function */
814             char **errmsg, /* Error msg written here */
815             va_list ap /* Arguments to the format string. */
816             ){
817             char *zSql;
818             int rc;
819              
820 0           zSql = sqlite_vmprintf(sqlFormat, ap);
821 0           rc = sqlite_exec(db, zSql, xCallback, pArg, errmsg);
822 0           free(zSql);
823 0           return rc;
824             }
825 0           int sqlite_get_table_printf(
826             sqlite *db, /* An open database */
827             const char *sqlFormat, /* printf-style format string for the SQL */
828             char ***resultp, /* Result written to a char *[] that this points to */
829             int *nrow, /* Number of result rows written here */
830             int *ncol, /* Number of result columns written here */
831             char **errmsg, /* Error msg written here */
832             ... /* Arguments to the format string */
833             ){
834             va_list ap;
835             int rc;
836              
837 0           va_start(ap, errmsg);
838 0           rc = sqlite_get_table_vprintf(db, sqlFormat, resultp, nrow, ncol, errmsg, ap);
839 0           va_end(ap);
840 0           return rc;
841             }
842 0           int sqlite_get_table_vprintf(
843             sqlite *db, /* An open database */
844             const char *sqlFormat, /* printf-style format string for the SQL */
845             char ***resultp, /* Result written to a char *[] that this points to */
846             int *nrow, /* Number of result rows written here */
847             int *ncolumn, /* Number of result columns written here */
848             char **errmsg, /* Error msg written here */
849             va_list ap /* Arguments to the format string */
850             ){
851             char *zSql;
852             int rc;
853              
854 0           zSql = sqlite_vmprintf(sqlFormat, ap);
855 0           rc = sqlite_get_table(db, zSql, resultp, nrow, ncolumn, errmsg);
856 0           free(zSql);
857 0           return rc;
858             }