Index: third_party/sqlite/src/src/printf.c |
diff --git a/third_party/sqlite/src/src/printf.c b/third_party/sqlite/src/src/printf.c |
index d8d838693fcd44b6350360f4b2707019a0bbe233..da2fdf610df5ed771b86e44b65e2f6ddeea5ea2f 100644 |
--- a/third_party/sqlite/src/src/printf.c |
+++ b/third_party/sqlite/src/src/printf.c |
@@ -5,8 +5,6 @@ |
** an historical reference. Most of the "enhancements" have been backed |
** out so that the functionality is now the same as standard printf(). |
** |
-** $Id: printf.c,v 1.104 2009/06/03 01:24:54 drh Exp $ |
-** |
************************************************************************** |
** |
** The following modules is an enhanced replacement for the "printf" subroutines |
@@ -462,7 +460,9 @@ void sqlite3VXPrintf( |
case etEXP: |
case etGENERIC: |
realvalue = va_arg(ap,double); |
-#ifndef SQLITE_OMIT_FLOATING_POINT |
+#ifdef SQLITE_OMIT_FLOATING_POINT |
+ length = 0; |
+#else |
if( precision<0 ) precision = 6; /* Set default precision */ |
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10; |
if( realvalue<0.0 ){ |
@@ -608,7 +608,7 @@ void sqlite3VXPrintf( |
while( nPad-- ) bufpt[i++] = '0'; |
length = width; |
} |
-#endif |
+#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */ |
break; |
case etSIZE: |
*(va_arg(ap,int*)) = pAccum->nChar; |
@@ -647,14 +647,15 @@ void sqlite3VXPrintf( |
case etSQLESCAPE: |
case etSQLESCAPE2: |
case etSQLESCAPE3: { |
- int i, j, n, isnull; |
+ int i, j, k, n, isnull; |
int needQuote; |
char ch; |
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ |
char *escarg = va_arg(ap,char*); |
isnull = escarg==0; |
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); |
- for(i=n=0; (ch=escarg[i])!=0; i++){ |
+ k = precision; |
+ for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){ |
if( ch==q ) n++; |
} |
needQuote = !isnull && xtype==etSQLESCAPE2; |
@@ -670,15 +671,17 @@ void sqlite3VXPrintf( |
} |
j = 0; |
if( needQuote ) bufpt[j++] = q; |
- for(i=0; (ch=escarg[i])!=0; i++){ |
- bufpt[j++] = ch; |
+ k = i; |
+ for(i=0; i<k; i++){ |
+ bufpt[j++] = ch = escarg[i]; |
if( ch==q ) bufpt[j++] = ch; |
} |
if( needQuote ) bufpt[j++] = q; |
bufpt[j] = 0; |
length = j; |
- /* The precision is ignored on %q and %Q */ |
- /* if( precision>=0 && precision<length ) length = precision; */ |
+ /* The precision in %q and %Q means how many input characters to |
+ ** consume, not the length of the output... |
+ ** if( precision>=0 && precision<length ) length = precision; */ |
break; |
} |
case etTOKEN: { |
@@ -769,7 +772,11 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ |
}else{ |
p->nAlloc = (int)szNew; |
} |
- zNew = sqlite3DbMallocRaw(p->db, p->nAlloc ); |
+ if( p->useMalloc==1 ){ |
+ zNew = sqlite3DbMallocRaw(p->db, p->nAlloc ); |
+ }else{ |
+ zNew = sqlite3_malloc(p->nAlloc); |
+ } |
if( zNew ){ |
memcpy(zNew, p->zText, p->nChar); |
sqlite3StrAccumReset(p); |
@@ -794,7 +801,11 @@ char *sqlite3StrAccumFinish(StrAccum *p){ |
if( p->zText ){ |
p->zText[p->nChar] = 0; |
if( p->useMalloc && p->zText==p->zBase ){ |
- p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); |
+ if( p->useMalloc==1 ){ |
+ p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); |
+ }else{ |
+ p->zText = sqlite3_malloc(p->nChar+1); |
+ } |
if( p->zText ){ |
memcpy(p->zText, p->zBase, p->nChar+1); |
}else{ |
@@ -810,7 +821,11 @@ char *sqlite3StrAccumFinish(StrAccum *p){ |
*/ |
void sqlite3StrAccumReset(StrAccum *p){ |
if( p->zText!=p->zBase ){ |
- sqlite3DbFree(p->db, p->zText); |
+ if( p->useMalloc==1 ){ |
+ sqlite3DbFree(p->db, p->zText); |
+ }else{ |
+ sqlite3_free(p->zText); |
+ } |
} |
p->zText = 0; |
} |
@@ -892,6 +907,7 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){ |
if( sqlite3_initialize() ) return 0; |
#endif |
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); |
+ acc.useMalloc = 2; |
sqlite3VXPrintf(&acc, 0, zFormat, ap); |
z = sqlite3StrAccumFinish(&acc); |
return z; |
@@ -936,6 +952,38 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
return z; |
} |
+/* |
+** This is the routine that actually formats the sqlite3_log() message. |
+** We house it in a separate routine from sqlite3_log() to avoid using |
+** stack space on small-stack systems when logging is disabled. |
+** |
+** sqlite3_log() must render into a static buffer. It cannot dynamically |
+** allocate memory because it might be called while the memory allocator |
+** mutex is held. |
+*/ |
+static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ |
+ StrAccum acc; /* String accumulator */ |
+ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ |
+ |
+ sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); |
+ acc.useMalloc = 0; |
+ sqlite3VXPrintf(&acc, 0, zFormat, ap); |
+ sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, |
+ sqlite3StrAccumFinish(&acc)); |
+} |
+ |
+/* |
+** Format and write a message to the log if logging is enabled. |
+*/ |
+void sqlite3_log(int iErrCode, const char *zFormat, ...){ |
+ va_list ap; /* Vararg list */ |
+ if( sqlite3GlobalConfig.xLog ){ |
+ va_start(ap, zFormat); |
+ renderLogMsg(iErrCode, zFormat, ap); |
+ va_end(ap); |
+ } |
+} |
+ |
#if defined(SQLITE_DEBUG) |
/* |
** A version of printf() that understands %lld. Used for debugging. |
@@ -956,3 +1004,15 @@ void sqlite3DebugPrintf(const char *zFormat, ...){ |
fflush(stdout); |
} |
#endif |
+ |
+#ifndef SQLITE_OMIT_TRACE |
+/* |
+** variable-argument wrapper around sqlite3VXPrintf(). |
+*/ |
+void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){ |
+ va_list ap; |
+ va_start(ap,zFormat); |
+ sqlite3VXPrintf(p, 1, zFormat, ap); |
+ va_end(ap); |
+} |
+#endif |