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. | 3 ** the public domain. |
4 ** | 4 ** |
5 ************************************************************************** | 5 ************************************************************************** |
6 ** | 6 ** |
7 ** 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 |
8 ** routines format strings much like the printf() from the standard C | 8 ** routines format strings much like the printf() from the standard C |
9 ** library, though the implementation here has enhancements to support | 9 ** library, though the implementation here has enhancements to support |
10 ** SQLite. | 10 ** SQLite. |
11 */ | 11 */ |
12 #include "sqliteInt.h" | 12 #include "sqliteInt.h" |
13 | 13 |
14 /* | 14 /* |
15 ** Conversion types fall into various categories as defined by the | 15 ** Conversion types fall into various categories as defined by the |
16 ** following enumeration. | 16 ** following enumeration. |
17 */ | 17 */ |
18 #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ | 18 #define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */ |
19 #define etFLOAT 2 /* Floating point. %f */ | 19 #define etFLOAT 1 /* Floating point. %f */ |
20 #define etEXP 3 /* Exponentional notation. %e and %E */ | 20 #define etEXP 2 /* Exponentional notation. %e and %E */ |
21 #define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ | 21 #define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */ |
22 #define etSIZE 5 /* Return number of characters processed so far. %n */ | 22 #define etSIZE 4 /* Return number of characters processed so far. %n */ |
23 #define etSTRING 6 /* Strings. %s */ | 23 #define etSTRING 5 /* Strings. %s */ |
24 #define etDYNSTRING 7 /* Dynamically allocated strings. %z */ | 24 #define etDYNSTRING 6 /* Dynamically allocated strings. %z */ |
25 #define etPERCENT 8 /* Percent symbol. %% */ | 25 #define etPERCENT 7 /* Percent symbol. %% */ |
26 #define etCHARX 9 /* Characters. %c */ | 26 #define etCHARX 8 /* Characters. %c */ |
27 /* The rest are extensions, not normally found in printf() */ | 27 /* The rest are extensions, not normally found in printf() */ |
28 #define etSQLESCAPE 10 /* Strings with '\'' doubled. %q */ | 28 #define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */ |
29 #define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '', | 29 #define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '', |
30 NULL pointers replaced by SQL NULL. %Q */ | 30 NULL pointers replaced by SQL NULL. %Q */ |
31 #define etTOKEN 12 /* a pointer to a Token structure */ | 31 #define etTOKEN 11 /* a pointer to a Token structure */ |
32 #define etSRCLIST 13 /* a pointer to a SrcList */ | 32 #define etSRCLIST 12 /* a pointer to a SrcList */ |
33 #define etPOINTER 14 /* The %p conversion */ | 33 #define etPOINTER 13 /* The %p conversion */ |
34 #define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */ | 34 #define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */ |
35 #define etORDINAL 16 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ | 35 #define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ |
36 | 36 |
37 #define etINVALID 0 /* Any unrecognized conversion type */ | 37 #define etINVALID 16 /* Any unrecognized conversion type */ |
38 | 38 |
39 | 39 |
40 /* | 40 /* |
41 ** An "etByte" is an 8-bit unsigned value. | 41 ** An "etByte" is an 8-bit unsigned value. |
42 */ | 42 */ |
43 typedef unsigned char etByte; | 43 typedef unsigned char etByte; |
44 | 44 |
45 /* | 45 /* |
46 ** Each builtin conversion character (ex: the 'd' in "%d") is described | 46 ** Each builtin conversion character (ex: the 'd' in "%d") is described |
47 ** by an instance of the following structure | 47 ** by an instance of the following structure |
48 */ | 48 */ |
49 typedef struct et_info { /* Information about each format field */ | 49 typedef struct et_info { /* Information about each format field */ |
50 char fmttype; /* The format field code letter */ | 50 char fmttype; /* The format field code letter */ |
51 etByte base; /* The base for radix conversion */ | 51 etByte base; /* The base for radix conversion */ |
52 etByte flags; /* One or more of FLAG_ constants below */ | 52 etByte flags; /* One or more of FLAG_ constants below */ |
53 etByte type; /* Conversion paradigm */ | 53 etByte type; /* Conversion paradigm */ |
54 etByte charset; /* Offset into aDigits[] of the digits string */ | 54 etByte charset; /* Offset into aDigits[] of the digits string */ |
55 etByte prefix; /* Offset into aPrefix[] of the prefix string */ | 55 etByte prefix; /* Offset into aPrefix[] of the prefix string */ |
56 } et_info; | 56 } et_info; |
57 | 57 |
58 /* | 58 /* |
59 ** Allowed values for et_info.flags | 59 ** Allowed values for et_info.flags |
60 */ | 60 */ |
61 #define FLAG_SIGNED 1 /* True if the value to convert is signed */ | 61 #define FLAG_SIGNED 1 /* True if the value to convert is signed */ |
62 #define FLAG_INTERN 2 /* True if for internal use only */ | |
63 #define FLAG_STRING 4 /* Allow infinity precision */ | 62 #define FLAG_STRING 4 /* Allow infinity precision */ |
64 | 63 |
65 | 64 |
66 /* | 65 /* |
67 ** The following table is searched linearly, so it is good to put the | 66 ** The following table is searched linearly, so it is good to put the |
68 ** most frequently used conversion types first. | 67 ** most frequently used conversion types first. |
69 */ | 68 */ |
70 static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; | 69 static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; |
71 static const char aPrefix[] = "-x0\000X0"; | 70 static const char aPrefix[] = "-x0\000X0"; |
72 static const et_info fmtinfo[] = { | 71 static const et_info fmtinfo[] = { |
(...skipping 13 matching lines...) Expand all Loading... |
86 { 'f', 0, 1, etFLOAT, 0, 0 }, | 85 { 'f', 0, 1, etFLOAT, 0, 0 }, |
87 { 'e', 0, 1, etEXP, 30, 0 }, | 86 { 'e', 0, 1, etEXP, 30, 0 }, |
88 { 'E', 0, 1, etEXP, 14, 0 }, | 87 { 'E', 0, 1, etEXP, 14, 0 }, |
89 { 'G', 0, 1, etGENERIC, 14, 0 }, | 88 { 'G', 0, 1, etGENERIC, 14, 0 }, |
90 #endif | 89 #endif |
91 { 'i', 10, 1, etRADIX, 0, 0 }, | 90 { 'i', 10, 1, etRADIX, 0, 0 }, |
92 { 'n', 0, 0, etSIZE, 0, 0 }, | 91 { 'n', 0, 0, etSIZE, 0, 0 }, |
93 { '%', 0, 0, etPERCENT, 0, 0 }, | 92 { '%', 0, 0, etPERCENT, 0, 0 }, |
94 { 'p', 16, 0, etPOINTER, 0, 1 }, | 93 { 'p', 16, 0, etPOINTER, 0, 1 }, |
95 | 94 |
96 /* All the rest have the FLAG_INTERN bit set and are thus for internal | 95 /* All the rest are undocumented and are for internal use only */ |
97 ** use only */ | 96 { 'T', 0, 0, etTOKEN, 0, 0 }, |
98 { 'T', 0, 2, etTOKEN, 0, 0 }, | 97 { 'S', 0, 0, etSRCLIST, 0, 0 }, |
99 { 'S', 0, 2, etSRCLIST, 0, 0 }, | 98 { 'r', 10, 1, etORDINAL, 0, 0 }, |
100 { 'r', 10, 3, etORDINAL, 0, 0 }, | |
101 }; | 99 }; |
102 | 100 |
103 /* | 101 /* |
104 ** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point | 102 ** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point |
105 ** conversions will work. | 103 ** conversions will work. |
106 */ | 104 */ |
107 #ifndef SQLITE_OMIT_FLOATING_POINT | 105 #ifndef SQLITE_OMIT_FLOATING_POINT |
108 /* | 106 /* |
109 ** "*val" is a double such that 0.1 <= *val < 10.0 | 107 ** "*val" is a double such that 0.1 <= *val < 10.0 |
110 ** Return the ascii code for the leading digit of *val, then | 108 ** Return the ascii code for the leading digit of *val, then |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 #ifndef SQLITE_PRINT_BUF_SIZE | 162 #ifndef SQLITE_PRINT_BUF_SIZE |
165 # define SQLITE_PRINT_BUF_SIZE 70 | 163 # define SQLITE_PRINT_BUF_SIZE 70 |
166 #endif | 164 #endif |
167 #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ | 165 #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ |
168 | 166 |
169 /* | 167 /* |
170 ** Render a string given by "fmt" into the StrAccum object. | 168 ** Render a string given by "fmt" into the StrAccum object. |
171 */ | 169 */ |
172 void sqlite3VXPrintf( | 170 void sqlite3VXPrintf( |
173 StrAccum *pAccum, /* Accumulate results here */ | 171 StrAccum *pAccum, /* Accumulate results here */ |
174 u32 bFlags, /* SQLITE_PRINTF_* flags */ | |
175 const char *fmt, /* Format string */ | 172 const char *fmt, /* Format string */ |
176 va_list ap /* arguments */ | 173 va_list ap /* arguments */ |
177 ){ | 174 ){ |
178 int c; /* Next character in the format string */ | 175 int c; /* Next character in the format string */ |
179 char *bufpt; /* Pointer to the conversion buffer */ | 176 char *bufpt; /* Pointer to the conversion buffer */ |
180 int precision; /* Precision of the current field */ | 177 int precision; /* Precision of the current field */ |
181 int length; /* Length of the field */ | 178 int length; /* Length of the field */ |
182 int idx; /* A general purpose loop counter */ | 179 int idx; /* A general purpose loop counter */ |
183 int width; /* Width of the current field */ | 180 int width; /* Width of the current field */ |
184 etByte flag_leftjustify; /* True if "-" flag is present */ | 181 etByte flag_leftjustify; /* True if "-" flag is present */ |
185 etByte flag_plussign; /* True if "+" flag is present */ | 182 etByte flag_plussign; /* True if "+" flag is present */ |
186 etByte flag_blanksign; /* True if " " flag is present */ | 183 etByte flag_blanksign; /* True if " " flag is present */ |
187 etByte flag_alternateform; /* True if "#" flag is present */ | 184 etByte flag_alternateform; /* True if "#" flag is present */ |
188 etByte flag_altform2; /* True if "!" flag is present */ | 185 etByte flag_altform2; /* True if "!" flag is present */ |
189 etByte flag_zeropad; /* True if field width constant starts with zero */ | 186 etByte flag_zeropad; /* True if field width constant starts with zero */ |
190 etByte flag_long; /* True if "l" flag is present */ | 187 etByte flag_long; /* True if "l" flag is present */ |
191 etByte flag_longlong; /* True if the "ll" flag is present */ | 188 etByte flag_longlong; /* True if the "ll" flag is present */ |
192 etByte done; /* Loop termination flag */ | 189 etByte done; /* Loop termination flag */ |
193 etByte xtype = 0; /* Conversion paradigm */ | 190 etByte xtype = etINVALID; /* Conversion paradigm */ |
194 u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ | 191 u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ |
195 u8 useIntern; /* Ok to use internal conversions (ex: %T) */ | |
196 char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ | 192 char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ |
197 sqlite_uint64 longvalue; /* Value for integer types */ | 193 sqlite_uint64 longvalue; /* Value for integer types */ |
198 LONGDOUBLE_TYPE realvalue; /* Value for real types */ | 194 LONGDOUBLE_TYPE realvalue; /* Value for real types */ |
199 const et_info *infop; /* Pointer to the appropriate info structure */ | 195 const et_info *infop; /* Pointer to the appropriate info structure */ |
200 char *zOut; /* Rendering buffer */ | 196 char *zOut; /* Rendering buffer */ |
201 int nOut; /* Size of the rendering buffer */ | 197 int nOut; /* Size of the rendering buffer */ |
202 char *zExtra = 0; /* Malloced memory used by some conversion */ | 198 char *zExtra = 0; /* Malloced memory used by some conversion */ |
203 #ifndef SQLITE_OMIT_FLOATING_POINT | 199 #ifndef SQLITE_OMIT_FLOATING_POINT |
204 int exp, e2; /* exponent of real numbers */ | 200 int exp, e2; /* exponent of real numbers */ |
205 int nsd; /* Number of significant digits returned */ | 201 int nsd; /* Number of significant digits returned */ |
206 double rounder; /* Used for rounding floating point values */ | 202 double rounder; /* Used for rounding floating point values */ |
207 etByte flag_dp; /* True if decimal point should be shown */ | 203 etByte flag_dp; /* True if decimal point should be shown */ |
208 etByte flag_rtz; /* True if trailing zeros should be removed */ | 204 etByte flag_rtz; /* True if trailing zeros should be removed */ |
209 #endif | 205 #endif |
210 PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ | 206 PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ |
211 char buf[etBUFSIZE]; /* Conversion buffer */ | 207 char buf[etBUFSIZE]; /* Conversion buffer */ |
212 | 208 |
213 bufpt = 0; | 209 bufpt = 0; |
214 if( bFlags ){ | 210 if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){ |
215 if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ | 211 pArgList = va_arg(ap, PrintfArguments*); |
216 pArgList = va_arg(ap, PrintfArguments*); | 212 bArgList = 1; |
217 } | |
218 useIntern = bFlags & SQLITE_PRINTF_INTERNAL; | |
219 }else{ | 213 }else{ |
220 bArgList = useIntern = 0; | 214 bArgList = 0; |
221 } | 215 } |
222 for(; (c=(*fmt))!=0; ++fmt){ | 216 for(; (c=(*fmt))!=0; ++fmt){ |
223 if( c!='%' ){ | 217 if( c!='%' ){ |
224 bufpt = (char *)fmt; | 218 bufpt = (char *)fmt; |
225 #if HAVE_STRCHRNUL | 219 #if HAVE_STRCHRNUL |
226 fmt = strchrnul(fmt, '%'); | 220 fmt = strchrnul(fmt, '%'); |
227 #else | 221 #else |
228 do{ fmt++; }while( *fmt && *fmt != '%' ); | 222 do{ fmt++; }while( *fmt && *fmt != '%' ); |
229 #endif | 223 #endif |
230 sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt)); | 224 sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt)); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 } | 316 } |
323 }else{ | 317 }else{ |
324 flag_long = flag_longlong = 0; | 318 flag_long = flag_longlong = 0; |
325 } | 319 } |
326 /* Fetch the info entry for the field */ | 320 /* Fetch the info entry for the field */ |
327 infop = &fmtinfo[0]; | 321 infop = &fmtinfo[0]; |
328 xtype = etINVALID; | 322 xtype = etINVALID; |
329 for(idx=0; idx<ArraySize(fmtinfo); idx++){ | 323 for(idx=0; idx<ArraySize(fmtinfo); idx++){ |
330 if( c==fmtinfo[idx].fmttype ){ | 324 if( c==fmtinfo[idx].fmttype ){ |
331 infop = &fmtinfo[idx]; | 325 infop = &fmtinfo[idx]; |
332 if( useIntern || (infop->flags & FLAG_INTERN)==0 ){ | 326 xtype = infop->type; |
333 xtype = infop->type; | |
334 }else{ | |
335 return; | |
336 } | |
337 break; | 327 break; |
338 } | 328 } |
339 } | 329 } |
340 | 330 |
341 /* | 331 /* |
342 ** At this point, variables are initialized as follows: | 332 ** At this point, variables are initialized as follows: |
343 ** | 333 ** |
344 ** flag_alternateform TRUE if a '#' is present. | 334 ** flag_alternateform TRUE if a '#' is present. |
345 ** flag_altform2 TRUE if a '!' is present. | 335 ** flag_altform2 TRUE if a '!' is present. |
346 ** flag_plussign TRUE if a '+' is present. | 336 ** flag_plussign TRUE if a '+' is present. |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 } | 685 } |
696 if( needQuote ) bufpt[j++] = q; | 686 if( needQuote ) bufpt[j++] = q; |
697 bufpt[j] = 0; | 687 bufpt[j] = 0; |
698 length = j; | 688 length = j; |
699 /* The precision in %q and %Q means how many input characters to | 689 /* The precision in %q and %Q means how many input characters to |
700 ** consume, not the length of the output... | 690 ** consume, not the length of the output... |
701 ** if( precision>=0 && precision<length ) length = precision; */ | 691 ** if( precision>=0 && precision<length ) length = precision; */ |
702 break; | 692 break; |
703 } | 693 } |
704 case etTOKEN: { | 694 case etTOKEN: { |
705 Token *pToken = va_arg(ap, Token*); | 695 Token *pToken; |
| 696 if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; |
| 697 pToken = va_arg(ap, Token*); |
706 assert( bArgList==0 ); | 698 assert( bArgList==0 ); |
707 if( pToken && pToken->n ){ | 699 if( pToken && pToken->n ){ |
708 sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); | 700 sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); |
709 } | 701 } |
710 length = width = 0; | 702 length = width = 0; |
711 break; | 703 break; |
712 } | 704 } |
713 case etSRCLIST: { | 705 case etSRCLIST: { |
714 SrcList *pSrc = va_arg(ap, SrcList*); | 706 SrcList *pSrc; |
715 int k = va_arg(ap, int); | 707 int k; |
716 struct SrcList_item *pItem = &pSrc->a[k]; | 708 struct SrcList_item *pItem; |
| 709 if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; |
| 710 pSrc = va_arg(ap, SrcList*); |
| 711 k = va_arg(ap, int); |
| 712 pItem = &pSrc->a[k]; |
717 assert( bArgList==0 ); | 713 assert( bArgList==0 ); |
718 assert( k>=0 && k<pSrc->nSrc ); | 714 assert( k>=0 && k<pSrc->nSrc ); |
719 if( pItem->zDatabase ){ | 715 if( pItem->zDatabase ){ |
720 sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); | 716 sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase); |
721 sqlite3StrAccumAppend(pAccum, ".", 1); | 717 sqlite3StrAccumAppend(pAccum, ".", 1); |
722 } | 718 } |
723 sqlite3StrAccumAppendAll(pAccum, pItem->zName); | 719 sqlite3StrAccumAppendAll(pAccum, pItem->zName); |
724 length = width = 0; | 720 length = width = 0; |
725 break; | 721 break; |
726 } | 722 } |
727 default: { | 723 default: { |
728 assert( xtype==etINVALID ); | 724 assert( xtype==etINVALID ); |
729 return; | 725 return; |
730 } | 726 } |
731 }/* End switch over the format type */ | 727 }/* End switch over the format type */ |
732 /* | 728 /* |
733 ** The text of the conversion is pointed to by "bufpt" and is | 729 ** The text of the conversion is pointed to by "bufpt" and is |
734 ** "length" characters long. The field width is "width". Do | 730 ** "length" characters long. The field width is "width". Do |
735 ** the output. | 731 ** the output. |
736 */ | 732 */ |
737 width -= length; | 733 width -= length; |
738 if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); | 734 if( width>0 ){ |
739 sqlite3StrAccumAppend(pAccum, bufpt, length); | 735 if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); |
740 if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); | 736 sqlite3StrAccumAppend(pAccum, bufpt, length); |
| 737 if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' '); |
| 738 }else{ |
| 739 sqlite3StrAccumAppend(pAccum, bufpt, length); |
| 740 } |
741 | 741 |
742 if( zExtra ){ | 742 if( zExtra ){ |
743 sqlite3DbFree(pAccum->db, zExtra); | 743 sqlite3DbFree(pAccum->db, zExtra); |
744 zExtra = 0; | 744 zExtra = 0; |
745 } | 745 } |
746 }/* End for loop over the format string */ | 746 }/* End for loop over the format string */ |
747 } /* End of function */ | 747 } /* End of function */ |
748 | 748 |
749 /* | 749 /* |
750 ** 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 |
751 ** able to accept at least N more bytes of text. | 751 ** able to accept at least N more bytes of text. |
752 ** | 752 ** |
753 ** 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 |
754 ** after the attempted enlargement. The value returned might be zero. | 754 ** after the attempted enlargement. The value returned might be zero. |
755 */ | 755 */ |
756 static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ | 756 static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ |
757 char *zNew; | 757 char *zNew; |
758 assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ | 758 assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ |
759 if( p->accError ){ | 759 if( p->accError ){ |
760 testcase(p->accError==STRACCUM_TOOBIG); | 760 testcase(p->accError==STRACCUM_TOOBIG); |
761 testcase(p->accError==STRACCUM_NOMEM); | 761 testcase(p->accError==STRACCUM_NOMEM); |
762 return 0; | 762 return 0; |
763 } | 763 } |
764 if( p->mxAlloc==0 ){ | 764 if( p->mxAlloc==0 ){ |
765 N = p->nAlloc - p->nChar - 1; | 765 N = p->nAlloc - p->nChar - 1; |
766 setStrAccumError(p, STRACCUM_TOOBIG); | 766 setStrAccumError(p, STRACCUM_TOOBIG); |
767 return N; | 767 return N; |
768 }else{ | 768 }else{ |
769 char *zOld = p->bMalloced ? p->zText : 0; | 769 char *zOld = isMalloced(p) ? p->zText : 0; |
770 i64 szNew = p->nChar; | 770 i64 szNew = p->nChar; |
771 assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); | 771 assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
772 szNew += N + 1; | 772 szNew += N + 1; |
773 if( szNew+p->nChar<=p->mxAlloc ){ | 773 if( szNew+p->nChar<=p->mxAlloc ){ |
774 /* Force exponential buffer size growth as long as it does not overflow, | 774 /* Force exponential buffer size growth as long as it does not overflow, |
775 ** to avoid having to call this routine too often */ | 775 ** to avoid having to call this routine too often */ |
776 szNew += p->nChar; | 776 szNew += p->nChar; |
777 } | 777 } |
778 if( szNew > p->mxAlloc ){ | 778 if( szNew > p->mxAlloc ){ |
779 sqlite3StrAccumReset(p); | 779 sqlite3StrAccumReset(p); |
780 setStrAccumError(p, STRACCUM_TOOBIG); | 780 setStrAccumError(p, STRACCUM_TOOBIG); |
781 return 0; | 781 return 0; |
782 }else{ | 782 }else{ |
783 p->nAlloc = (int)szNew; | 783 p->nAlloc = (int)szNew; |
784 } | 784 } |
785 if( p->db ){ | 785 if( p->db ){ |
786 zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); | 786 zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); |
787 }else{ | 787 }else{ |
788 zNew = sqlite3_realloc64(zOld, p->nAlloc); | 788 zNew = sqlite3_realloc64(zOld, p->nAlloc); |
789 } | 789 } |
790 if( zNew ){ | 790 if( zNew ){ |
791 assert( p->zText!=0 || p->nChar==0 ); | 791 assert( p->zText!=0 || p->nChar==0 ); |
792 if( !p->bMalloced && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); | 792 if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar); |
793 p->zText = zNew; | 793 p->zText = zNew; |
794 p->nAlloc = sqlite3DbMallocSize(p->db, zNew); | 794 p->nAlloc = sqlite3DbMallocSize(p->db, zNew); |
795 p->bMalloced = 1; | 795 p->printfFlags |= SQLITE_PRINTF_MALLOCED; |
796 }else{ | 796 }else{ |
797 sqlite3StrAccumReset(p); | 797 sqlite3StrAccumReset(p); |
798 setStrAccumError(p, STRACCUM_NOMEM); | 798 setStrAccumError(p, STRACCUM_NOMEM); |
799 return 0; | 799 return 0; |
800 } | 800 } |
801 } | 801 } |
802 return N; | 802 return N; |
803 } | 803 } |
804 | 804 |
805 /* | 805 /* |
806 ** Append N copies of character c to the given string buffer. | 806 ** Append N copies of character c to the given string buffer. |
807 */ | 807 */ |
808 void sqlite3AppendChar(StrAccum *p, int N, char c){ | 808 void sqlite3AppendChar(StrAccum *p, int N, char c){ |
809 testcase( p->nChar + (i64)N > 0x7fffffff ); | 809 testcase( p->nChar + (i64)N > 0x7fffffff ); |
810 if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ | 810 if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ |
811 return; | 811 return; |
812 } | 812 } |
813 assert( (p->zText==p->zBase)==(p->bMalloced==0) ); | 813 assert( (p->zText==p->zBase)==!isMalloced(p) ); |
814 while( (N--)>0 ) p->zText[p->nChar++] = c; | 814 while( (N--)>0 ) p->zText[p->nChar++] = c; |
815 } | 815 } |
816 | 816 |
817 /* | 817 /* |
818 ** 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[]. |
819 ** So enlarge if first, then do the append. | 819 ** So enlarge if first, then do the append. |
820 ** | 820 ** |
821 ** This is a helper routine to sqlite3StrAccumAppend() that does special-case | 821 ** This is a helper routine to sqlite3StrAccumAppend() that does special-case |
822 ** work (enlarging the buffer) using tail recursion, so that the | 822 ** work (enlarging the buffer) using tail recursion, so that the |
823 ** sqlite3StrAccumAppend() routine can use fast calling semantics. | 823 ** sqlite3StrAccumAppend() routine can use fast calling semantics. |
824 */ | 824 */ |
825 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){ |
826 N = sqlite3StrAccumEnlarge(p, N); | 826 N = sqlite3StrAccumEnlarge(p, N); |
827 if( N>0 ){ | 827 if( N>0 ){ |
828 memcpy(&p->zText[p->nChar], z, N); | 828 memcpy(&p->zText[p->nChar], z, N); |
829 p->nChar += N; | 829 p->nChar += N; |
830 } | 830 } |
831 assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); | 831 assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
832 } | 832 } |
833 | 833 |
834 /* | 834 /* |
835 ** 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 |
836 ** size of the memory allocation for StrAccum if necessary. | 836 ** size of the memory allocation for StrAccum if necessary. |
837 */ | 837 */ |
838 void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ | 838 void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ |
839 assert( z!=0 || N==0 ); | 839 assert( z!=0 || N==0 ); |
840 assert( p->zText!=0 || p->nChar==0 || p->accError ); | 840 assert( p->zText!=0 || p->nChar==0 || p->accError ); |
841 assert( N>=0 ); | 841 assert( N>=0 ); |
842 assert( p->accError==0 || p->nAlloc==0 ); | 842 assert( p->accError==0 || p->nAlloc==0 ); |
843 if( p->nChar+N >= p->nAlloc ){ | 843 if( p->nChar+N >= p->nAlloc ){ |
844 enlargeAndAppend(p,z,N); | 844 enlargeAndAppend(p,z,N); |
845 }else{ | 845 }else if( N ){ |
846 assert( p->zText ); | 846 assert( p->zText ); |
847 p->nChar += N; | 847 p->nChar += N; |
848 memcpy(&p->zText[p->nChar-N], z, N); | 848 memcpy(&p->zText[p->nChar-N], z, N); |
849 } | 849 } |
850 } | 850 } |
851 | 851 |
852 /* | 852 /* |
853 ** 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. |
854 */ | 854 */ |
855 void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ | 855 void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ |
856 sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); | 856 sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z)); |
857 } | 857 } |
858 | 858 |
859 | 859 |
860 /* | 860 /* |
861 ** Finish off a string by making sure it is zero-terminated. | 861 ** Finish off a string by making sure it is zero-terminated. |
862 ** Return a pointer to the resulting string. Return a NULL | 862 ** Return a pointer to the resulting string. Return a NULL |
863 ** pointer if any kind of error was encountered. | 863 ** pointer if any kind of error was encountered. |
864 */ | 864 */ |
| 865 static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ |
| 866 assert( p->mxAlloc>0 && !isMalloced(p) ); |
| 867 p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); |
| 868 if( p->zText ){ |
| 869 memcpy(p->zText, p->zBase, p->nChar+1); |
| 870 p->printfFlags |= SQLITE_PRINTF_MALLOCED; |
| 871 }else{ |
| 872 setStrAccumError(p, STRACCUM_NOMEM); |
| 873 } |
| 874 return p->zText; |
| 875 } |
865 char *sqlite3StrAccumFinish(StrAccum *p){ | 876 char *sqlite3StrAccumFinish(StrAccum *p){ |
866 if( p->zText ){ | 877 if( p->zText ){ |
867 assert( (p->zText==p->zBase)==(p->bMalloced==0) ); | 878 assert( (p->zText==p->zBase)==!isMalloced(p) ); |
868 p->zText[p->nChar] = 0; | 879 p->zText[p->nChar] = 0; |
869 if( p->mxAlloc>0 && p->bMalloced==0 ){ | 880 if( p->mxAlloc>0 && !isMalloced(p) ){ |
870 p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); | 881 return strAccumFinishRealloc(p); |
871 if( p->zText ){ | |
872 memcpy(p->zText, p->zBase, p->nChar+1); | |
873 p->bMalloced = 1; | |
874 }else{ | |
875 setStrAccumError(p, STRACCUM_NOMEM); | |
876 } | |
877 } | 882 } |
878 } | 883 } |
879 return p->zText; | 884 return p->zText; |
880 } | 885 } |
881 | 886 |
882 /* | 887 /* |
883 ** Reset an StrAccum string. Reclaim all malloced memory. | 888 ** Reset an StrAccum string. Reclaim all malloced memory. |
884 */ | 889 */ |
885 void sqlite3StrAccumReset(StrAccum *p){ | 890 void sqlite3StrAccumReset(StrAccum *p){ |
886 assert( (p->zText==0 || p->zText==p->zBase)==(p->bMalloced==0) ); | 891 assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) ); |
887 if( p->bMalloced ){ | 892 if( isMalloced(p) ){ |
888 sqlite3DbFree(p->db, p->zText); | 893 sqlite3DbFree(p->db, p->zText); |
889 p->bMalloced = 0; | 894 p->printfFlags &= ~SQLITE_PRINTF_MALLOCED; |
890 } | 895 } |
891 p->zText = 0; | 896 p->zText = 0; |
892 } | 897 } |
893 | 898 |
894 /* | 899 /* |
895 ** Initialize a string accumulator. | 900 ** Initialize a string accumulator. |
896 ** | 901 ** |
897 ** p: The accumulator to be initialized. | 902 ** p: The accumulator to be initialized. |
898 ** db: Pointer to a database connection. May be NULL. Lookaside | 903 ** db: Pointer to a database connection. May be NULL. Lookaside |
899 ** memory is used if not NULL. db->mallocFailed is set appropriately | 904 ** memory is used if not NULL. db->mallocFailed is set appropriately |
900 ** when not NULL. | 905 ** when not NULL. |
901 ** zBase: An initial buffer. May be NULL in which case the initial buffer | 906 ** zBase: An initial buffer. May be NULL in which case the initial buffer |
902 ** is malloced. | 907 ** is malloced. |
903 ** n: Size of zBase in bytes. If total space requirements never exceed | 908 ** n: Size of zBase in bytes. If total space requirements never exceed |
904 ** n then no memory allocations ever occur. | 909 ** n then no memory allocations ever occur. |
905 ** mx: Maximum number of bytes to accumulate. If mx==0 then no memory | 910 ** mx: Maximum number of bytes to accumulate. If mx==0 then no memory |
906 ** allocations will ever occur. | 911 ** allocations will ever occur. |
907 */ | 912 */ |
908 void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ | 913 void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ |
909 p->zText = p->zBase = zBase; | 914 p->zText = p->zBase = zBase; |
910 p->db = db; | 915 p->db = db; |
911 p->nChar = 0; | 916 p->nChar = 0; |
912 p->nAlloc = n; | 917 p->nAlloc = n; |
913 p->mxAlloc = mx; | 918 p->mxAlloc = mx; |
914 p->accError = 0; | 919 p->accError = 0; |
915 p->bMalloced = 0; | 920 p->printfFlags = 0; |
916 } | 921 } |
917 | 922 |
918 /* | 923 /* |
919 ** Print into memory obtained from sqliteMalloc(). Use the internal | 924 ** Print into memory obtained from sqliteMalloc(). Use the internal |
920 ** %-conversion extensions. | 925 ** %-conversion extensions. |
921 */ | 926 */ |
922 char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ | 927 char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ |
923 char *z; | 928 char *z; |
924 char zBase[SQLITE_PRINT_BUF_SIZE]; | 929 char zBase[SQLITE_PRINT_BUF_SIZE]; |
925 StrAccum acc; | 930 StrAccum acc; |
926 assert( db!=0 ); | 931 assert( db!=0 ); |
927 sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), | 932 sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), |
928 db->aLimit[SQLITE_LIMIT_LENGTH]); | 933 db->aLimit[SQLITE_LIMIT_LENGTH]); |
929 sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); | 934 acc.printfFlags = SQLITE_PRINTF_INTERNAL; |
| 935 sqlite3VXPrintf(&acc, zFormat, ap); |
930 z = sqlite3StrAccumFinish(&acc); | 936 z = sqlite3StrAccumFinish(&acc); |
931 if( acc.accError==STRACCUM_NOMEM ){ | 937 if( acc.accError==STRACCUM_NOMEM ){ |
932 db->mallocFailed = 1; | 938 sqlite3OomFault(db); |
933 } | 939 } |
934 return z; | 940 return z; |
935 } | 941 } |
936 | 942 |
937 /* | 943 /* |
938 ** Print into memory obtained from sqliteMalloc(). Use the internal | 944 ** Print into memory obtained from sqliteMalloc(). Use the internal |
939 ** %-conversion extensions. | 945 ** %-conversion extensions. |
940 */ | 946 */ |
941 char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ | 947 char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ |
942 va_list ap; | 948 va_list ap; |
(...skipping 16 matching lines...) Expand all Loading... |
959 #ifdef SQLITE_ENABLE_API_ARMOR | 965 #ifdef SQLITE_ENABLE_API_ARMOR |
960 if( zFormat==0 ){ | 966 if( zFormat==0 ){ |
961 (void)SQLITE_MISUSE_BKPT; | 967 (void)SQLITE_MISUSE_BKPT; |
962 return 0; | 968 return 0; |
963 } | 969 } |
964 #endif | 970 #endif |
965 #ifndef SQLITE_OMIT_AUTOINIT | 971 #ifndef SQLITE_OMIT_AUTOINIT |
966 if( sqlite3_initialize() ) return 0; | 972 if( sqlite3_initialize() ) return 0; |
967 #endif | 973 #endif |
968 sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); | 974 sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); |
969 sqlite3VXPrintf(&acc, 0, zFormat, ap); | 975 sqlite3VXPrintf(&acc, zFormat, ap); |
970 z = sqlite3StrAccumFinish(&acc); | 976 z = sqlite3StrAccumFinish(&acc); |
971 return z; | 977 return z; |
972 } | 978 } |
973 | 979 |
974 /* | 980 /* |
975 ** Print into memory obtained from sqlite3_malloc()(). Omit the internal | 981 ** Print into memory obtained from sqlite3_malloc()(). Omit the internal |
976 ** %-conversion extensions. | 982 ** %-conversion extensions. |
977 */ | 983 */ |
978 char *sqlite3_mprintf(const char *zFormat, ...){ | 984 char *sqlite3_mprintf(const char *zFormat, ...){ |
979 va_list ap; | 985 va_list ap; |
(...skipping 24 matching lines...) Expand all Loading... |
1004 StrAccum acc; | 1010 StrAccum acc; |
1005 if( n<=0 ) return zBuf; | 1011 if( n<=0 ) return zBuf; |
1006 #ifdef SQLITE_ENABLE_API_ARMOR | 1012 #ifdef SQLITE_ENABLE_API_ARMOR |
1007 if( zBuf==0 || zFormat==0 ) { | 1013 if( zBuf==0 || zFormat==0 ) { |
1008 (void)SQLITE_MISUSE_BKPT; | 1014 (void)SQLITE_MISUSE_BKPT; |
1009 if( zBuf ) zBuf[0] = 0; | 1015 if( zBuf ) zBuf[0] = 0; |
1010 return zBuf; | 1016 return zBuf; |
1011 } | 1017 } |
1012 #endif | 1018 #endif |
1013 sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); | 1019 sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); |
1014 sqlite3VXPrintf(&acc, 0, zFormat, ap); | 1020 sqlite3VXPrintf(&acc, zFormat, ap); |
1015 return sqlite3StrAccumFinish(&acc); | 1021 zBuf[acc.nChar] = 0; |
| 1022 return zBuf; |
1016 } | 1023 } |
1017 char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ | 1024 char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
1018 char *z; | 1025 char *z; |
1019 va_list ap; | 1026 va_list ap; |
1020 va_start(ap,zFormat); | 1027 va_start(ap,zFormat); |
1021 z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); | 1028 z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); |
1022 va_end(ap); | 1029 va_end(ap); |
1023 return z; | 1030 return z; |
1024 } | 1031 } |
1025 | 1032 |
1026 /* | 1033 /* |
1027 ** This is the routine that actually formats the sqlite3_log() message. | 1034 ** This is the routine that actually formats the sqlite3_log() message. |
1028 ** We house it in a separate routine from sqlite3_log() to avoid using | 1035 ** We house it in a separate routine from sqlite3_log() to avoid using |
1029 ** stack space on small-stack systems when logging is disabled. | 1036 ** stack space on small-stack systems when logging is disabled. |
1030 ** | 1037 ** |
1031 ** sqlite3_log() must render into a static buffer. It cannot dynamically | 1038 ** sqlite3_log() must render into a static buffer. It cannot dynamically |
1032 ** allocate memory because it might be called while the memory allocator | 1039 ** allocate memory because it might be called while the memory allocator |
1033 ** mutex is held. | 1040 ** mutex is held. |
1034 ** | 1041 ** |
1035 ** sqlite3VXPrintf() might ask for *temporary* memory allocations for | 1042 ** sqlite3VXPrintf() might ask for *temporary* memory allocations for |
1036 ** certain format characters (%q) or for very large precisions or widths. | 1043 ** 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 | 1044 ** Care must be taken that any sqlite3_log() calls that occur while the |
1038 ** memory mutex is held do not use these mechanisms. | 1045 ** memory mutex is held do not use these mechanisms. |
1039 */ | 1046 */ |
1040 static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ | 1047 static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ |
1041 StrAccum acc; /* String accumulator */ | 1048 StrAccum acc; /* String accumulator */ |
1042 char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ | 1049 char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
1043 | 1050 |
1044 sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); | 1051 sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); |
1045 sqlite3VXPrintf(&acc, 0, zFormat, ap); | 1052 sqlite3VXPrintf(&acc, zFormat, ap); |
1046 sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, | 1053 sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, |
1047 sqlite3StrAccumFinish(&acc)); | 1054 sqlite3StrAccumFinish(&acc)); |
1048 } | 1055 } |
1049 | 1056 |
1050 /* | 1057 /* |
1051 ** Format and write a message to the log if logging is enabled. | 1058 ** Format and write a message to the log if logging is enabled. |
1052 */ | 1059 */ |
1053 void sqlite3_log(int iErrCode, const char *zFormat, ...){ | 1060 void sqlite3_log(int iErrCode, const char *zFormat, ...){ |
1054 va_list ap; /* Vararg list */ | 1061 va_list ap; /* Vararg list */ |
1055 if( sqlite3GlobalConfig.xLog ){ | 1062 if( sqlite3GlobalConfig.xLog ){ |
1056 va_start(ap, zFormat); | 1063 va_start(ap, zFormat); |
1057 renderLogMsg(iErrCode, zFormat, ap); | 1064 renderLogMsg(iErrCode, zFormat, ap); |
1058 va_end(ap); | 1065 va_end(ap); |
1059 } | 1066 } |
1060 } | 1067 } |
1061 | 1068 |
1062 #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) | 1069 #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) |
1063 /* | 1070 /* |
1064 ** A version of printf() that understands %lld. Used for debugging. | 1071 ** A version of printf() that understands %lld. Used for debugging. |
1065 ** The printf() built into some versions of windows does not understand %lld | 1072 ** The printf() built into some versions of windows does not understand %lld |
1066 ** and segfaults if you give it a long long int. | 1073 ** and segfaults if you give it a long long int. |
1067 */ | 1074 */ |
1068 void sqlite3DebugPrintf(const char *zFormat, ...){ | 1075 void sqlite3DebugPrintf(const char *zFormat, ...){ |
1069 va_list ap; | 1076 va_list ap; |
1070 StrAccum acc; | 1077 StrAccum acc; |
1071 char zBuf[500]; | 1078 char zBuf[500]; |
1072 sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); | 1079 sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); |
1073 va_start(ap,zFormat); | 1080 va_start(ap,zFormat); |
1074 sqlite3VXPrintf(&acc, 0, zFormat, ap); | 1081 sqlite3VXPrintf(&acc, zFormat, ap); |
1075 va_end(ap); | 1082 va_end(ap); |
1076 sqlite3StrAccumFinish(&acc); | 1083 sqlite3StrAccumFinish(&acc); |
1077 fprintf(stdout,"%s", zBuf); | 1084 fprintf(stdout,"%s", zBuf); |
1078 fflush(stdout); | 1085 fflush(stdout); |
1079 } | 1086 } |
1080 #endif | 1087 #endif |
1081 | 1088 |
1082 | 1089 |
1083 /* | 1090 /* |
1084 ** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument | 1091 ** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument |
1085 ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. | 1092 ** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats. |
1086 */ | 1093 */ |
1087 void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){ | 1094 void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ |
1088 va_list ap; | 1095 va_list ap; |
1089 va_start(ap,zFormat); | 1096 va_start(ap,zFormat); |
1090 sqlite3VXPrintf(p, bFlags, zFormat, ap); | 1097 sqlite3VXPrintf(p, zFormat, ap); |
1091 va_end(ap); | 1098 va_end(ap); |
1092 } | 1099 } |
OLD | NEW |