OLD | NEW |
1 /* | 1 /* |
2 ** The "printf" code that follows dates from the 1980's. It is in | 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 | 3 ** the public domain. |
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 ** | 4 ** |
8 ************************************************************************** | 5 ************************************************************************** |
9 ** | 6 ** |
10 ** This file contains code for a set of "printf"-like routines. These | 7 ** This file contains code for a set of "printf"-like routines. These |
11 ** routines format strings much like the printf() from the standard C | 8 ** routines format strings much like the printf() from the standard C |
12 ** library, though the implementation here has enhancements to support | 9 ** library, though the implementation here has enhancements to support |
13 ** SQLlite. | 10 ** SQLite. |
14 */ | 11 */ |
15 #include "sqliteInt.h" | 12 #include "sqliteInt.h" |
16 | 13 |
17 /* | 14 /* |
18 ** If the strchrnul() library function is available, then set | |
19 ** HAVE_STRCHRNUL. If that routine is not available, this module | |
20 ** will supply its own. The built-in version is slower than | |
21 ** the glibc version so the glibc version is definitely preferred. | |
22 */ | |
23 #if !defined(HAVE_STRCHRNUL) | |
24 # define HAVE_STRCHRNUL 0 | |
25 #endif | |
26 | |
27 | |
28 /* | |
29 ** Conversion types fall into various categories as defined by the | 15 ** Conversion types fall into various categories as defined by the |
30 ** following enumeration. | 16 ** following enumeration. |
31 */ | 17 */ |
32 #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ | 18 #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ |
33 #define etFLOAT 2 /* Floating point. %f */ | 19 #define etFLOAT 2 /* Floating point. %f */ |
34 #define etEXP 3 /* Exponentional notation. %e and %E */ | 20 #define etEXP 3 /* Exponentional notation. %e and %E */ |
35 #define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ | 21 #define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ |
36 #define etSIZE 5 /* Return number of characters processed so far. %n */ | 22 #define etSIZE 5 /* Return number of characters processed so far. %n */ |
37 #define etSTRING 6 /* Strings. %s */ | 23 #define etSTRING 6 /* Strings. %s */ |
38 #define etDYNSTRING 7 /* Dynamically allocated strings. %z */ | 24 #define etDYNSTRING 7 /* Dynamically allocated strings. %z */ |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 digit += '0'; | 128 digit += '0'; |
143 *val = (*val - d)*10.0; | 129 *val = (*val - d)*10.0; |
144 return (char)digit; | 130 return (char)digit; |
145 } | 131 } |
146 #endif /* SQLITE_OMIT_FLOATING_POINT */ | 132 #endif /* SQLITE_OMIT_FLOATING_POINT */ |
147 | 133 |
148 /* | 134 /* |
149 ** Set the StrAccum object to an error mode. | 135 ** Set the StrAccum object to an error mode. |
150 */ | 136 */ |
151 static void setStrAccumError(StrAccum *p, u8 eError){ | 137 static void setStrAccumError(StrAccum *p, u8 eError){ |
| 138 assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); |
152 p->accError = eError; | 139 p->accError = eError; |
153 p->nAlloc = 0; | 140 p->nAlloc = 0; |
154 } | 141 } |
155 | 142 |
156 /* | 143 /* |
157 ** Extra argument values from a PrintfArguments object | 144 ** Extra argument values from a PrintfArguments object |
158 */ | 145 */ |
159 static sqlite3_int64 getIntArg(PrintfArguments *p){ | 146 static sqlite3_int64 getIntArg(PrintfArguments *p){ |
160 if( p->nArg<=p->nUsed ) return 0; | 147 if( p->nArg<=p->nUsed ) return 0; |
161 return sqlite3_value_int64(p->apArg[p->nUsed++]); | 148 return sqlite3_value_int64(p->apArg[p->nUsed++]); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 case '-': flag_leftjustify = 1; break; | 243 case '-': flag_leftjustify = 1; break; |
257 case '+': flag_plussign = 1; break; | 244 case '+': flag_plussign = 1; break; |
258 case ' ': flag_blanksign = 1; break; | 245 case ' ': flag_blanksign = 1; break; |
259 case '#': flag_alternateform = 1; break; | 246 case '#': flag_alternateform = 1; break; |
260 case '!': flag_altform2 = 1; break; | 247 case '!': flag_altform2 = 1; break; |
261 case '0': flag_zeropad = 1; break; | 248 case '0': flag_zeropad = 1; break; |
262 default: done = 1; break; | 249 default: done = 1; break; |
263 } | 250 } |
264 }while( !done && (c=(*++fmt))!=0 ); | 251 }while( !done && (c=(*++fmt))!=0 ); |
265 /* Get the field width */ | 252 /* Get the field width */ |
266 width = 0; | |
267 if( c=='*' ){ | 253 if( c=='*' ){ |
268 if( bArgList ){ | 254 if( bArgList ){ |
269 width = (int)getIntArg(pArgList); | 255 width = (int)getIntArg(pArgList); |
270 }else{ | 256 }else{ |
271 width = va_arg(ap,int); | 257 width = va_arg(ap,int); |
272 } | 258 } |
273 if( width<0 ){ | 259 if( width<0 ){ |
274 flag_leftjustify = 1; | 260 flag_leftjustify = 1; |
275 width = -width; | 261 width = width >= -2147483647 ? -width : 0; |
276 } | 262 } |
277 c = *++fmt; | 263 c = *++fmt; |
278 }else{ | 264 }else{ |
| 265 unsigned wx = 0; |
279 while( c>='0' && c<='9' ){ | 266 while( c>='0' && c<='9' ){ |
280 width = width*10 + c - '0'; | 267 wx = wx*10 + c - '0'; |
281 c = *++fmt; | 268 c = *++fmt; |
282 } | 269 } |
| 270 testcase( wx>0x7fffffff ); |
| 271 width = wx & 0x7fffffff; |
283 } | 272 } |
| 273 assert( width>=0 ); |
| 274 #ifdef SQLITE_PRINTF_PRECISION_LIMIT |
| 275 if( width>SQLITE_PRINTF_PRECISION_LIMIT ){ |
| 276 width = SQLITE_PRINTF_PRECISION_LIMIT; |
| 277 } |
| 278 #endif |
| 279 |
284 /* Get the precision */ | 280 /* Get the precision */ |
285 if( c=='.' ){ | 281 if( c=='.' ){ |
286 precision = 0; | |
287 c = *++fmt; | 282 c = *++fmt; |
288 if( c=='*' ){ | 283 if( c=='*' ){ |
289 if( bArgList ){ | 284 if( bArgList ){ |
290 precision = (int)getIntArg(pArgList); | 285 precision = (int)getIntArg(pArgList); |
291 }else{ | 286 }else{ |
292 precision = va_arg(ap,int); | 287 precision = va_arg(ap,int); |
293 } | 288 } |
294 if( precision<0 ) precision = -precision; | |
295 c = *++fmt; | 289 c = *++fmt; |
| 290 if( precision<0 ){ |
| 291 precision = precision >= -2147483647 ? -precision : -1; |
| 292 } |
296 }else{ | 293 }else{ |
| 294 unsigned px = 0; |
297 while( c>='0' && c<='9' ){ | 295 while( c>='0' && c<='9' ){ |
298 precision = precision*10 + c - '0'; | 296 px = px*10 + c - '0'; |
299 c = *++fmt; | 297 c = *++fmt; |
300 } | 298 } |
| 299 testcase( px>0x7fffffff ); |
| 300 precision = px & 0x7fffffff; |
301 } | 301 } |
302 }else{ | 302 }else{ |
303 precision = -1; | 303 precision = -1; |
304 } | 304 } |
| 305 assert( precision>=(-1) ); |
| 306 #ifdef SQLITE_PRINTF_PRECISION_LIMIT |
| 307 if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){ |
| 308 precision = SQLITE_PRINTF_PRECISION_LIMIT; |
| 309 } |
| 310 #endif |
| 311 |
| 312 |
305 /* Get the conversion type modifier */ | 313 /* Get the conversion type modifier */ |
306 if( c=='l' ){ | 314 if( c=='l' ){ |
307 flag_long = 1; | 315 flag_long = 1; |
308 c = *++fmt; | 316 c = *++fmt; |
309 if( c=='l' ){ | 317 if( c=='l' ){ |
310 flag_longlong = 1; | 318 flag_longlong = 1; |
311 c = *++fmt; | 319 c = *++fmt; |
312 }else{ | 320 }else{ |
313 flag_longlong = 0; | 321 flag_longlong = 0; |
314 } | 322 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 if( precision<0 ) precision = 6; /* Set default precision */ | 462 if( precision<0 ) precision = 6; /* Set default precision */ |
455 if( realvalue<0.0 ){ | 463 if( realvalue<0.0 ){ |
456 realvalue = -realvalue; | 464 realvalue = -realvalue; |
457 prefix = '-'; | 465 prefix = '-'; |
458 }else{ | 466 }else{ |
459 if( flag_plussign ) prefix = '+'; | 467 if( flag_plussign ) prefix = '+'; |
460 else if( flag_blanksign ) prefix = ' '; | 468 else if( flag_blanksign ) prefix = ' '; |
461 else prefix = 0; | 469 else prefix = 0; |
462 } | 470 } |
463 if( xtype==etGENERIC && precision>0 ) precision--; | 471 if( xtype==etGENERIC && precision>0 ) precision--; |
464 for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){} | 472 testcase( precision>0xfff ); |
| 473 for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} |
465 if( xtype==etFLOAT ) realvalue += rounder; | 474 if( xtype==etFLOAT ) realvalue += rounder; |
466 /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ | 475 /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ |
467 exp = 0; | 476 exp = 0; |
468 if( sqlite3IsNaN((double)realvalue) ){ | 477 if( sqlite3IsNaN((double)realvalue) ){ |
469 bufpt = "NaN"; | 478 bufpt = "NaN"; |
470 length = 3; | 479 length = 3; |
471 break; | 480 break; |
472 } | 481 } |
473 if( realvalue>0.0 ){ | 482 if( realvalue>0.0 ){ |
474 LONGDOUBLE_TYPE scale = 1.0; | 483 LONGDOUBLE_TYPE scale = 1.0; |
475 while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;} | 484 while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;} |
476 while( realvalue>=1e64*scale && exp<=350 ){ scale *= 1e64; exp+=64; } | 485 while( realvalue>=1e10*scale && exp<=350 ){ scale *= 1e10; exp+=10; } |
477 while( realvalue>=1e8*scale && exp<=350 ){ scale *= 1e8; exp+=8; } | |
478 while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } | 486 while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } |
479 realvalue /= scale; | 487 realvalue /= scale; |
480 while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } | 488 while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } |
481 while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } | 489 while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } |
482 if( exp>350 ){ | 490 if( exp>350 ){ |
483 if( prefix=='-' ){ | 491 bufpt = buf; |
484 bufpt = "-Inf"; | 492 buf[0] = prefix; |
485 }else if( prefix=='+' ){ | 493 memcpy(buf+(prefix!=0),"Inf",4); |
486 bufpt = "+Inf"; | 494 length = 3+(prefix!=0); |
487 }else{ | |
488 bufpt = "Inf"; | |
489 } | |
490 length = sqlite3Strlen30(bufpt); | |
491 break; | 495 break; |
492 } | 496 } |
493 } | 497 } |
494 bufpt = buf; | 498 bufpt = buf; |
495 /* | 499 /* |
496 ** If the field type is etGENERIC, then convert to either etEXP | 500 ** If the field type is etGENERIC, then convert to either etEXP |
497 ** or etFLOAT, as appropriate. | 501 ** or etFLOAT, as appropriate. |
498 */ | 502 */ |
499 if( xtype!=etFLOAT ){ | 503 if( xtype!=etFLOAT ){ |
500 realvalue += rounder; | 504 realvalue += rounder; |
501 if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } | 505 if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } |
502 } | 506 } |
503 if( xtype==etGENERIC ){ | 507 if( xtype==etGENERIC ){ |
504 flag_rtz = !flag_alternateform; | 508 flag_rtz = !flag_alternateform; |
505 if( exp<-4 || exp>precision ){ | 509 if( exp<-4 || exp>precision ){ |
506 xtype = etEXP; | 510 xtype = etEXP; |
507 }else{ | 511 }else{ |
508 precision = precision - exp; | 512 precision = precision - exp; |
509 xtype = etFLOAT; | 513 xtype = etFLOAT; |
510 } | 514 } |
511 }else{ | 515 }else{ |
512 flag_rtz = flag_altform2; | 516 flag_rtz = flag_altform2; |
513 } | 517 } |
514 if( xtype==etEXP ){ | 518 if( xtype==etEXP ){ |
515 e2 = 0; | 519 e2 = 0; |
516 }else{ | 520 }else{ |
517 e2 = exp; | 521 e2 = exp; |
518 } | 522 } |
519 if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){ | 523 if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){ |
520 bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 ); | 524 bufpt = zExtra |
| 525 = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); |
521 if( bufpt==0 ){ | 526 if( bufpt==0 ){ |
522 setStrAccumError(pAccum, STRACCUM_NOMEM); | 527 setStrAccumError(pAccum, STRACCUM_NOMEM); |
523 return; | 528 return; |
524 } | 529 } |
525 } | 530 } |
526 zOut = bufpt; | 531 zOut = bufpt; |
527 nsd = 16 + flag_altform2*10; | 532 nsd = 16 + flag_altform2*10; |
528 flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; | 533 flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; |
529 /* The sign in front of the number */ | 534 /* The sign in front of the number */ |
530 if( prefix ){ | 535 if( prefix ){ |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 sqlite3AppendChar(pAccum, precision-1, c); | 633 sqlite3AppendChar(pAccum, precision-1, c); |
629 } | 634 } |
630 length = 1; | 635 length = 1; |
631 buf[0] = c; | 636 buf[0] = c; |
632 bufpt = buf; | 637 bufpt = buf; |
633 break; | 638 break; |
634 case etSTRING: | 639 case etSTRING: |
635 case etDYNSTRING: | 640 case etDYNSTRING: |
636 if( bArgList ){ | 641 if( bArgList ){ |
637 bufpt = getTextArg(pArgList); | 642 bufpt = getTextArg(pArgList); |
| 643 xtype = etSTRING; |
638 }else{ | 644 }else{ |
639 bufpt = va_arg(ap,char*); | 645 bufpt = va_arg(ap,char*); |
640 } | 646 } |
641 if( bufpt==0 ){ | 647 if( bufpt==0 ){ |
642 bufpt = ""; | 648 bufpt = ""; |
643 }else if( xtype==etDYNSTRING && !bArgList ){ | 649 }else if( xtype==etDYNSTRING ){ |
644 zExtra = bufpt; | 650 zExtra = bufpt; |
645 } | 651 } |
646 if( precision>=0 ){ | 652 if( precision>=0 ){ |
647 for(length=0; length<precision && bufpt[length]; length++){} | 653 for(length=0; length<precision && bufpt[length]; length++){} |
648 }else{ | 654 }else{ |
649 length = sqlite3Strlen30(bufpt); | 655 length = sqlite3Strlen30(bufpt); |
650 } | 656 } |
651 break; | 657 break; |
652 case etSQLESCAPE: | 658 case etSQLESCAPE: /* Escape ' characters */ |
653 case etSQLESCAPE2: | 659 case etSQLESCAPE2: /* Escape ' and enclose in '...' */ |
654 case etSQLESCAPE3: { | 660 case etSQLESCAPE3: { /* Escape " characters */ |
655 int i, j, k, n, isnull; | 661 int i, j, k, n, isnull; |
656 int needQuote; | 662 int needQuote; |
657 char ch; | 663 char ch; |
658 char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ | 664 char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ |
659 char *escarg; | 665 char *escarg; |
660 | 666 |
661 if( bArgList ){ | 667 if( bArgList ){ |
662 escarg = getTextArg(pArgList); | 668 escarg = getTextArg(pArgList); |
663 }else{ | 669 }else{ |
664 escarg = va_arg(ap,char*); | 670 escarg = va_arg(ap,char*); |
665 } | 671 } |
666 isnull = escarg==0; | 672 isnull = escarg==0; |
667 if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); | 673 if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); |
668 k = precision; | 674 k = precision; |
669 for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){ | 675 for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){ |
670 if( ch==q ) n++; | 676 if( ch==q ) n++; |
671 } | 677 } |
672 needQuote = !isnull && xtype==etSQLESCAPE2; | 678 needQuote = !isnull && xtype==etSQLESCAPE2; |
673 n += i + 1 + needQuote*2; | 679 n += i + 3; |
674 if( n>etBUFSIZE ){ | 680 if( n>etBUFSIZE ){ |
675 bufpt = zExtra = sqlite3Malloc( n ); | 681 bufpt = zExtra = sqlite3Malloc( n ); |
676 if( bufpt==0 ){ | 682 if( bufpt==0 ){ |
677 setStrAccumError(pAccum, STRACCUM_NOMEM); | 683 setStrAccumError(pAccum, STRACCUM_NOMEM); |
678 return; | 684 return; |
679 } | 685 } |
680 }else{ | 686 }else{ |
681 bufpt = buf; | 687 bufpt = buf; |
682 } | 688 } |
683 j = 0; | 689 j = 0; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 ** The text of the conversion is pointed to by "bufpt" and is | 733 ** The text of the conversion is pointed to by "bufpt" and is |
728 ** "length" characters long. The field width is "width". Do | 734 ** "length" characters long. The field width is "width". Do |
729 ** the output. | 735 ** the output. |
730 */ | 736 */ |
731 width -= length; | 737 width -= length; |
732 if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); | 738 if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); |
733 sqlite3StrAccumAppend(pAccum, bufpt, length); | 739 sqlite3StrAccumAppend(pAccum, bufpt, length); |
734 if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); | 740 if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); |
735 | 741 |
736 if( zExtra ){ | 742 if( zExtra ){ |
737 sqlite3_free(zExtra); | 743 sqlite3DbFree(pAccum->db, zExtra); |
738 zExtra = 0; | 744 zExtra = 0; |
739 } | 745 } |
740 }/* End for loop over the format string */ | 746 }/* End for loop over the format string */ |
741 } /* End of function */ | 747 } /* End of function */ |
742 | 748 |
743 /* | 749 /* |
744 ** Enlarge the memory allocation on a StrAccum object so that it is | 750 ** Enlarge the memory allocation on a StrAccum object so that it is |
745 ** able to accept at least N more bytes of text. | 751 ** able to accept at least N more bytes of text. |
746 ** | 752 ** |
747 ** Return the number of bytes of text that StrAccum is able to accept | 753 ** Return the number of bytes of text that StrAccum is able to accept |
748 ** after the attempted enlargement. The value returned might be zero. | 754 ** after the attempted enlargement. The value returned might be zero. |
749 */ | 755 */ |
750 static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ | 756 static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ |
751 char *zNew; | 757 char *zNew; |
752 assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */ | 758 assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ |
753 if( p->accError ){ | 759 if( p->accError ){ |
754 testcase(p->accError==STRACCUM_TOOBIG); | 760 testcase(p->accError==STRACCUM_TOOBIG); |
755 testcase(p->accError==STRACCUM_NOMEM); | 761 testcase(p->accError==STRACCUM_NOMEM); |
756 return 0; | 762 return 0; |
757 } | 763 } |
758 if( !p->useMalloc ){ | 764 if( p->mxAlloc==0 ){ |
759 N = p->nAlloc - p->nChar - 1; | 765 N = p->nAlloc - p->nChar - 1; |
760 setStrAccumError(p, STRACCUM_TOOBIG); | 766 setStrAccumError(p, STRACCUM_TOOBIG); |
761 return N; | 767 return N; |
762 }else{ | 768 }else{ |
763 char *zOld = (p->zText==p->zBase ? 0 : p->zText); | 769 char *zOld = p->bMalloced ? p->zText : 0; |
764 i64 szNew = p->nChar; | 770 i64 szNew = p->nChar; |
| 771 assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
765 szNew += N + 1; | 772 szNew += N + 1; |
| 773 if( szNew+p->nChar<=p->mxAlloc ){ |
| 774 /* Force exponential buffer size growth as long as it does not overflow, |
| 775 ** to avoid having to call this routine too often */ |
| 776 szNew += p->nChar; |
| 777 } |
766 if( szNew > p->mxAlloc ){ | 778 if( szNew > p->mxAlloc ){ |
767 sqlite3StrAccumReset(p); | 779 sqlite3StrAccumReset(p); |
768 setStrAccumError(p, STRACCUM_TOOBIG); | 780 setStrAccumError(p, STRACCUM_TOOBIG); |
769 return 0; | 781 return 0; |
770 }else{ | 782 }else{ |
771 p->nAlloc = (int)szNew; | 783 p->nAlloc = (int)szNew; |
772 } | 784 } |
773 if( p->useMalloc==1 ){ | 785 if( p->db ){ |
774 zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); | 786 zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); |
775 }else{ | 787 }else{ |
776 zNew = sqlite3_realloc(zOld, p->nAlloc); | 788 zNew = sqlite3_realloc64(zOld, p->nAlloc); |
777 } | 789 } |
778 if( zNew ){ | 790 if( zNew ){ |
779 assert( p->zText!=0 || p->nChar==0 ); | 791 assert( p->zText!=0 || p->nChar==0 ); |
780 if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); | 792 if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); |
781 p->zText = zNew; | 793 p->zText = zNew; |
| 794 p->nAlloc = sqlite3DbMallocSize(p->db, zNew); |
| 795 p->bMalloced = 1; |
782 }else{ | 796 }else{ |
783 sqlite3StrAccumReset(p); | 797 sqlite3StrAccumReset(p); |
784 setStrAccumError(p, STRACCUM_NOMEM); | 798 setStrAccumError(p, STRACCUM_NOMEM); |
785 return 0; | 799 return 0; |
786 } | 800 } |
787 } | 801 } |
788 return N; | 802 return N; |
789 } | 803 } |
790 | 804 |
791 /* | 805 /* |
792 ** Append N copies of character c to the given string buffer. | 806 ** Append N copies of character c to the given string buffer. |
793 */ | 807 */ |
794 void sqlite3AppendChar(StrAccum *p, int N, char c){ | 808 void sqlite3AppendChar(StrAccum *p, int N, char c){ |
795 if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return; | 809 testcase( p->nChar + (i64)N > 0x7fffffff ); |
| 810 if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ |
| 811 return; |
| 812 } |
| 813 assert( (p->zText==p->zBase)==(p->bMalloced==0) ); |
796 while( (N--)>0 ) p->zText[p->nChar++] = c; | 814 while( (N--)>0 ) p->zText[p->nChar++] = c; |
797 } | 815 } |
798 | 816 |
799 /* | 817 /* |
800 ** The StrAccum "p" is not large enough to accept N new bytes of z[]. | 818 ** The StrAccum "p" is not large enough to accept N new bytes of z[]. |
801 ** So enlarge if first, then do the append. | 819 ** So enlarge if first, then do the append. |
802 ** | 820 ** |
803 ** This is a helper routine to sqlite3StrAccumAppend() that does special-case | 821 ** This is a helper routine to sqlite3StrAccumAppend() that does special-case |
804 ** work (enlarging the buffer) using tail recursion, so that the | 822 ** work (enlarging the buffer) using tail recursion, so that the |
805 ** sqlite3StrAccumAppend() routine can use fast calling semantics. | 823 ** sqlite3StrAccumAppend() routine can use fast calling semantics. |
806 */ | 824 */ |
807 static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ | 825 static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ |
808 N = sqlite3StrAccumEnlarge(p, N); | 826 N = sqlite3StrAccumEnlarge(p, N); |
809 if( N>0 ){ | 827 if( N>0 ){ |
810 memcpy(&p->zText[p->nChar], z, N); | 828 memcpy(&p->zText[p->nChar], z, N); |
811 p->nChar += N; | 829 p->nChar += N; |
812 } | 830 } |
| 831 assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
813 } | 832 } |
814 | 833 |
815 /* | 834 /* |
816 ** Append N bytes of text from z to the StrAccum object. Increase the | 835 ** Append N bytes of text from z to the StrAccum object. Increase the |
817 ** size of the memory allocation for StrAccum if necessary. | 836 ** size of the memory allocation for StrAccum if necessary. |
818 */ | 837 */ |
819 void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ | 838 void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ |
820 assert( z!=0 ); | 839 assert( z!=0 || N==0 ); |
821 assert( p->zText!=0 || p->nChar==0 || p->accError ); | 840 assert( p->zText!=0 || p->nChar==0 || p->accError ); |
822 assert( N>=0 ); | 841 assert( N>=0 ); |
823 assert( p->accError==0 || p->nAlloc==0 ); | 842 assert( p->accError==0 || p->nAlloc==0 ); |
824 if( p->nChar+N >= p->nAlloc ){ | 843 if( p->nChar+N >= p->nAlloc ){ |
825 enlargeAndAppend(p,z,N); | 844 enlargeAndAppend(p,z,N); |
826 }else{ | 845 }else{ |
827 assert( p->zText ); | 846 assert( p->zText ); |
828 p->nChar += N; | 847 p->nChar += N; |
829 memcpy(&p->zText[p->nChar-N], z, N); | 848 memcpy(&p->zText[p->nChar-N], z, N); |
830 } | 849 } |
831 } | 850 } |
832 | 851 |
833 /* | 852 /* |
834 ** Append the complete text of zero-terminated string z[] to the p string. | 853 ** Append the complete text of zero-terminated string z[] to the p string. |
835 */ | 854 */ |
836 void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ | 855 void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ |
837 sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); | 856 sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); |
838 } | 857 } |
839 | 858 |
840 | 859 |
841 /* | 860 /* |
842 ** Finish off a string by making sure it is zero-terminated. | 861 ** Finish off a string by making sure it is zero-terminated. |
843 ** Return a pointer to the resulting string. Return a NULL | 862 ** Return a pointer to the resulting string. Return a NULL |
844 ** pointer if any kind of error was encountered. | 863 ** pointer if any kind of error was encountered. |
845 */ | 864 */ |
846 char *sqlite3StrAccumFinish(StrAccum *p){ | 865 char *sqlite3StrAccumFinish(StrAccum *p){ |
847 if( p->zText ){ | 866 if( p->zText ){ |
| 867 assert( (p->zText==p->zBase)==(p->bMalloced==0) ); |
848 p->zText[p->nChar] = 0; | 868 p->zText[p->nChar] = 0; |
849 if( p->useMalloc && p->zText==p->zBase ){ | 869 if( p->mxAlloc>0 && p->bMalloced==0 ){ |
850 if( p->useMalloc==1 ){ | 870 p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); |
851 p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); | |
852 }else{ | |
853 p->zText = sqlite3_malloc(p->nChar+1); | |
854 } | |
855 if( p->zText ){ | 871 if( p->zText ){ |
856 memcpy(p->zText, p->zBase, p->nChar+1); | 872 memcpy(p->zText, p->zBase, p->nChar+1); |
| 873 p->bMalloced = 1; |
857 }else{ | 874 }else{ |
858 setStrAccumError(p, STRACCUM_NOMEM); | 875 setStrAccumError(p, STRACCUM_NOMEM); |
859 } | 876 } |
860 } | 877 } |
861 } | 878 } |
862 return p->zText; | 879 return p->zText; |
863 } | 880 } |
864 | 881 |
865 /* | 882 /* |
866 ** Reset an StrAccum string. Reclaim all malloced memory. | 883 ** Reset an StrAccum string. Reclaim all malloced memory. |
867 */ | 884 */ |
868 void sqlite3StrAccumReset(StrAccum *p){ | 885 void sqlite3StrAccumReset(StrAccum *p){ |
869 if( p->zText!=p->zBase ){ | 886 assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); |
870 if( p->useMalloc==1 ){ | 887 if( p->bMalloced ){ |
871 sqlite3DbFree(p->db, p->zText); | 888 sqlite3DbFree(p->db, p->zText); |
872 }else{ | 889 p->bMalloced = 0; |
873 sqlite3_free(p->zText); | |
874 } | |
875 } | 890 } |
876 p->zText = 0; | 891 p->zText = 0; |
877 } | 892 } |
878 | 893 |
879 /* | 894 /* |
880 ** Initialize a string accumulator | 895 ** Initialize a string accumulator. |
| 896 ** |
| 897 ** p: The accumulator to be initialized. |
| 898 ** db: Pointer to a database connection. May be NULL. Lookaside |
| 899 ** memory is used if not NULL. db->mallocFailed is set appropriately |
| 900 ** when not NULL. |
| 901 ** zBase: An initial buffer. May be NULL in which case the initial buffer |
| 902 ** is malloced. |
| 903 ** n: Size of zBase in bytes. If total space requirements never exceed |
| 904 ** n then no memory allocations ever occur. |
| 905 ** mx: Maximum number of bytes to accumulate. If mx==0 then no memory |
| 906 ** allocations will ever occur. |
881 */ | 907 */ |
882 void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){ | 908 void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ |
883 p->zText = p->zBase = zBase; | 909 p->zText = p->zBase = zBase; |
884 p->db = 0; | 910 p->db = db; |
885 p->nChar = 0; | 911 p->nChar = 0; |
886 p->nAlloc = n; | 912 p->nAlloc = n; |
887 p->mxAlloc = mx; | 913 p->mxAlloc = mx; |
888 p->useMalloc = 1; | |
889 p->accError = 0; | 914 p->accError = 0; |
| 915 p->bMalloced = 0; |
890 } | 916 } |
891 | 917 |
892 /* | 918 /* |
893 ** Print into memory obtained from sqliteMalloc(). Use the internal | 919 ** Print into memory obtained from sqliteMalloc(). Use the internal |
894 ** %-conversion extensions. | 920 ** %-conversion extensions. |
895 */ | 921 */ |
896 char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ | 922 char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ |
897 char *z; | 923 char *z; |
898 char zBase[SQLITE_PRINT_BUF_SIZE]; | 924 char zBase[SQLITE_PRINT_BUF_SIZE]; |
899 StrAccum acc; | 925 StrAccum acc; |
900 assert( db!=0 ); | 926 assert( db!=0 ); |
901 sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), | 927 sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), |
902 db->aLimit[SQLITE_LIMIT_LENGTH]); | 928 db->aLimit[SQLITE_LIMIT_LENGTH]); |
903 acc.db = db; | |
904 sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); | 929 sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); |
905 z = sqlite3StrAccumFinish(&acc); | 930 z = sqlite3StrAccumFinish(&acc); |
906 if( acc.accError==STRACCUM_NOMEM ){ | 931 if( acc.accError==STRACCUM_NOMEM ){ |
907 db->mallocFailed = 1; | 932 db->mallocFailed = 1; |
908 } | 933 } |
909 return z; | 934 return z; |
910 } | 935 } |
911 | 936 |
912 /* | 937 /* |
913 ** Print into memory obtained from sqliteMalloc(). Use the internal | 938 ** Print into memory obtained from sqliteMalloc(). Use the internal |
914 ** %-conversion extensions. | 939 ** %-conversion extensions. |
915 */ | 940 */ |
916 char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ | 941 char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ |
917 va_list ap; | 942 va_list ap; |
918 char *z; | 943 char *z; |
919 va_start(ap, zFormat); | 944 va_start(ap, zFormat); |
920 z = sqlite3VMPrintf(db, zFormat, ap); | 945 z = sqlite3VMPrintf(db, zFormat, ap); |
921 va_end(ap); | 946 va_end(ap); |
922 return z; | 947 return z; |
923 } | 948 } |
924 | 949 |
925 /* | 950 /* |
926 ** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting | |
927 ** the string and before returning. This routine is intended to be used | |
928 ** to modify an existing string. For example: | |
929 ** | |
930 ** x = sqlite3MPrintf(db, x, "prefix %s suffix", x); | |
931 ** | |
932 */ | |
933 char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){ | |
934 va_list ap; | |
935 char *z; | |
936 va_start(ap, zFormat); | |
937 z = sqlite3VMPrintf(db, zFormat, ap); | |
938 va_end(ap); | |
939 sqlite3DbFree(db, zStr); | |
940 return z; | |
941 } | |
942 | |
943 /* | |
944 ** Print into memory obtained from sqlite3_malloc(). Omit the internal | 951 ** Print into memory obtained from sqlite3_malloc(). Omit the internal |
945 ** %-conversion extensions. | 952 ** %-conversion extensions. |
946 */ | 953 */ |
947 char *sqlite3_vmprintf(const char *zFormat, va_list ap){ | 954 char *sqlite3_vmprintf(const char *zFormat, va_list ap){ |
948 char *z; | 955 char *z; |
949 char zBase[SQLITE_PRINT_BUF_SIZE]; | 956 char zBase[SQLITE_PRINT_BUF_SIZE]; |
950 StrAccum acc; | 957 StrAccum acc; |
| 958 |
| 959 #ifdef SQLITE_ENABLE_API_ARMOR |
| 960 if( zFormat==0 ){ |
| 961 (void)SQLITE_MISUSE_BKPT; |
| 962 return 0; |
| 963 } |
| 964 #endif |
951 #ifndef SQLITE_OMIT_AUTOINIT | 965 #ifndef SQLITE_OMIT_AUTOINIT |
952 if( sqlite3_initialize() ) return 0; | 966 if( sqlite3_initialize() ) return 0; |
953 #endif | 967 #endif |
954 sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); | 968 sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); |
955 acc.useMalloc = 2; | |
956 sqlite3VXPrintf(&acc, 0, zFormat, ap); | 969 sqlite3VXPrintf(&acc, 0, zFormat, ap); |
957 z = sqlite3StrAccumFinish(&acc); | 970 z = sqlite3StrAccumFinish(&acc); |
958 return z; | 971 return z; |
959 } | 972 } |
960 | 973 |
961 /* | 974 /* |
962 ** Print into memory obtained from sqlite3_malloc()(). Omit the internal | 975 ** Print into memory obtained from sqlite3_malloc()(). Omit the internal |
963 ** %-conversion extensions. | 976 ** %-conversion extensions. |
964 */ | 977 */ |
965 char *sqlite3_mprintf(const char *zFormat, ...){ | 978 char *sqlite3_mprintf(const char *zFormat, ...){ |
(...skipping 17 matching lines...) Expand all Loading... |
983 ** Oops: The first two arguments of sqlite3_snprintf() are backwards | 996 ** Oops: The first two arguments of sqlite3_snprintf() are backwards |
984 ** from the snprintf() standard. Unfortunately, it is too late to change | 997 ** from the snprintf() standard. Unfortunately, it is too late to change |
985 ** this without breaking compatibility, so we just have to live with the | 998 ** this without breaking compatibility, so we just have to live with the |
986 ** mistake. | 999 ** mistake. |
987 ** | 1000 ** |
988 ** sqlite3_vsnprintf() is the varargs version. | 1001 ** sqlite3_vsnprintf() is the varargs version. |
989 */ | 1002 */ |
990 char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ | 1003 char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ |
991 StrAccum acc; | 1004 StrAccum acc; |
992 if( n<=0 ) return zBuf; | 1005 if( n<=0 ) return zBuf; |
993 sqlite3StrAccumInit(&acc, zBuf, n, 0); | 1006 #ifdef SQLITE_ENABLE_API_ARMOR |
994 acc.useMalloc = 0; | 1007 if( zBuf==0 || zFormat==0 ) { |
| 1008 (void)SQLITE_MISUSE_BKPT; |
| 1009 if( zBuf ) zBuf[0] = 0; |
| 1010 return zBuf; |
| 1011 } |
| 1012 #endif |
| 1013 sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); |
995 sqlite3VXPrintf(&acc, 0, zFormat, ap); | 1014 sqlite3VXPrintf(&acc, 0, zFormat, ap); |
996 return sqlite3StrAccumFinish(&acc); | 1015 return sqlite3StrAccumFinish(&acc); |
997 } | 1016 } |
998 char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ | 1017 char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
999 char *z; | 1018 char *z; |
1000 va_list ap; | 1019 va_list ap; |
1001 va_start(ap,zFormat); | 1020 va_start(ap,zFormat); |
1002 z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); | 1021 z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); |
1003 va_end(ap); | 1022 va_end(ap); |
1004 return z; | 1023 return z; |
1005 } | 1024 } |
1006 | 1025 |
1007 /* | 1026 /* |
1008 ** This is the routine that actually formats the sqlite3_log() message. | 1027 ** This is the routine that actually formats the sqlite3_log() message. |
1009 ** We house it in a separate routine from sqlite3_log() to avoid using | 1028 ** We house it in a separate routine from sqlite3_log() to avoid using |
1010 ** stack space on small-stack systems when logging is disabled. | 1029 ** stack space on small-stack systems when logging is disabled. |
1011 ** | 1030 ** |
1012 ** sqlite3_log() must render into a static buffer. It cannot dynamically | 1031 ** sqlite3_log() must render into a static buffer. It cannot dynamically |
1013 ** allocate memory because it might be called while the memory allocator | 1032 ** allocate memory because it might be called while the memory allocator |
1014 ** mutex is held. | 1033 ** mutex is held. |
| 1034 ** |
| 1035 ** sqlite3VXPrintf() might ask for *temporary* memory allocations for |
| 1036 ** certain format characters (%q) or for very large precisions or widths. |
| 1037 ** Care must be taken that any sqlite3_log() calls that occur while the |
| 1038 ** memory mutex is held do not use these mechanisms. |
1015 */ | 1039 */ |
1016 static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ | 1040 static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ |
1017 StrAccum acc; /* String accumulator */ | 1041 StrAccum acc; /* String accumulator */ |
1018 char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ | 1042 char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
1019 | 1043 |
1020 sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); | 1044 sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); |
1021 acc.useMalloc = 0; | |
1022 sqlite3VXPrintf(&acc, 0, zFormat, ap); | 1045 sqlite3VXPrintf(&acc, 0, zFormat, ap); |
1023 sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, | 1046 sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, |
1024 sqlite3StrAccumFinish(&acc)); | 1047 sqlite3StrAccumFinish(&acc)); |
1025 } | 1048 } |
1026 | 1049 |
1027 /* | 1050 /* |
1028 ** Format and write a message to the log if logging is enabled. | 1051 ** Format and write a message to the log if logging is enabled. |
1029 */ | 1052 */ |
1030 void sqlite3_log(int iErrCode, const char *zFormat, ...){ | 1053 void sqlite3_log(int iErrCode, const char *zFormat, ...){ |
1031 va_list ap; /* Vararg list */ | 1054 va_list ap; /* Vararg list */ |
1032 if( sqlite3GlobalConfig.xLog ){ | 1055 if( sqlite3GlobalConfig.xLog ){ |
1033 va_start(ap, zFormat); | 1056 va_start(ap, zFormat); |
1034 renderLogMsg(iErrCode, zFormat, ap); | 1057 renderLogMsg(iErrCode, zFormat, ap); |
1035 va_end(ap); | 1058 va_end(ap); |
1036 } | 1059 } |
1037 } | 1060 } |
1038 | 1061 |
1039 #if defined(SQLITE_DEBUG) | 1062 #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
1040 /* | 1063 /* |
1041 ** A version of printf() that understands %lld. Used for debugging. | 1064 ** A version of printf() that understands %lld. Used for debugging. |
1042 ** The printf() built into some versions of windows does not understand %lld | 1065 ** The printf() built into some versions of windows does not understand %lld |
1043 ** and segfaults if you give it a long long int. | 1066 ** and segfaults if you give it a long long int. |
1044 */ | 1067 */ |
1045 void sqlite3DebugPrintf(const char *zFormat, ...){ | 1068 void sqlite3DebugPrintf(const char *zFormat, ...){ |
1046 va_list ap; | 1069 va_list ap; |
1047 StrAccum acc; | 1070 StrAccum acc; |
1048 char zBuf[500]; | 1071 char zBuf[500]; |
1049 sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); | 1072 sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); |
1050 acc.useMalloc = 0; | |
1051 va_start(ap,zFormat); | 1073 va_start(ap,zFormat); |
1052 sqlite3VXPrintf(&acc, 0, zFormat, ap); | 1074 sqlite3VXPrintf(&acc, 0, zFormat, ap); |
1053 va_end(ap); | 1075 va_end(ap); |
1054 sqlite3StrAccumFinish(&acc); | 1076 sqlite3StrAccumFinish(&acc); |
1055 fprintf(stdout,"%s", zBuf); | 1077 fprintf(stdout,"%s", zBuf); |
1056 fflush(stdout); | 1078 fflush(stdout); |
1057 } | 1079 } |
1058 #endif | 1080 #endif |
1059 | 1081 |
1060 #ifdef SQLITE_DEBUG | |
1061 /************************************************************************* | |
1062 ** Routines for implementing the "TreeView" display of hierarchical | |
1063 ** data structures for debugging. | |
1064 ** | |
1065 ** The main entry points (coded elsewhere) are: | |
1066 ** sqlite3TreeViewExpr(0, pExpr, 0); | |
1067 ** sqlite3TreeViewExprList(0, pList, 0, 0); | |
1068 ** sqlite3TreeViewSelect(0, pSelect, 0); | |
1069 ** Insert calls to those routines while debugging in order to display | |
1070 ** a diagram of Expr, ExprList, and Select objects. | |
1071 ** | |
1072 */ | |
1073 /* Add a new subitem to the tree. The moreToFollow flag indicates that this | |
1074 ** is not the last item in the tree. */ | |
1075 TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ | |
1076 if( p==0 ){ | |
1077 p = sqlite3_malloc( sizeof(*p) ); | |
1078 if( p==0 ) return 0; | |
1079 memset(p, 0, sizeof(*p)); | |
1080 }else{ | |
1081 p->iLevel++; | |
1082 } | |
1083 assert( moreToFollow==0 || moreToFollow==1 ); | |
1084 if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow; | |
1085 return p; | |
1086 } | |
1087 /* Finished with one layer of the tree */ | |
1088 void sqlite3TreeViewPop(TreeView *p){ | |
1089 if( p==0 ) return; | |
1090 p->iLevel--; | |
1091 if( p->iLevel<0 ) sqlite3_free(p); | |
1092 } | |
1093 /* Generate a single line of output for the tree, with a prefix that contains | |
1094 ** all the appropriate tree lines */ | |
1095 void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ | |
1096 va_list ap; | |
1097 int i; | |
1098 StrAccum acc; | |
1099 char zBuf[500]; | |
1100 sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); | |
1101 acc.useMalloc = 0; | |
1102 if( p ){ | |
1103 for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){ | |
1104 sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); | |
1105 } | |
1106 sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); | |
1107 } | |
1108 va_start(ap, zFormat); | |
1109 sqlite3VXPrintf(&acc, 0, zFormat, ap); | |
1110 va_end(ap); | |
1111 if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1); | |
1112 sqlite3StrAccumFinish(&acc); | |
1113 fprintf(stdout,"%s", zBuf); | |
1114 fflush(stdout); | |
1115 } | |
1116 /* Shorthand for starting a new tree item that consists of a single label */ | |
1117 void sqlite3TreeViewItem(TreeView *p, const char *zLabel, u8 moreToFollow){ | |
1118 p = sqlite3TreeViewPush(p, moreToFollow); | |
1119 sqlite3TreeViewLine(p, "%s", zLabel); | |
1120 } | |
1121 #endif /* SQLITE_DEBUG */ | |
1122 | 1082 |
1123 /* | 1083 /* |
1124 ** variable-argument wrapper around sqlite3VXPrintf(). | 1084 ** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument |
| 1085 ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. |
1125 */ | 1086 */ |
1126 void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ | 1087 void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ |
1127 va_list ap; | 1088 va_list ap; |
1128 va_start(ap,zFormat); | 1089 va_start(ap,zFormat); |
1129 sqlite3VXPrintf(p, bFlags, zFormat, ap); | 1090 sqlite3VXPrintf(p, bFlags, zFormat, ap); |
1130 va_end(ap); | 1091 va_end(ap); |
1131 } | 1092 } |
OLD | NEW |