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..2a3dd81d7d2603a072d5074973004ab48123bc7f 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 |
@@ -402,7 +400,11 @@ void sqlite3VXPrintf( |
v = va_arg(ap,int); |
} |
if( v<0 ){ |
- longvalue = -v; |
+ if( v==SMALLEST_INT64 ){ |
+ longvalue = ((u64)1)<<63; |
+ }else{ |
+ longvalue = -v; |
+ } |
prefix = '-'; |
}else{ |
longvalue = v; |
@@ -462,7 +464,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 +612,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 +651,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 +675,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: { |
@@ -760,6 +767,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ |
return; |
} |
}else{ |
+ char *zOld = (p->zText==p->zBase ? 0 : p->zText); |
i64 szNew = p->nChar; |
szNew += N + 1; |
if( szNew > p->mxAlloc ){ |
@@ -769,10 +777,13 @@ 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 = sqlite3DbRealloc(p->db, zOld, p->nAlloc); |
+ }else{ |
+ zNew = sqlite3_realloc(zOld, p->nAlloc); |
+ } |
if( zNew ){ |
- memcpy(zNew, p->zText, p->nChar); |
- sqlite3StrAccumReset(p); |
+ if( zOld==0 ) memcpy(zNew, p->zText, p->nChar); |
p->zText = zNew; |
}else{ |
p->mallocFailed = 1; |
@@ -794,7 +805,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 +825,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 +911,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; |
@@ -918,24 +938,63 @@ char *sqlite3_mprintf(const char *zFormat, ...){ |
** current locale settings. This is important for SQLite because we |
** are not able to use a "," as the decimal point in place of "." as |
** specified by some locales. |
+** |
+** Oops: The first two arguments of sqlite3_snprintf() are backwards |
+** from the snprintf() standard. Unfortunately, it is too late to change |
+** this without breaking compatibility, so we just have to live with the |
+** mistake. |
+** |
+** sqlite3_vsnprintf() is the varargs version. |
*/ |
-char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
- char *z; |
- va_list ap; |
+char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ |
StrAccum acc; |
- |
- if( n<=0 ){ |
- return zBuf; |
- } |
+ if( n<=0 ) return zBuf; |
sqlite3StrAccumInit(&acc, zBuf, n, 0); |
acc.useMalloc = 0; |
- va_start(ap,zFormat); |
sqlite3VXPrintf(&acc, 0, zFormat, ap); |
+ return sqlite3StrAccumFinish(&acc); |
+} |
+char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ |
+ char *z; |
+ va_list ap; |
+ va_start(ap,zFormat); |
+ z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); |
va_end(ap); |
- z = sqlite3StrAccumFinish(&acc); |
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 +1015,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 |