Annotation of embedaddon/sqlite3/src/printf.c, revision 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: ** This file contains code for a set of "printf"-like routines. These
! 11: ** routines format strings much like the printf() from the standard C
! 12: ** library, though the implementation here has enhancements to support
! 13: ** SQLlite.
! 14: */
! 15: #include "sqliteInt.h"
! 16:
! 17: /*
! 18: ** Conversion types fall into various categories as defined by the
! 19: ** following enumeration.
! 20: */
! 21: #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
! 22: #define etFLOAT 2 /* Floating point. %f */
! 23: #define etEXP 3 /* Exponentional notation. %e and %E */
! 24: #define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
! 25: #define etSIZE 5 /* Return number of characters processed so far. %n */
! 26: #define etSTRING 6 /* Strings. %s */
! 27: #define etDYNSTRING 7 /* Dynamically allocated strings. %z */
! 28: #define etPERCENT 8 /* Percent symbol. %% */
! 29: #define etCHARX 9 /* Characters. %c */
! 30: /* The rest are extensions, not normally found in printf() */
! 31: #define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */
! 32: #define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '',
! 33: NULL pointers replaced by SQL NULL. %Q */
! 34: #define etTOKEN 12 /* a pointer to a Token structure */
! 35: #define etSRCLIST 13 /* a pointer to a SrcList */
! 36: #define etPOINTER 14 /* The %p conversion */
! 37: #define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
! 38: #define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
! 39:
! 40: #define etINVALID 0 /* Any unrecognized conversion type */
! 41:
! 42:
! 43: /*
! 44: ** An "etByte" is an 8-bit unsigned value.
! 45: */
! 46: typedef unsigned char etByte;
! 47:
! 48: /*
! 49: ** Each builtin conversion character (ex: the 'd' in "%d") is described
! 50: ** by an instance of the following structure
! 51: */
! 52: typedef struct et_info { /* Information about each format field */
! 53: char fmttype; /* The format field code letter */
! 54: etByte base; /* The base for radix conversion */
! 55: etByte flags; /* One or more of FLAG_ constants below */
! 56: etByte type; /* Conversion paradigm */
! 57: etByte charset; /* Offset into aDigits[] of the digits string */
! 58: etByte prefix; /* Offset into aPrefix[] of the prefix string */
! 59: } et_info;
! 60:
! 61: /*
! 62: ** Allowed values for et_info.flags
! 63: */
! 64: #define FLAG_SIGNED 1 /* True if the value to convert is signed */
! 65: #define FLAG_INTERN 2 /* True if for internal use only */
! 66: #define FLAG_STRING 4 /* Allow infinity precision */
! 67:
! 68:
! 69: /*
! 70: ** The following table is searched linearly, so it is good to put the
! 71: ** most frequently used conversion types first.
! 72: */
! 73: static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
! 74: static const char aPrefix[] = "-x0\000X0";
! 75: static const et_info fmtinfo[] = {
! 76: { 'd', 10, 1, etRADIX, 0, 0 },
! 77: { 's', 0, 4, etSTRING, 0, 0 },
! 78: { 'g', 0, 1, etGENERIC, 30, 0 },
! 79: { 'z', 0, 4, etDYNSTRING, 0, 0 },
! 80: { 'q', 0, 4, etSQLESCAPE, 0, 0 },
! 81: { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
! 82: { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
! 83: { 'c', 0, 0, etCHARX, 0, 0 },
! 84: { 'o', 8, 0, etRADIX, 0, 2 },
! 85: { 'u', 10, 0, etRADIX, 0, 0 },
! 86: { 'x', 16, 0, etRADIX, 16, 1 },
! 87: { 'X', 16, 0, etRADIX, 0, 4 },
! 88: #ifndef SQLITE_OMIT_FLOATING_POINT
! 89: { 'f', 0, 1, etFLOAT, 0, 0 },
! 90: { 'e', 0, 1, etEXP, 30, 0 },
! 91: { 'E', 0, 1, etEXP, 14, 0 },
! 92: { 'G', 0, 1, etGENERIC, 14, 0 },
! 93: #endif
! 94: { 'i', 10, 1, etRADIX, 0, 0 },
! 95: { 'n', 0, 0, etSIZE, 0, 0 },
! 96: { '%', 0, 0, etPERCENT, 0, 0 },
! 97: { 'p', 16, 0, etPOINTER, 0, 1 },
! 98:
! 99: /* All the rest have the FLAG_INTERN bit set and are thus for internal
! 100: ** use only */
! 101: { 'T', 0, 2, etTOKEN, 0, 0 },
! 102: { 'S', 0, 2, etSRCLIST, 0, 0 },
! 103: { 'r', 10, 3, etORDINAL, 0, 0 },
! 104: };
! 105:
! 106: /*
! 107: ** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
! 108: ** conversions will work.
! 109: */
! 110: #ifndef SQLITE_OMIT_FLOATING_POINT
! 111: /*
! 112: ** "*val" is a double such that 0.1 <= *val < 10.0
! 113: ** Return the ascii code for the leading digit of *val, then
! 114: ** multiply "*val" by 10.0 to renormalize.
! 115: **
! 116: ** Example:
! 117: ** input: *val = 3.14159
! 118: ** output: *val = 1.4159 function return = '3'
! 119: **
! 120: ** The counter *cnt is incremented each time. After counter exceeds
! 121: ** 16 (the number of significant digits in a 64-bit float) '0' is
! 122: ** always returned.
! 123: */
! 124: static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
! 125: int digit;
! 126: LONGDOUBLE_TYPE d;
! 127: if( (*cnt)++ >= 16 ) return '0';
! 128: digit = (int)*val;
! 129: d = digit;
! 130: digit += '0';
! 131: *val = (*val - d)*10.0;
! 132: return (char)digit;
! 133: }
! 134: #endif /* SQLITE_OMIT_FLOATING_POINT */
! 135:
! 136: /*
! 137: ** Append N space characters to the given string buffer.
! 138: */
! 139: void sqlite3AppendSpace(StrAccum *pAccum, int N){
! 140: static const char zSpaces[] = " ";
! 141: while( N>=(int)sizeof(zSpaces)-1 ){
! 142: sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
! 143: N -= sizeof(zSpaces)-1;
! 144: }
! 145: if( N>0 ){
! 146: sqlite3StrAccumAppend(pAccum, zSpaces, N);
! 147: }
! 148: }
! 149:
! 150: /*
! 151: ** On machines with a small stack size, you can redefine the
! 152: ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
! 153: */
! 154: #ifndef SQLITE_PRINT_BUF_SIZE
! 155: # define SQLITE_PRINT_BUF_SIZE 70
! 156: #endif
! 157: #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
! 158:
! 159: /*
! 160: ** Render a string given by "fmt" into the StrAccum object.
! 161: */
! 162: void sqlite3VXPrintf(
! 163: StrAccum *pAccum, /* Accumulate results here */
! 164: int useExtended, /* Allow extended %-conversions */
! 165: const char *fmt, /* Format string */
! 166: va_list ap /* arguments */
! 167: ){
! 168: int c; /* Next character in the format string */
! 169: char *bufpt; /* Pointer to the conversion buffer */
! 170: int precision; /* Precision of the current field */
! 171: int length; /* Length of the field */
! 172: int idx; /* A general purpose loop counter */
! 173: int width; /* Width of the current field */
! 174: etByte flag_leftjustify; /* True if "-" flag is present */
! 175: etByte flag_plussign; /* True if "+" flag is present */
! 176: etByte flag_blanksign; /* True if " " flag is present */
! 177: etByte flag_alternateform; /* True if "#" flag is present */
! 178: etByte flag_altform2; /* True if "!" flag is present */
! 179: etByte flag_zeropad; /* True if field width constant starts with zero */
! 180: etByte flag_long; /* True if "l" flag is present */
! 181: etByte flag_longlong; /* True if the "ll" flag is present */
! 182: etByte done; /* Loop termination flag */
! 183: etByte xtype = 0; /* Conversion paradigm */
! 184: char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
! 185: sqlite_uint64 longvalue; /* Value for integer types */
! 186: LONGDOUBLE_TYPE realvalue; /* Value for real types */
! 187: const et_info *infop; /* Pointer to the appropriate info structure */
! 188: char *zOut; /* Rendering buffer */
! 189: int nOut; /* Size of the rendering buffer */
! 190: char *zExtra; /* Malloced memory used by some conversion */
! 191: #ifndef SQLITE_OMIT_FLOATING_POINT
! 192: int exp, e2; /* exponent of real numbers */
! 193: int nsd; /* Number of significant digits returned */
! 194: double rounder; /* Used for rounding floating point values */
! 195: etByte flag_dp; /* True if decimal point should be shown */
! 196: etByte flag_rtz; /* True if trailing zeros should be removed */
! 197: #endif
! 198: char buf[etBUFSIZE]; /* Conversion buffer */
! 199:
! 200: bufpt = 0;
! 201: for(; (c=(*fmt))!=0; ++fmt){
! 202: if( c!='%' ){
! 203: int amt;
! 204: bufpt = (char *)fmt;
! 205: amt = 1;
! 206: while( (c=(*++fmt))!='%' && c!=0 ) amt++;
! 207: sqlite3StrAccumAppend(pAccum, bufpt, amt);
! 208: if( c==0 ) break;
! 209: }
! 210: if( (c=(*++fmt))==0 ){
! 211: sqlite3StrAccumAppend(pAccum, "%", 1);
! 212: break;
! 213: }
! 214: /* Find out what flags are present */
! 215: flag_leftjustify = flag_plussign = flag_blanksign =
! 216: flag_alternateform = flag_altform2 = flag_zeropad = 0;
! 217: done = 0;
! 218: do{
! 219: switch( c ){
! 220: case '-': flag_leftjustify = 1; break;
! 221: case '+': flag_plussign = 1; break;
! 222: case ' ': flag_blanksign = 1; break;
! 223: case '#': flag_alternateform = 1; break;
! 224: case '!': flag_altform2 = 1; break;
! 225: case '0': flag_zeropad = 1; break;
! 226: default: done = 1; break;
! 227: }
! 228: }while( !done && (c=(*++fmt))!=0 );
! 229: /* Get the field width */
! 230: width = 0;
! 231: if( c=='*' ){
! 232: width = va_arg(ap,int);
! 233: if( width<0 ){
! 234: flag_leftjustify = 1;
! 235: width = -width;
! 236: }
! 237: c = *++fmt;
! 238: }else{
! 239: while( c>='0' && c<='9' ){
! 240: width = width*10 + c - '0';
! 241: c = *++fmt;
! 242: }
! 243: }
! 244: /* Get the precision */
! 245: if( c=='.' ){
! 246: precision = 0;
! 247: c = *++fmt;
! 248: if( c=='*' ){
! 249: precision = va_arg(ap,int);
! 250: if( precision<0 ) precision = -precision;
! 251: c = *++fmt;
! 252: }else{
! 253: while( c>='0' && c<='9' ){
! 254: precision = precision*10 + c - '0';
! 255: c = *++fmt;
! 256: }
! 257: }
! 258: }else{
! 259: precision = -1;
! 260: }
! 261: /* Get the conversion type modifier */
! 262: if( c=='l' ){
! 263: flag_long = 1;
! 264: c = *++fmt;
! 265: if( c=='l' ){
! 266: flag_longlong = 1;
! 267: c = *++fmt;
! 268: }else{
! 269: flag_longlong = 0;
! 270: }
! 271: }else{
! 272: flag_long = flag_longlong = 0;
! 273: }
! 274: /* Fetch the info entry for the field */
! 275: infop = &fmtinfo[0];
! 276: xtype = etINVALID;
! 277: for(idx=0; idx<ArraySize(fmtinfo); idx++){
! 278: if( c==fmtinfo[idx].fmttype ){
! 279: infop = &fmtinfo[idx];
! 280: if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
! 281: xtype = infop->type;
! 282: }else{
! 283: return;
! 284: }
! 285: break;
! 286: }
! 287: }
! 288: zExtra = 0;
! 289:
! 290: /*
! 291: ** At this point, variables are initialized as follows:
! 292: **
! 293: ** flag_alternateform TRUE if a '#' is present.
! 294: ** flag_altform2 TRUE if a '!' is present.
! 295: ** flag_plussign TRUE if a '+' is present.
! 296: ** flag_leftjustify TRUE if a '-' is present or if the
! 297: ** field width was negative.
! 298: ** flag_zeropad TRUE if the width began with 0.
! 299: ** flag_long TRUE if the letter 'l' (ell) prefixed
! 300: ** the conversion character.
! 301: ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
! 302: ** the conversion character.
! 303: ** flag_blanksign TRUE if a ' ' is present.
! 304: ** width The specified field width. This is
! 305: ** always non-negative. Zero is the default.
! 306: ** precision The specified precision. The default
! 307: ** is -1.
! 308: ** xtype The class of the conversion.
! 309: ** infop Pointer to the appropriate info struct.
! 310: */
! 311: switch( xtype ){
! 312: case etPOINTER:
! 313: flag_longlong = sizeof(char*)==sizeof(i64);
! 314: flag_long = sizeof(char*)==sizeof(long int);
! 315: /* Fall through into the next case */
! 316: case etORDINAL:
! 317: case etRADIX:
! 318: if( infop->flags & FLAG_SIGNED ){
! 319: i64 v;
! 320: if( flag_longlong ){
! 321: v = va_arg(ap,i64);
! 322: }else if( flag_long ){
! 323: v = va_arg(ap,long int);
! 324: }else{
! 325: v = va_arg(ap,int);
! 326: }
! 327: if( v<0 ){
! 328: if( v==SMALLEST_INT64 ){
! 329: longvalue = ((u64)1)<<63;
! 330: }else{
! 331: longvalue = -v;
! 332: }
! 333: prefix = '-';
! 334: }else{
! 335: longvalue = v;
! 336: if( flag_plussign ) prefix = '+';
! 337: else if( flag_blanksign ) prefix = ' ';
! 338: else prefix = 0;
! 339: }
! 340: }else{
! 341: if( flag_longlong ){
! 342: longvalue = va_arg(ap,u64);
! 343: }else if( flag_long ){
! 344: longvalue = va_arg(ap,unsigned long int);
! 345: }else{
! 346: longvalue = va_arg(ap,unsigned int);
! 347: }
! 348: prefix = 0;
! 349: }
! 350: if( longvalue==0 ) flag_alternateform = 0;
! 351: if( flag_zeropad && precision<width-(prefix!=0) ){
! 352: precision = width-(prefix!=0);
! 353: }
! 354: if( precision<etBUFSIZE-10 ){
! 355: nOut = etBUFSIZE;
! 356: zOut = buf;
! 357: }else{
! 358: nOut = precision + 10;
! 359: zOut = zExtra = sqlite3Malloc( nOut );
! 360: if( zOut==0 ){
! 361: pAccum->mallocFailed = 1;
! 362: return;
! 363: }
! 364: }
! 365: bufpt = &zOut[nOut-1];
! 366: if( xtype==etORDINAL ){
! 367: static const char zOrd[] = "thstndrd";
! 368: int x = (int)(longvalue % 10);
! 369: if( x>=4 || (longvalue/10)%10==1 ){
! 370: x = 0;
! 371: }
! 372: *(--bufpt) = zOrd[x*2+1];
! 373: *(--bufpt) = zOrd[x*2];
! 374: }
! 375: {
! 376: register const char *cset; /* Use registers for speed */
! 377: register int base;
! 378: cset = &aDigits[infop->charset];
! 379: base = infop->base;
! 380: do{ /* Convert to ascii */
! 381: *(--bufpt) = cset[longvalue%base];
! 382: longvalue = longvalue/base;
! 383: }while( longvalue>0 );
! 384: }
! 385: length = (int)(&zOut[nOut-1]-bufpt);
! 386: for(idx=precision-length; idx>0; idx--){
! 387: *(--bufpt) = '0'; /* Zero pad */
! 388: }
! 389: if( prefix ) *(--bufpt) = prefix; /* Add sign */
! 390: if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
! 391: const char *pre;
! 392: char x;
! 393: pre = &aPrefix[infop->prefix];
! 394: for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
! 395: }
! 396: length = (int)(&zOut[nOut-1]-bufpt);
! 397: break;
! 398: case etFLOAT:
! 399: case etEXP:
! 400: case etGENERIC:
! 401: realvalue = va_arg(ap,double);
! 402: #ifdef SQLITE_OMIT_FLOATING_POINT
! 403: length = 0;
! 404: #else
! 405: if( precision<0 ) precision = 6; /* Set default precision */
! 406: if( realvalue<0.0 ){
! 407: realvalue = -realvalue;
! 408: prefix = '-';
! 409: }else{
! 410: if( flag_plussign ) prefix = '+';
! 411: else if( flag_blanksign ) prefix = ' ';
! 412: else prefix = 0;
! 413: }
! 414: if( xtype==etGENERIC && precision>0 ) precision--;
! 415: #if 0
! 416: /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
! 417: for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
! 418: #else
! 419: /* It makes more sense to use 0.5 */
! 420: for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
! 421: #endif
! 422: if( xtype==etFLOAT ) realvalue += rounder;
! 423: /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
! 424: exp = 0;
! 425: if( sqlite3IsNaN((double)realvalue) ){
! 426: bufpt = "NaN";
! 427: length = 3;
! 428: break;
! 429: }
! 430: if( realvalue>0.0 ){
! 431: while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
! 432: while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
! 433: while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
! 434: while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
! 435: while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
! 436: if( exp>350 ){
! 437: if( prefix=='-' ){
! 438: bufpt = "-Inf";
! 439: }else if( prefix=='+' ){
! 440: bufpt = "+Inf";
! 441: }else{
! 442: bufpt = "Inf";
! 443: }
! 444: length = sqlite3Strlen30(bufpt);
! 445: break;
! 446: }
! 447: }
! 448: bufpt = buf;
! 449: /*
! 450: ** If the field type is etGENERIC, then convert to either etEXP
! 451: ** or etFLOAT, as appropriate.
! 452: */
! 453: if( xtype!=etFLOAT ){
! 454: realvalue += rounder;
! 455: if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
! 456: }
! 457: if( xtype==etGENERIC ){
! 458: flag_rtz = !flag_alternateform;
! 459: if( exp<-4 || exp>precision ){
! 460: xtype = etEXP;
! 461: }else{
! 462: precision = precision - exp;
! 463: xtype = etFLOAT;
! 464: }
! 465: }else{
! 466: flag_rtz = 0;
! 467: }
! 468: if( xtype==etEXP ){
! 469: e2 = 0;
! 470: }else{
! 471: e2 = exp;
! 472: }
! 473: if( e2+precision+width > etBUFSIZE - 15 ){
! 474: bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
! 475: if( bufpt==0 ){
! 476: pAccum->mallocFailed = 1;
! 477: return;
! 478: }
! 479: }
! 480: zOut = bufpt;
! 481: nsd = 0;
! 482: flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
! 483: /* The sign in front of the number */
! 484: if( prefix ){
! 485: *(bufpt++) = prefix;
! 486: }
! 487: /* Digits prior to the decimal point */
! 488: if( e2<0 ){
! 489: *(bufpt++) = '0';
! 490: }else{
! 491: for(; e2>=0; e2--){
! 492: *(bufpt++) = et_getdigit(&realvalue,&nsd);
! 493: }
! 494: }
! 495: /* The decimal point */
! 496: if( flag_dp ){
! 497: *(bufpt++) = '.';
! 498: }
! 499: /* "0" digits after the decimal point but before the first
! 500: ** significant digit of the number */
! 501: for(e2++; e2<0; precision--, e2++){
! 502: assert( precision>0 );
! 503: *(bufpt++) = '0';
! 504: }
! 505: /* Significant digits after the decimal point */
! 506: while( (precision--)>0 ){
! 507: *(bufpt++) = et_getdigit(&realvalue,&nsd);
! 508: }
! 509: /* Remove trailing zeros and the "." if no digits follow the "." */
! 510: if( flag_rtz && flag_dp ){
! 511: while( bufpt[-1]=='0' ) *(--bufpt) = 0;
! 512: assert( bufpt>zOut );
! 513: if( bufpt[-1]=='.' ){
! 514: if( flag_altform2 ){
! 515: *(bufpt++) = '0';
! 516: }else{
! 517: *(--bufpt) = 0;
! 518: }
! 519: }
! 520: }
! 521: /* Add the "eNNN" suffix */
! 522: if( xtype==etEXP ){
! 523: *(bufpt++) = aDigits[infop->charset];
! 524: if( exp<0 ){
! 525: *(bufpt++) = '-'; exp = -exp;
! 526: }else{
! 527: *(bufpt++) = '+';
! 528: }
! 529: if( exp>=100 ){
! 530: *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */
! 531: exp %= 100;
! 532: }
! 533: *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
! 534: *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */
! 535: }
! 536: *bufpt = 0;
! 537:
! 538: /* The converted number is in buf[] and zero terminated. Output it.
! 539: ** Note that the number is in the usual order, not reversed as with
! 540: ** integer conversions. */
! 541: length = (int)(bufpt-zOut);
! 542: bufpt = zOut;
! 543:
! 544: /* Special case: Add leading zeros if the flag_zeropad flag is
! 545: ** set and we are not left justified */
! 546: if( flag_zeropad && !flag_leftjustify && length < width){
! 547: int i;
! 548: int nPad = width - length;
! 549: for(i=width; i>=nPad; i--){
! 550: bufpt[i] = bufpt[i-nPad];
! 551: }
! 552: i = prefix!=0;
! 553: while( nPad-- ) bufpt[i++] = '0';
! 554: length = width;
! 555: }
! 556: #endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
! 557: break;
! 558: case etSIZE:
! 559: *(va_arg(ap,int*)) = pAccum->nChar;
! 560: length = width = 0;
! 561: break;
! 562: case etPERCENT:
! 563: buf[0] = '%';
! 564: bufpt = buf;
! 565: length = 1;
! 566: break;
! 567: case etCHARX:
! 568: c = va_arg(ap,int);
! 569: buf[0] = (char)c;
! 570: if( precision>=0 ){
! 571: for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
! 572: length = precision;
! 573: }else{
! 574: length =1;
! 575: }
! 576: bufpt = buf;
! 577: break;
! 578: case etSTRING:
! 579: case etDYNSTRING:
! 580: bufpt = va_arg(ap,char*);
! 581: if( bufpt==0 ){
! 582: bufpt = "";
! 583: }else if( xtype==etDYNSTRING ){
! 584: zExtra = bufpt;
! 585: }
! 586: if( precision>=0 ){
! 587: for(length=0; length<precision && bufpt[length]; length++){}
! 588: }else{
! 589: length = sqlite3Strlen30(bufpt);
! 590: }
! 591: break;
! 592: case etSQLESCAPE:
! 593: case etSQLESCAPE2:
! 594: case etSQLESCAPE3: {
! 595: int i, j, k, n, isnull;
! 596: int needQuote;
! 597: char ch;
! 598: char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
! 599: char *escarg = va_arg(ap,char*);
! 600: isnull = escarg==0;
! 601: if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
! 602: k = precision;
! 603: for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
! 604: if( ch==q ) n++;
! 605: }
! 606: needQuote = !isnull && xtype==etSQLESCAPE2;
! 607: n += i + 1 + needQuote*2;
! 608: if( n>etBUFSIZE ){
! 609: bufpt = zExtra = sqlite3Malloc( n );
! 610: if( bufpt==0 ){
! 611: pAccum->mallocFailed = 1;
! 612: return;
! 613: }
! 614: }else{
! 615: bufpt = buf;
! 616: }
! 617: j = 0;
! 618: if( needQuote ) bufpt[j++] = q;
! 619: k = i;
! 620: for(i=0; i<k; i++){
! 621: bufpt[j++] = ch = escarg[i];
! 622: if( ch==q ) bufpt[j++] = ch;
! 623: }
! 624: if( needQuote ) bufpt[j++] = q;
! 625: bufpt[j] = 0;
! 626: length = j;
! 627: /* The precision in %q and %Q means how many input characters to
! 628: ** consume, not the length of the output...
! 629: ** if( precision>=0 && precision<length ) length = precision; */
! 630: break;
! 631: }
! 632: case etTOKEN: {
! 633: Token *pToken = va_arg(ap, Token*);
! 634: if( pToken ){
! 635: sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
! 636: }
! 637: length = width = 0;
! 638: break;
! 639: }
! 640: case etSRCLIST: {
! 641: SrcList *pSrc = va_arg(ap, SrcList*);
! 642: int k = va_arg(ap, int);
! 643: struct SrcList_item *pItem = &pSrc->a[k];
! 644: assert( k>=0 && k<pSrc->nSrc );
! 645: if( pItem->zDatabase ){
! 646: sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
! 647: sqlite3StrAccumAppend(pAccum, ".", 1);
! 648: }
! 649: sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
! 650: length = width = 0;
! 651: break;
! 652: }
! 653: default: {
! 654: assert( xtype==etINVALID );
! 655: return;
! 656: }
! 657: }/* End switch over the format type */
! 658: /*
! 659: ** The text of the conversion is pointed to by "bufpt" and is
! 660: ** "length" characters long. The field width is "width". Do
! 661: ** the output.
! 662: */
! 663: if( !flag_leftjustify ){
! 664: register int nspace;
! 665: nspace = width-length;
! 666: if( nspace>0 ){
! 667: sqlite3AppendSpace(pAccum, nspace);
! 668: }
! 669: }
! 670: if( length>0 ){
! 671: sqlite3StrAccumAppend(pAccum, bufpt, length);
! 672: }
! 673: if( flag_leftjustify ){
! 674: register int nspace;
! 675: nspace = width-length;
! 676: if( nspace>0 ){
! 677: sqlite3AppendSpace(pAccum, nspace);
! 678: }
! 679: }
! 680: sqlite3_free(zExtra);
! 681: }/* End for loop over the format string */
! 682: } /* End of function */
! 683:
! 684: /*
! 685: ** Append N bytes of text from z to the StrAccum object.
! 686: */
! 687: void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
! 688: assert( z!=0 || N==0 );
! 689: if( p->tooBig | p->mallocFailed ){
! 690: testcase(p->tooBig);
! 691: testcase(p->mallocFailed);
! 692: return;
! 693: }
! 694: assert( p->zText!=0 || p->nChar==0 );
! 695: if( N<0 ){
! 696: N = sqlite3Strlen30(z);
! 697: }
! 698: if( N==0 || NEVER(z==0) ){
! 699: return;
! 700: }
! 701: if( p->nChar+N >= p->nAlloc ){
! 702: char *zNew;
! 703: if( !p->useMalloc ){
! 704: p->tooBig = 1;
! 705: N = p->nAlloc - p->nChar - 1;
! 706: if( N<=0 ){
! 707: return;
! 708: }
! 709: }else{
! 710: char *zOld = (p->zText==p->zBase ? 0 : p->zText);
! 711: i64 szNew = p->nChar;
! 712: szNew += N + 1;
! 713: if( szNew > p->mxAlloc ){
! 714: sqlite3StrAccumReset(p);
! 715: p->tooBig = 1;
! 716: return;
! 717: }else{
! 718: p->nAlloc = (int)szNew;
! 719: }
! 720: if( p->useMalloc==1 ){
! 721: zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
! 722: }else{
! 723: zNew = sqlite3_realloc(zOld, p->nAlloc);
! 724: }
! 725: if( zNew ){
! 726: if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
! 727: p->zText = zNew;
! 728: }else{
! 729: p->mallocFailed = 1;
! 730: sqlite3StrAccumReset(p);
! 731: return;
! 732: }
! 733: }
! 734: }
! 735: assert( p->zText );
! 736: memcpy(&p->zText[p->nChar], z, N);
! 737: p->nChar += N;
! 738: }
! 739:
! 740: /*
! 741: ** Finish off a string by making sure it is zero-terminated.
! 742: ** Return a pointer to the resulting string. Return a NULL
! 743: ** pointer if any kind of error was encountered.
! 744: */
! 745: char *sqlite3StrAccumFinish(StrAccum *p){
! 746: if( p->zText ){
! 747: p->zText[p->nChar] = 0;
! 748: if( p->useMalloc && p->zText==p->zBase ){
! 749: if( p->useMalloc==1 ){
! 750: p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
! 751: }else{
! 752: p->zText = sqlite3_malloc(p->nChar+1);
! 753: }
! 754: if( p->zText ){
! 755: memcpy(p->zText, p->zBase, p->nChar+1);
! 756: }else{
! 757: p->mallocFailed = 1;
! 758: }
! 759: }
! 760: }
! 761: return p->zText;
! 762: }
! 763:
! 764: /*
! 765: ** Reset an StrAccum string. Reclaim all malloced memory.
! 766: */
! 767: void sqlite3StrAccumReset(StrAccum *p){
! 768: if( p->zText!=p->zBase ){
! 769: if( p->useMalloc==1 ){
! 770: sqlite3DbFree(p->db, p->zText);
! 771: }else{
! 772: sqlite3_free(p->zText);
! 773: }
! 774: }
! 775: p->zText = 0;
! 776: }
! 777:
! 778: /*
! 779: ** Initialize a string accumulator
! 780: */
! 781: void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
! 782: p->zText = p->zBase = zBase;
! 783: p->db = 0;
! 784: p->nChar = 0;
! 785: p->nAlloc = n;
! 786: p->mxAlloc = mx;
! 787: p->useMalloc = 1;
! 788: p->tooBig = 0;
! 789: p->mallocFailed = 0;
! 790: }
! 791:
! 792: /*
! 793: ** Print into memory obtained from sqliteMalloc(). Use the internal
! 794: ** %-conversion extensions.
! 795: */
! 796: char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
! 797: char *z;
! 798: char zBase[SQLITE_PRINT_BUF_SIZE];
! 799: StrAccum acc;
! 800: assert( db!=0 );
! 801: sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
! 802: db->aLimit[SQLITE_LIMIT_LENGTH]);
! 803: acc.db = db;
! 804: sqlite3VXPrintf(&acc, 1, zFormat, ap);
! 805: z = sqlite3StrAccumFinish(&acc);
! 806: if( acc.mallocFailed ){
! 807: db->mallocFailed = 1;
! 808: }
! 809: return z;
! 810: }
! 811:
! 812: /*
! 813: ** Print into memory obtained from sqliteMalloc(). Use the internal
! 814: ** %-conversion extensions.
! 815: */
! 816: char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
! 817: va_list ap;
! 818: char *z;
! 819: va_start(ap, zFormat);
! 820: z = sqlite3VMPrintf(db, zFormat, ap);
! 821: va_end(ap);
! 822: return z;
! 823: }
! 824:
! 825: /*
! 826: ** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
! 827: ** the string and before returnning. This routine is intended to be used
! 828: ** to modify an existing string. For example:
! 829: **
! 830: ** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
! 831: **
! 832: */
! 833: char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
! 834: va_list ap;
! 835: char *z;
! 836: va_start(ap, zFormat);
! 837: z = sqlite3VMPrintf(db, zFormat, ap);
! 838: va_end(ap);
! 839: sqlite3DbFree(db, zStr);
! 840: return z;
! 841: }
! 842:
! 843: /*
! 844: ** Print into memory obtained from sqlite3_malloc(). Omit the internal
! 845: ** %-conversion extensions.
! 846: */
! 847: char *sqlite3_vmprintf(const char *zFormat, va_list ap){
! 848: char *z;
! 849: char zBase[SQLITE_PRINT_BUF_SIZE];
! 850: StrAccum acc;
! 851: #ifndef SQLITE_OMIT_AUTOINIT
! 852: if( sqlite3_initialize() ) return 0;
! 853: #endif
! 854: sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
! 855: acc.useMalloc = 2;
! 856: sqlite3VXPrintf(&acc, 0, zFormat, ap);
! 857: z = sqlite3StrAccumFinish(&acc);
! 858: return z;
! 859: }
! 860:
! 861: /*
! 862: ** Print into memory obtained from sqlite3_malloc()(). Omit the internal
! 863: ** %-conversion extensions.
! 864: */
! 865: char *sqlite3_mprintf(const char *zFormat, ...){
! 866: va_list ap;
! 867: char *z;
! 868: #ifndef SQLITE_OMIT_AUTOINIT
! 869: if( sqlite3_initialize() ) return 0;
! 870: #endif
! 871: va_start(ap, zFormat);
! 872: z = sqlite3_vmprintf(zFormat, ap);
! 873: va_end(ap);
! 874: return z;
! 875: }
! 876:
! 877: /*
! 878: ** sqlite3_snprintf() works like snprintf() except that it ignores the
! 879: ** current locale settings. This is important for SQLite because we
! 880: ** are not able to use a "," as the decimal point in place of "." as
! 881: ** specified by some locales.
! 882: **
! 883: ** Oops: The first two arguments of sqlite3_snprintf() are backwards
! 884: ** from the snprintf() standard. Unfortunately, it is too late to change
! 885: ** this without breaking compatibility, so we just have to live with the
! 886: ** mistake.
! 887: **
! 888: ** sqlite3_vsnprintf() is the varargs version.
! 889: */
! 890: char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
! 891: StrAccum acc;
! 892: if( n<=0 ) return zBuf;
! 893: sqlite3StrAccumInit(&acc, zBuf, n, 0);
! 894: acc.useMalloc = 0;
! 895: sqlite3VXPrintf(&acc, 0, zFormat, ap);
! 896: return sqlite3StrAccumFinish(&acc);
! 897: }
! 898: char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
! 899: char *z;
! 900: va_list ap;
! 901: va_start(ap,zFormat);
! 902: z = sqlite3_vsnprintf(n, zBuf, zFormat, ap);
! 903: va_end(ap);
! 904: return z;
! 905: }
! 906:
! 907: /*
! 908: ** This is the routine that actually formats the sqlite3_log() message.
! 909: ** We house it in a separate routine from sqlite3_log() to avoid using
! 910: ** stack space on small-stack systems when logging is disabled.
! 911: **
! 912: ** sqlite3_log() must render into a static buffer. It cannot dynamically
! 913: ** allocate memory because it might be called while the memory allocator
! 914: ** mutex is held.
! 915: */
! 916: static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
! 917: StrAccum acc; /* String accumulator */
! 918: char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
! 919:
! 920: sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
! 921: acc.useMalloc = 0;
! 922: sqlite3VXPrintf(&acc, 0, zFormat, ap);
! 923: sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
! 924: sqlite3StrAccumFinish(&acc));
! 925: }
! 926:
! 927: /*
! 928: ** Format and write a message to the log if logging is enabled.
! 929: */
! 930: void sqlite3_log(int iErrCode, const char *zFormat, ...){
! 931: va_list ap; /* Vararg list */
! 932: if( sqlite3GlobalConfig.xLog ){
! 933: va_start(ap, zFormat);
! 934: renderLogMsg(iErrCode, zFormat, ap);
! 935: va_end(ap);
! 936: }
! 937: }
! 938:
! 939: #if defined(SQLITE_DEBUG)
! 940: /*
! 941: ** A version of printf() that understands %lld. Used for debugging.
! 942: ** The printf() built into some versions of windows does not understand %lld
! 943: ** and segfaults if you give it a long long int.
! 944: */
! 945: void sqlite3DebugPrintf(const char *zFormat, ...){
! 946: va_list ap;
! 947: StrAccum acc;
! 948: char zBuf[500];
! 949: sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
! 950: acc.useMalloc = 0;
! 951: va_start(ap,zFormat);
! 952: sqlite3VXPrintf(&acc, 0, zFormat, ap);
! 953: va_end(ap);
! 954: sqlite3StrAccumFinish(&acc);
! 955: fprintf(stdout,"%s", zBuf);
! 956: fflush(stdout);
! 957: }
! 958: #endif
! 959:
! 960: #ifndef SQLITE_OMIT_TRACE
! 961: /*
! 962: ** variable-argument wrapper around sqlite3VXPrintf().
! 963: */
! 964: void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
! 965: va_list ap;
! 966: va_start(ap,zFormat);
! 967: sqlite3VXPrintf(p, 1, zFormat, ap);
! 968: va_end(ap);
! 969: }
! 970: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>