Annotation of embedaddon/php/ext/sqlite/libsqlite/src/printf.c, revision 1.1.1.1
1.1 misho 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: static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
151: int digit;
152: LONGDOUBLE_TYPE d;
153: if( (*cnt)++ >= 16 ) return '0';
154: digit = (int)*val;
155: d = digit;
156: digit += '0';
157: *val = (*val - d)*10.0;
158: 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: 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: 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: func(arg,"",0);
231: count = length = 0;
232: bufpt = 0;
233: for(; (c=(*fmt))!=0; ++fmt){
234: if( c!='%' ){
235: int amt;
236: bufpt = (char *)fmt;
237: amt = 1;
238: while( (c=(*++fmt))!='%' && c!=0 ) amt++;
239: (*func)(arg,bufpt,amt);
240: count += amt;
241: if( c==0 ) break;
242: }
243: if( (c=(*++fmt))==0 ){
244: errorflag = 1;
245: (*func)(arg,"%",1);
246: count++;
247: break;
248: }
249: /* Find out what flags are present */
250: flag_leftjustify = flag_plussign = flag_blanksign =
251: flag_alternateform = flag_zeropad = 0;
252: do{
253: switch( c ){
254: case '-': flag_leftjustify = 1; c = 0; break;
255: case '+': flag_plussign = 1; c = 0; break;
256: case ' ': flag_blanksign = 1; c = 0; break;
257: case '#': flag_alternateform = 1; c = 0; break;
258: case '0': flag_zeropad = 1; c = 0; break;
259: default: break;
260: }
261: }while( c==0 && (c=(*++fmt))!=0 );
262: /* Get the field width */
263: width = 0;
264: if( c=='*' ){
265: width = va_arg(ap,int);
266: if( width<0 ){
267: flag_leftjustify = 1;
268: width = -width;
269: }
270: c = *++fmt;
271: }else{
272: while( c>='0' && c<='9' ){
273: width = width*10 + c - '0';
274: c = *++fmt;
275: }
276: }
277: if( width > etBUFSIZE-10 ){
278: width = etBUFSIZE-10;
279: }
280: /* Get the precision */
281: if( c=='.' ){
282: precision = 0;
283: c = *++fmt;
284: if( c=='*' ){
285: precision = va_arg(ap,int);
286: if( precision<0 ) precision = -precision;
287: c = *++fmt;
288: }else{
289: while( c>='0' && c<='9' ){
290: precision = precision*10 + c - '0';
291: c = *++fmt;
292: }
293: }
294: /* Limit the precision to prevent overflowing buf[] during conversion */
295: if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40;
296: }else{
297: precision = -1;
298: }
299: /* Get the conversion type modifier */
300: if( c=='l' ){
301: flag_long = 1;
302: c = *++fmt;
303: }else{
304: flag_long = 0;
305: }
306: /* Fetch the info entry for the field */
307: infop = 0;
308: xtype = etERROR;
309: for(idx=0; idx<etNINFO; idx++){
310: if( c==fmtinfo[idx].fmttype ){
311: infop = &fmtinfo[idx];
312: if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
313: xtype = infop->type;
314: }
315: break;
316: }
317: }
318: 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: switch( xtype ){
339: case etRADIX:
340: if( flag_long ) longvalue = va_arg(ap,long);
341: 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: 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: if( infop->flags & FLAG_SIGNED ){
352: if( *(long*)&longvalue<0 ){
353: longvalue = -*(long*)&longvalue;
354: prefix = '-';
355: }else if( flag_plussign ) prefix = '+';
356: else if( flag_blanksign ) prefix = ' ';
357: else prefix = 0;
358: }else prefix = 0;
359: if( flag_zeropad && precision<width-(prefix!=0) ){
360: precision = width-(prefix!=0);
361: }
362: bufpt = &buf[etBUFSIZE-1];
363: {
364: register char *cset; /* Use registers for speed */
365: register int base;
366: cset = infop->charset;
367: base = infop->base;
368: do{ /* Convert to ascii */
369: *(--bufpt) = cset[longvalue%base];
370: longvalue = longvalue/base;
371: }while( longvalue>0 );
372: }
373: length = &buf[etBUFSIZE-1]-bufpt;
374: for(idx=precision-length; idx>0; idx--){
375: *(--bufpt) = '0'; /* Zero pad */
376: }
377: if( prefix ) *(--bufpt) = prefix; /* Add sign */
378: if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
379: char *pre, x;
380: pre = infop->prefix;
381: if( *bufpt!=pre[0] ){
382: for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
383: }
384: }
385: length = &buf[etBUFSIZE-1]-bufpt;
386: break;
387: case etFLOAT:
388: case etEXP:
389: case etGENERIC:
390: realvalue = va_arg(ap,double);
391: #ifndef etNOFLOATINGPOINT
392: if( precision<0 ) precision = 6; /* Set default precision */
393: if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10;
394: if( realvalue<0.0 ){
395: realvalue = -realvalue;
396: prefix = '-';
397: }else{
398: if( flag_plussign ) prefix = '+';
399: else if( flag_blanksign ) prefix = ' ';
400: else prefix = 0;
401: }
402: if( infop->type==etGENERIC && precision>0 ) precision--;
403: 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: for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
410: #endif
411: if( infop->type==etFLOAT ) realvalue += rounder;
412: /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
413: exp = 0;
414: if( realvalue>0.0 ){
415: while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
416: while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
417: while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
418: while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
419: if( exp>350 || exp<-350 ){
420: bufpt = "NaN";
421: length = 3;
422: break;
423: }
424: }
425: bufpt = buf;
426: /*
427: ** If the field type is etGENERIC, then convert to either etEXP
428: ** or etFLOAT, as appropriate.
429: */
430: flag_exp = xtype==etEXP;
431: if( xtype!=etFLOAT ){
432: realvalue += rounder;
433: if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
434: }
435: if( xtype==etGENERIC ){
436: flag_rtz = !flag_alternateform;
437: if( exp<-4 || exp>precision ){
438: xtype = etEXP;
439: }else{
440: precision = precision - exp;
441: xtype = etFLOAT;
442: }
443: }else{
444: 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: nsd = 0;
451: if( xtype==etFLOAT && exp+precision<etBUFSIZE-30 ){
452: flag_dp = (precision>0 || flag_alternateform);
453: if( prefix ) *(bufpt++) = prefix; /* Sign */
454: if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */
455: else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd);
456: if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */
457: for(exp++; exp<0 && precision>0; precision--, exp++){
458: *(bufpt++) = '0';
459: }
460: while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
461: *(bufpt--) = 0; /* Null terminate */
462: if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */
463: while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
464: if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
465: }
466: bufpt++; /* point to next free slot */
467: }else{ /* etEXP or etGENERIC */
468: flag_dp = (precision>0 || flag_alternateform);
469: if( prefix ) *(bufpt++) = prefix; /* Sign */
470: *(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */
471: if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */
472: while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
473: bufpt--; /* point to last digit */
474: if( flag_rtz && flag_dp ){ /* Remove tail zeros */
475: while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
476: if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
477: }
478: bufpt++; /* point to next free slot */
479: if( exp || flag_exp ){
480: *(bufpt++) = infop->charset[0];
481: if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
482: else { *(bufpt++) = '+'; }
483: if( exp>=100 ){
484: *(bufpt++) = (exp/100)+'0'; /* 100's digit */
485: exp %= 100;
486: }
487: *(bufpt++) = exp/10+'0'; /* 10's digit */
488: *(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: length = bufpt-buf;
495: bufpt = buf;
496:
497: /* Special case: Add leading zeros if the flag_zeropad flag is
498: ** set and we are not left justified */
499: if( flag_zeropad && !flag_leftjustify && length < width){
500: int i;
501: int nPad = width - length;
502: for(i=width; i>=nPad; i--){
503: bufpt[i] = bufpt[i-nPad];
504: }
505: i = prefix!=0;
506: while( nPad-- ) bufpt[i++] = '0';
507: length = width;
508: }
509: #endif
510: break;
511: case etSIZE:
512: *(va_arg(ap,int*)) = count;
513: length = width = 0;
514: break;
515: case etPERCENT:
516: buf[0] = '%';
517: bufpt = buf;
518: length = 1;
519: break;
520: case etCHARLIT:
521: case etCHARX:
522: c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt);
523: if( precision>=0 ){
524: for(idx=1; idx<precision; idx++) buf[idx] = c;
525: length = precision;
526: }else{
527: length =1;
528: }
529: bufpt = buf;
530: break;
531: case etSTRING:
532: case etDYNSTRING:
533: bufpt = va_arg(ap,char*);
534: if( bufpt==0 ){
535: bufpt = "";
536: }else if( xtype==etDYNSTRING ){
537: zExtra = bufpt;
538: }
539: length = strlen(bufpt);
540: if( precision>=0 && precision<length ) length = precision;
541: break;
542: case etSQLESCAPE:
543: case etSQLESCAPE2:
544: {
545: int i, j, n, c, isnull;
546: char *arg = va_arg(ap,char*);
547: isnull = arg==0;
548: if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
549: for(i=n=0; (c=arg[i])!=0; i++){
550: if( c=='\'' ) n++;
551: }
552: n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0);
553: if( n>etBUFSIZE ){
554: bufpt = zExtra = sqliteMalloc( n );
555: if( bufpt==0 ) return -1;
556: }else{
557: bufpt = buf;
558: }
559: j = 0;
560: if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
561: for(i=0; (c=arg[i])!=0; i++){
562: bufpt[j++] = c;
563: if( c=='\'' ) bufpt[j++] = c;
564: }
565: if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
566: bufpt[j] = 0;
567: length = j;
568: if( precision>=0 && precision<length ) length = precision;
569: }
570: break;
571: case etTOKEN: {
572: Token *pToken = va_arg(ap, Token*);
573: (*func)(arg, pToken->z, pToken->n);
574: length = width = 0;
575: break;
576: }
577: case etSRCLIST: {
578: SrcList *pSrc = va_arg(ap, SrcList*);
579: int k = va_arg(ap, int);
580: struct SrcList_item *pItem = &pSrc->a[k];
581: assert( k>=0 && k<pSrc->nSrc );
582: if( pItem->zDatabase && pItem->zDatabase[0] ){
583: (*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase));
584: (*func)(arg, ".", 1);
585: }
586: (*func)(arg, pItem->zName, strlen(pItem->zName));
587: length = width = 0;
588: break;
589: }
590: case etERROR:
591: buf[0] = '%';
592: buf[1] = c;
593: errorflag = 0;
594: idx = 1+(c!=0);
595: (*func)(arg,"%",idx);
596: count += idx;
597: if( c==0 ) fmt--;
598: 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: if( !flag_leftjustify ){
606: register int nspace;
607: nspace = width-length;
608: if( nspace>0 ){
609: count += nspace;
610: while( nspace>=etSPACESIZE ){
611: (*func)(arg,spaces,etSPACESIZE);
612: nspace -= etSPACESIZE;
613: }
614: if( nspace>0 ) (*func)(arg,spaces,nspace);
615: }
616: }
617: if( length>0 ){
618: (*func)(arg,bufpt,length);
619: count += length;
620: }
621: if( flag_leftjustify ){
622: register int nspace;
623: nspace = width-length;
624: if( nspace>0 ){
625: count += nspace;
626: while( nspace>=etSPACESIZE ){
627: (*func)(arg,spaces,etSPACESIZE);
628: nspace -= etSPACESIZE;
629: }
630: if( nspace>0 ) (*func)(arg,spaces,nspace);
631: }
632: }
633: if( zExtra ){
634: sqliteFree(zExtra);
635: }
636: }/* End for loop over the format string */
637: 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: static void mout(void *arg, const char *zNewText, int nNewChar){
660: struct sgMprintf *pM = (struct sgMprintf*)arg;
661: pM->nTotal += nNewChar;
662: if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
663: if( pM->xRealloc==0 ){
664: nNewChar = pM->nAlloc - pM->nChar - 1;
665: }else{
666: pM->nAlloc = pM->nChar + nNewChar*2 + 1;
667: if( pM->zText==pM->zBase ){
668: pM->zText = pM->xRealloc(0, pM->nAlloc);
669: if( pM->zText && pM->nChar ){
670: memcpy(pM->zText, pM->zBase, pM->nChar);
671: }
672: }else{
673: pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
674: }
675: }
676: }
677: if( pM->zText ){
678: if( nNewChar>0 ){
679: memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
680: pM->nChar += nNewChar;
681: }
682: pM->zText[pM->nChar] = 0;
683: }
684: }
685:
686: /*
687: ** This routine is a wrapper around xprintf() that invokes mout() as
688: ** the consumer.
689: */
690: 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: sM.zBase = sM.zText = zInitBuf;
700: sM.nChar = sM.nTotal = 0;
701: sM.nAlloc = nInitBuf;
702: sM.xRealloc = xRealloc;
703: vxprintf(mout, &sM, useInternal, zFormat, ap);
704: if( xRealloc ){
705: if( sM.zText==sM.zBase ){
706: sM.zText = xRealloc(0, sM.nChar+1);
707: memcpy(sM.zText, sM.zBase, sM.nChar+1);
708: }else if( sM.nAlloc>sM.nChar+10 ){
709: sM.zText = xRealloc(sM.zText, sM.nChar+1);
710: }
711: }
712: return sM.zText;
713: }
714:
715: /*
716: ** Realloc that is a real function, not a macro.
717: */
718: static void *printf_realloc(void *old, int size){
719: return sqliteRealloc(old,size);
720: }
721:
722: /*
723: ** Print into memory obtained from sqliteMalloc(). Use the internal
724: ** %-conversion extensions.
725: */
726: char *sqliteVMPrintf(const char *zFormat, va_list ap){
727: char zBase[1000];
728: 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: char *sqliteMPrintf(const char *zFormat, ...){
736: va_list ap;
737: char *z;
738: char zBase[1000];
739: va_start(ap, zFormat);
740: z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
741: va_end(ap);
742: 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: char *sqlite_mprintf(const char *zFormat, ...){
750: va_list ap;
751: char *z;
752: char zBuf[200];
753:
754: va_start(ap,zFormat);
755: z = base_vprintf((void*(*)(void*,int))realloc, 0,
756: zBuf, sizeof(zBuf), zFormat, ap);
757: va_end(ap);
758: return z;
759: }
760:
761: /* This is the varargs version of sqlite_mprintf.
762: */
763: char *sqlite_vmprintf(const char *zFormat, va_list ap){
764: char zBuf[200];
765: 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: char *sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){
776: char *z;
777: va_list ap;
778:
779: va_start(ap,zFormat);
780: z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
781: va_end(ap);
782: 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: 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: va_start(ap, errmsg);
805: rc = sqlite_exec_vprintf(db, sqlFormat, xCallback, pArg, errmsg, ap);
806: va_end(ap);
807: return rc;
808: }
809: 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: zSql = sqlite_vmprintf(sqlFormat, ap);
821: rc = sqlite_exec(db, zSql, xCallback, pArg, errmsg);
822: free(zSql);
823: return rc;
824: }
825: 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: va_start(ap, errmsg);
838: rc = sqlite_get_table_vprintf(db, sqlFormat, resultp, nrow, ncol, errmsg, ap);
839: va_end(ap);
840: return rc;
841: }
842: 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: zSql = sqlite_vmprintf(sqlFormat, ap);
855: rc = sqlite_get_table(db, zSql, resultp, nrow, ncolumn, errmsg);
856: free(zSql);
857: return rc;
858: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>