Add a new, experimental logging interface designed to aid in debugging of
deeply embedded projects that use SQLite.

FossilOrigin-Name: 103321e37ae46eacfad4e127d13477ad5dd02bab
diff --git a/src/global.c b/src/global.c
index bdfd1ff..673a274 100644
--- a/src/global.c
+++ b/src/global.c
@@ -164,6 +164,8 @@
    0,                         /* isPCacheInit */
    0,                         /* pInitMutex */
    0,                         /* nRefInitMutex */
+   0,                         /* xLog */
+   0,                         /* pLogArg */
 };
 
 
diff --git a/src/main.c b/src/main.c
index 07fe15c..e4419d2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -378,6 +378,16 @@
       sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
       break;
     }
+    
+    /* Record a pointer to the logger funcction and its first argument.
+    ** The default is NULL.  Logging is disabled if the function pointer is
+    ** NULL.
+    */
+    case SQLITE_CONFIG_LOG: {
+      sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*));
+      sqlite3GlobalConfig.pLogArg = va_arg(ap, void*);
+      break;
+    }
 
     default: {
       rc = SQLITE_ERROR;
diff --git a/src/printf.c b/src/printf.c
index fdd4793..2966946 100644
--- a/src/printf.c
+++ b/src/printf.c
@@ -939,6 +939,28 @@
   return z;
 }
 
+/*
+** Format and write a message to the log if logging is enabled.
+*/
+void sqlite3_log(int iPriority, const char *zFormat, ...){
+  void (*xLog)(void*, int, const char*);  /* The global logger function */
+  void *pLogArg;                          /* First argument to the logger */
+  va_list ap;                             /* Vararg list */
+  char *zMsg;                             /* Complete log message */
+  
+  xLog = sqlite3GlobalConfig.xLog;
+  if( xLog ){
+    va_start(ap, zFormat);
+    sqlite3BeginBenignMalloc();
+    zMsg = sqlite3_vmprintf(zFormat, ap);
+    sqlite3EndBenignMalloc();
+    va_end(ap);
+    pLogArg = sqlite3GlobalConfig.pLogArg;
+    xLog(pLogArg, iPriority, zMsg ? zMsg : zFormat);
+    sqlite3_free(zMsg);
+  }
+}
+
 #if defined(SQLITE_DEBUG)
 /*
 ** A version of printf() that understands %lld.  Used for debugging.
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index e1b8dc6..bd61083 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -914,7 +914,6 @@
 
 /*
 ** CAPI3REF: Configuring The SQLite Library
-** EXPERIMENTAL
 **
 ** The sqlite3_config() interface is used to make global configuration
 ** changes to SQLite in order to tune SQLite to the specific needs of
@@ -1255,6 +1254,7 @@
 #define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
 #define SQLITE_CONFIG_PCACHE       14  /* sqlite3_pcache_methods* */
 #define SQLITE_CONFIG_GETPCACHE    15  /* sqlite3_pcache_methods* */
+#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
 
 /*
 ** CAPI3REF: Configuration Options
@@ -5664,6 +5664,20 @@
 int sqlite3_strnicmp(const char *, const char *, int);
 
 /*
+** CAPI3REF: Error Logging Interface
+** EXPERIMENTAL
+**
+** ^The [sqlite3_log()] interface writes a message into the error log
+** established by the [SQLITE_CONFIG_ERRORLOG] option to [sqlite3_config()].
+**
+** The sqlite3_log() interface is intended for use by extensions such as
+** virtual tables, collating functions, and SQL functions.  While there is
+** nothing to prevent an application from calling sqlite3_log(), doing so
+** is considered bad form.
+*/
+void sqlite3_log(int iPriority, const char *zFormat, ...);
+
+/*
 ** Undo the hack that converts floating point types to integer for
 ** builds on processors without floating point support.
 */
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index ff90e03..a576dd6 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2370,6 +2370,8 @@
   int isPCacheInit;                 /* True after malloc is initialized */
   sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */
   int nRefInitMutex;                /* Number of users of pInitMutex */
+  void (*xLog)(void*,int,const char*); /* Function for logging */
+  void *pLogArg;                       /* First argument to xLog() */
 };
 
 /*