Progress toward implementation of sqlite3_config() and a rework of the
mutex and memory allocation subsystems.  This is an incremental check-in. (CVS 5218)

FossilOrigin-Name: a03c5af115889f477e17187a198a7d2d40bc76bf
diff --git a/src/complete.c b/src/complete.c
index ae61d8a..8e2dbc2 100644
--- a/src/complete.c
+++ b/src/complete.c
@@ -16,7 +16,7 @@
 ** separating it out, the code will be automatically omitted from
 ** static links that do not use it.
 **
-** $Id: complete.c,v 1.6 2007/08/27 23:26:59 drh Exp $
+** $Id: complete.c,v 1.7 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 #ifndef SQLITE_OMIT_COMPLETE
@@ -258,11 +258,17 @@
   char const *zSql8;
   int rc = SQLITE_NOMEM;
 
+#ifndef SQLITE_OMIT_AUTOINIT
+  rc = sqlite3_initialize();
+  if( rc ) return rc;
+#endif
   pVal = sqlite3ValueNew(0);
   sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
   zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
   if( zSql8 ){
     rc = sqlite3_complete(zSql8);
+  }else{
+    rc = SQLITE_NOMEM;
   }
   sqlite3ValueFree(pVal);
   return sqlite3ApiExit(0, rc);
diff --git a/src/global.c b/src/global.c
new file mode 100644
index 0000000..6c21d89
--- /dev/null
+++ b/src/global.c
@@ -0,0 +1,69 @@
+/*
+** 2008 June 13
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains definitions of global variables and contants.
+**
+** $Id: global.c,v 1.1 2008/06/13 18:24:27 drh Exp $
+*/
+#include "sqliteInt.h"
+
+
+/* An array to map all upper-case characters into their corresponding
+** lower-case character. 
+**
+** SQLite only considers US-ASCII (or EBCDIC) characters.  We do not
+** handle case conversions for the UTF character set since the tables
+** involved are nearly as big or bigger than SQLite itself.
+*/
+const unsigned char sqlite3UpperToLower[] = {
+#ifdef SQLITE_ASCII
+      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
+     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+     54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
+    104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
+    122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
+    108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
+    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
+    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
+    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
+    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
+    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
+    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
+    252,253,254,255
+#endif
+#ifdef SQLITE_EBCDIC
+      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, /* 0x */
+     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
+     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
+     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
+     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
+     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
+     96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */
+    112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */
+    128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
+    144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */
+    160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
+    176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
+    192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
+    208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
+    224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */
+    239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */
+#endif
+};
+
+/*
+** The following singleton contains the global configuration for
+** the SQLite library.
+*/
+struct Sqlite3Config sqlite3Config;
diff --git a/src/loadext.c b/src/loadext.c
index 3ad0ab1..828d71e 100644
--- a/src/loadext.c
+++ b/src/loadext.c
@@ -12,7 +12,7 @@
 ** This file contains code used to dynamically load extensions into
 ** the SQLite library.
 **
-** $Id: loadext.c,v 1.47 2008/05/15 19:43:53 drh Exp $
+** $Id: loadext.c,v 1.48 2008/06/13 18:24:27 drh Exp $
 */
 
 #ifndef SQLITE_CORE
@@ -469,44 +469,56 @@
 ** loaded by every new database connection.
 */
 int sqlite3_auto_extension(void *xInit){
-  int i;
-  int rc = SQLITE_OK;
-#ifndef SQLITE_MUTEX_NOOP
-  sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+#ifndef SQLITE_OMIT_AUTOINIT
+  int rc = sqlite3_initialize();
+  if( rc ){
+    return rc;
+  }else
 #endif
-  sqlite3_mutex_enter(mutex);
-  for(i=0; i<autoext.nExt; i++){
-    if( autoext.aExt[i]==xInit ) break;
-  }
-  if( i==autoext.nExt ){
-    int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);
-    void **aNew;
-    aNew = sqlite3_realloc(autoext.aExt, nByte);
-    if( aNew==0 ){
-      rc = SQLITE_NOMEM;
-    }else{
-      autoext.aExt = aNew;
-      autoext.aExt[autoext.nExt] = xInit;
-      autoext.nExt++;
+  {
+    int i;
+#ifndef SQLITE_MUTEX_NOOP
+    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+    sqlite3_mutex_enter(mutex);
+    for(i=0; i<autoext.nExt; i++){
+      if( autoext.aExt[i]==xInit ) break;
     }
+    if( i==autoext.nExt ){
+      int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);
+      void **aNew;
+      aNew = sqlite3_realloc(autoext.aExt, nByte);
+      if( aNew==0 ){
+        rc = SQLITE_NOMEM;
+      }else{
+        autoext.aExt = aNew;
+        autoext.aExt[autoext.nExt] = xInit;
+        autoext.nExt++;
+      }
+    }
+    sqlite3_mutex_leave(mutex);
+    assert( (rc&0xff)==rc );
+    return rc;
   }
-  sqlite3_mutex_leave(mutex);
-  assert( (rc&0xff)==rc );
-  return rc;
 }
 
 /*
 ** Reset the automatic extension loading mechanism.
 */
 void sqlite3_reset_auto_extension(void){
-#ifndef SQLITE_MUTEX_NOOP
-  sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+#ifndef SQLITE_OMIT_AUTOINIT
+  if( sqlite3_initialize()==SQLITE_OK )
 #endif
-  sqlite3_mutex_enter(mutex);
-  sqlite3_free(autoext.aExt);
-  autoext.aExt = 0;
-  autoext.nExt = 0;
-  sqlite3_mutex_leave(mutex);
+  {
+#ifndef SQLITE_MUTEX_NOOP
+    sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+    sqlite3_mutex_enter(mutex);
+    sqlite3_free(autoext.aExt);
+    autoext.aExt = 0;
+    autoext.nExt = 0;
+    sqlite3_mutex_leave(mutex);
+  }
 }
 
 /*
diff --git a/src/main.c b/src/main.c
index c80bacb..d98530c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.442 2008/05/26 20:19:26 drh Exp $
+** $Id: main.c,v 1.443 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -54,6 +54,123 @@
 char *sqlite3_temp_directory = 0;
 
 /*
+** Flags to help SQLite determine if it has been initialized.
+*/
+static int sqlite3IsInit = 0;        /* Initialization has started */
+static int sqlite3FullInit = 0;      /* Initialization is complete */
+
+/*
+** Initialize SQLite.  
+**
+** This routine must be called to initialize the memory allocation,
+** VFS, and mutex subsystesms prior to doing any serious work with
+** SQLite.  But as long as you do not compile with SQLITE_OMIT_AUTOINIT
+** this routine will be called automatically by key routines such as
+** sqlite3_open().  
+**
+** This routine is a no-op except on its very first call for the process,
+** or for the first call after a call to sqlite3_shutdown.
+*/
+int sqlite3_initialize(void){
+  int rc;
+  if( sqlite3IsInit ) return SQLITE_OK;
+  rc = sqlite3_mutex_init();
+  if( rc==SQLITE_OK ){
+#ifndef SQLITE_MUTEX_NOOP
+    sqlite3_mutex *pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+    sqlite3_mutex_enter(pMutex);
+    if( sqlite3IsInit==0 ){
+      sqlite3IsInit = 1;
+      if( rc==SQLITE_OK ) rc = sqlite3MallocInit();
+      if( rc==SQLITE_OK ) rc = sqlite3_os_init();
+      if( rc!=SQLITE_OK ){
+        sqlite3IsInit = 0;
+      }else{
+        sqlite3FullInit = 1;
+      }
+    }
+    sqlite3_mutex_leave(pMutex);
+  }
+  return rc;
+}
+
+/*
+** Undo the effects of sqlite3_initialize().  Must not be called while
+** there are outstanding database connections or memory allocations or
+** while any part of SQLite is otherwise in use in any thread.  This
+** routine is not threadsafe.  Not by a long shot.
+*/
+int sqlite3_shutdown(void){
+  sqlite3_os_end();
+  sqlite3_mutex_end();
+  sqlite3FullInit = 0;
+  sqlite3IsInit = 0;
+  return SQLITE_OK;
+}
+
+/*
+** This API allows applications to modify the global configuration of
+** the SQLite library at run-time.
+**
+** This routine should only be called when there are no outstanding
+** database connections or memory allocations.  This routine is not
+** threadsafe.  Failure to heed these warnings can lead to unpredictable
+** behavior.
+*/
+int sqlite3_config(int op, ...){
+  va_list ap;
+  int rc = SQLITE_OK;
+
+  /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
+  ** the SQLite library is in use. */
+  if( sqlite3FullInit ) return SQLITE_MISUSE;
+
+  va_start(ap, op);
+  switch( op ){
+    case SQLITE_CONFIG_SINGLETHREAD: {
+      /* Disable all mutexing */
+      sqlite3Config.bCoreMutex = 0;
+      sqlite3Config.bFullMutex = 0;
+      break;
+    }
+    case SQLITE_CONFIG_MULTITHREAD: {
+      /* Disable mutexing of database connections */
+      /* Enable mutexing of core data structures */
+      sqlite3Config.bCoreMutex = 1;
+      sqlite3Config.bFullMutex = 0;
+      break;
+    }
+    case SQLITE_CONFIG_SERIALIZED: {
+      /* Enable all mutexing */
+      sqlite3Config.bCoreMutex = 1;
+      sqlite3Config.bFullMutex = 1;
+      break;
+    }
+    case SQLITE_CONFIG_MALLOC: {
+      /* Specify an alternative malloc implementation */
+      sqlite3Config.xMalloc = va_arg(ap, void*(*)(int));
+      sqlite3Config.xFree = va_arg(ap, void(*)(void*));
+      sqlite3Config.xRealloc = va_arg(ap, void*(*)(void*,int));
+      sqlite3Config.xMemsize = va_arg(ap, int(*)(void*));
+      sqlite3Config.xRoundup = va_arg(ap, int(*)(int));
+      break;
+    }
+    case SQLITE_CONFIG_MEMSTATS: {
+      /* Enable or disable the malloc status collection */
+      sqlite3Config.bMemstat = va_arg(ap, int);
+      break;
+    }
+    default: {
+      rc = SQLITE_ERROR;
+      break;
+    }
+  }
+  va_end(ap);
+  return rc;
+}
+
+/*
 ** Routine needed to support the testcase() macro.
 */
 #ifdef SQLITE_COVERAGE_TEST
@@ -1040,6 +1157,11 @@
   int rc;
   CollSeq *pColl;
 
+#ifndef SQLITE_OMIT_AUTOINIT
+  rc = sqlite3_initialize();
+  if( rc ) return rc;
+#endif
+
   /* Remove harmful bits from the flags parameter */
   flags &=  ~( SQLITE_OPEN_DELETEONCLOSE |
                SQLITE_OPEN_MAIN_DB |
@@ -1249,11 +1371,15 @@
 ){
   char const *zFilename8;   /* zFilename encoded in UTF-8 instead of UTF-16 */
   sqlite3_value *pVal;
-  int rc = SQLITE_NOMEM;
+  int rc;
 
   assert( zFilename );
   assert( ppDb );
   *ppDb = 0;
+#ifndef SQLITE_OMIT_AUTOINIT
+  rc = sqlite3_initialize();
+  if( rc ) return rc;
+#endif
   pVal = sqlite3ValueNew(0);
   sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC);
   zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8);
@@ -1264,6 +1390,8 @@
     if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){
       ENC(*ppDb) = SQLITE_UTF16NATIVE;
     }
+  }else{
+    rc = SQLITE_NOMEM;
   }
   sqlite3ValueFree(pVal);
 
@@ -1536,6 +1664,7 @@
   sqlite3_vfs *pVfs;
   int rc;
   pVfs = sqlite3_vfs_find(0);
+  if( pVfs==0 ) return 0;
 
   /* This function works in milliseconds, but the underlying OsSleep() 
   ** API uses microseconds. Hence the 1000's.
diff --git a/src/mem1.c b/src/mem1.c
index 87dd41a..296dbe7 100644
--- a/src/mem1.c
+++ b/src/mem1.c
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement a memory
 ** allocation subsystem for use by SQLite.  
 **
-** $Id: mem1.c,v 1.17 2008/03/18 00:07:11 drh Exp $
+** $Id: mem1.c,v 1.18 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -189,6 +189,13 @@
 }
 
 /*
+** Initialize the memmory allocation subsystem.
+*/
+int sqlite3MallocInit(void){
+  return SQLITE_OK;
+}
+
+/*
 ** Change the size of an existing memory allocation
 */
 void *sqlite3_realloc(void *pPrior, int nBytes){
diff --git a/src/mem2.c b/src/mem2.c
index 10d68e2..ff8c87a 100644
--- a/src/mem2.c
+++ b/src/mem2.c
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement a memory
 ** allocation subsystem for use by SQLite.  
 **
-** $Id: mem2.c,v 1.26 2008/04/10 14:57:25 drh Exp $
+** $Id: mem2.c,v 1.27 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -241,6 +241,13 @@
 }
 
 /*
+** Initialize the memmory allocation subsystem.
+*/
+int sqlite3MallocInit(void){
+  return SQLITE_OK;
+}
+
+/*
 ** Allocate nByte bytes of memory.
 */
 void *sqlite3_malloc(int nByte){
diff --git a/src/mem3.c b/src/mem3.c
index 9f15bc6..e74cb8f 100644
--- a/src/mem3.c
+++ b/src/mem3.c
@@ -20,7 +20,7 @@
 ** This version of the memory allocation subsystem is used if
 ** and only if SQLITE_MEMORY_SIZE is defined.
 **
-** $Id: mem3.c,v 1.12 2008/02/19 15:15:16 drh Exp $
+** $Id: mem3.c,v 1.13 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -298,6 +298,13 @@
 }
 
 /*
+** Initialize the memmory allocation subsystem.
+*/
+int sqlite3MallocInit(void){
+  return SQLITE_OK;
+}
+
+/*
 ** Chunk i is a free chunk that has been unlinked.  Adjust its 
 ** size parameters for check-out and return a pointer to the 
 ** user portion of the chunk.
diff --git a/src/mem5.c b/src/mem5.c
index 4250cfa..fbea0ef 100644
--- a/src/mem5.c
+++ b/src/mem5.c
@@ -20,7 +20,7 @@
 ** This version of the memory allocation subsystem is used if
 ** and only if SQLITE_POW2_MEMORY_SIZE is defined.
 **
-** $Id: mem5.c,v 1.4 2008/02/19 15:15:16 drh Exp $
+** $Id: mem5.c,v 1.5 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -284,6 +284,13 @@
 }
 
 /*
+** Initialize the memmory allocation subsystem.
+*/
+int sqlite3MallocInit(void){
+  return SQLITE_OK;
+}
+
+/*
 ** Find the first entry on the freelist iLogsize.  Unlink that
 ** entry and return its index. 
 */
diff --git a/src/mutex.c b/src/mutex.c
index f4372c9..939f362 100644
--- a/src/mutex.c
+++ b/src/mutex.c
@@ -19,7 +19,7 @@
 ** implementation is suitable for testing.
 ** debugging purposes
 **
-** $Id: mutex.c,v 1.17 2008/03/26 18:34:43 danielk1977 Exp $
+** $Id: mutex.c,v 1.18 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -39,6 +39,12 @@
 };
 
 /*
+** Initialize and deinitialize the mutex subsystem.
+*/
+int sqlite3_mutex_init(void){ return SQLITE_OK; }
+int sqlite3_mutex_end(void){ return SQLITE_OK; }
+
+/*
 ** The sqlite3_mutex_alloc() routine allocates a new
 ** mutex and returns a pointer to it.  If it returns NULL
 ** that means that a mutex could not be allocated. 
diff --git a/src/mutex.h b/src/mutex.h
index e7ec9d2..f85739d 100644
--- a/src/mutex.h
+++ b/src/mutex.h
@@ -19,7 +19,7 @@
 ** Source files should #include the sqliteInt.h file and let that file
 ** include this one indirectly.
 **
-** $Id: mutex.h,v 1.2 2007/08/30 14:10:30 drh Exp $
+** $Id: mutex.h,v 1.3 2008/06/13 18:24:27 drh Exp $
 */
 
 
@@ -77,6 +77,8 @@
 #define sqlite3_mutex_leave(X)
 #define sqlite3_mutex_held(X)     1
 #define sqlite3_mutex_notheld(X)  1
+#define sqlite3_mutex_init()
+#define sqlite3_mutex_end()
 #endif
 
 #endif /* SQLITE_MUTEX_APPDEF */
diff --git a/src/mutex_os2.c b/src/mutex_os2.c
index ed5477a..dd1894d 100644
--- a/src/mutex_os2.c
+++ b/src/mutex_os2.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains the C functions that implement mutexes for OS/2
 **
-** $Id: mutex_os2.c,v 1.6 2008/03/26 18:34:43 danielk1977 Exp $
+** $Id: mutex_os2.c,v 1.7 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -40,6 +40,12 @@
 #define OS2_MUTEX_INITIALIZER   0,0,0,0
 
 /*
+** Initialize and deinitialize the mutex subsystem.
+*/
+int sqlite3_mutex_init(void){ return SQLITE_OK; }
+int sqlite3_mutex_end(void){ return SQLITE_OK; }
+
+/*
 ** The sqlite3_mutex_alloc() routine allocates a new
 ** mutex and returns a pointer to it.  If it returns NULL
 ** that means that a mutex could not be allocated. 
@@ -147,7 +153,7 @@
 ** SQLite is careful to deallocate every mutex that it allocates.
 */
 void sqlite3_mutex_free(sqlite3_mutex *p){
-  assert( p );
+  if( p==0 ) return;
   assert( p->nRef==0 );
   assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
   DosCloseMutexSem( p->mutex );
@@ -169,7 +175,7 @@
   TID tid;
   PID holder1;
   ULONG holder2;
-  assert( p );
+  if( p==0 ) return;
   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
   DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
   DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
@@ -181,7 +187,7 @@
   TID tid;
   PID holder1;
   ULONG holder2;
-  assert( p );
+  if( p==0 ) return SQLITE_OK;
   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
   if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) {
     DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
@@ -205,6 +211,7 @@
   TID tid;
   PID holder1;
   ULONG holder2;
+  if( p==0 ) return;
   assert( p->nRef>0 );
   DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
   assert( p->owner==tid );
diff --git a/src/mutex_unix.c b/src/mutex_unix.c
index ebd3217..4639a84 100644
--- a/src/mutex_unix.c
+++ b/src/mutex_unix.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains the C functions that implement mutexes for pthreads
 **
-** $Id: mutex_unix.c,v 1.7 2008/03/29 12:47:27 rse Exp $
+** $Id: mutex_unix.c,v 1.8 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -46,6 +46,12 @@
 #endif
 
 /*
+** Initialize and deinitialize the mutex subsystem.
+*/
+int sqlite3_mutex_init(void){ return SQLITE_OK; }
+int sqlite3_mutex_end(void){ return SQLITE_OK; }
+
+/*
 ** The sqlite3_mutex_alloc() routine allocates a new
 ** mutex and returns a pointer to it.  If it returns NULL
 ** that means that a mutex could not be allocated.  SQLite
@@ -142,11 +148,12 @@
 ** mutex that it allocates.
 */
 void sqlite3_mutex_free(sqlite3_mutex *p){
-  assert( p );
-  assert( p->nRef==0 );
-  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
-  pthread_mutex_destroy(&p->mutex);
-  sqlite3_free(p);
+  if( p ){
+    assert( p->nRef==0 );
+    assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+    pthread_mutex_destroy(&p->mutex);
+    sqlite3_free(p);
+  }
 }
 
 /*
@@ -161,7 +168,7 @@
 ** more than once, the behavior is undefined.
 */
 void sqlite3_mutex_enter(sqlite3_mutex *p){
-  assert( p );
+  if( p==0 ) return;
   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
 
 #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
@@ -202,7 +209,7 @@
 }
 int sqlite3_mutex_try(sqlite3_mutex *p){
   int rc;
-  assert( p );
+  if( p==0 ) return SQLITE_OK;
   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
 
 #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
@@ -257,7 +264,7 @@
 ** is not currently allocated.  SQLite will never do either.
 */
 void sqlite3_mutex_leave(sqlite3_mutex *p){
-  assert( p );
+  if( p==0 ) return;
   assert( sqlite3_mutex_held(p) );
   p->nRef--;
   assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
diff --git a/src/mutex_w32.c b/src/mutex_w32.c
index 7fc73da..fcb468a 100644
--- a/src/mutex_w32.c
+++ b/src/mutex_w32.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains the C functions that implement mutexes for win32
 **
-** $Id: mutex_w32.c,v 1.6 2008/03/26 18:34:43 danielk1977 Exp $
+** $Id: mutex_w32.c,v 1.7 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -59,6 +59,12 @@
 
 
 /*
+** Initialize and deinitialize the mutex subsystem.
+*/
+int sqlite3_mutex_init(void){ return SQLITE_OK; }
+int sqlite3_mutex_end(void){ return SQLITE_OK; }
+
+/*
 ** The sqlite3_mutex_alloc() routine allocates a new
 ** mutex and returns a pointer to it.  If it returns NULL
 ** that means that a mutex could not be allocated.  SQLite
@@ -161,7 +167,7 @@
 ** more than once, the behavior is undefined.
 */
 void sqlite3_mutex_enter(sqlite3_mutex *p){
-  assert( p );
+  if( p==0 ) return;
   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
   EnterCriticalSection(&p->mutex);
   p->owner = GetCurrentThreadId(); 
@@ -169,7 +175,7 @@
 }
 int sqlite3_mutex_try(sqlite3_mutex *p){
   int rc = SQLITE_BUSY;
-  assert( p );
+  if( p==0 ) return SQLITE_OK;
   assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) );
   /*
   ** The sqlite3_mutex_try() routine is very rarely used, and when it
@@ -199,6 +205,7 @@
 ** is not currently allocated.  SQLite will never do either.
 */
 void sqlite3_mutex_leave(sqlite3_mutex *p){
+  if( p==0 ) return;
   assert( p->nRef>0 );
   assert( p->owner==GetCurrentThreadId() );
   p->nRef--;
diff --git a/src/os.c b/src/os.c
index 834100f..b4bcd82 100644
--- a/src/os.c
+++ b/src/os.c
@@ -13,7 +13,7 @@
 ** This file contains OS interface code that is common to all
 ** architectures.
 **
-** $Id: os.c,v 1.111 2008/06/06 11:11:26 danielk1977 Exp $
+** $Id: os.c,v 1.112 2008/06/13 18:24:27 drh Exp $
 */
 #define _SQLITE_OS_C_ 1
 #include "sqliteInt.h"
@@ -200,7 +200,14 @@
 */
 sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
 #ifndef SQLITE_MUTEX_NOOP
-  sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+  sqlite3_mutex *mutex;
+#endif
+#ifndef SQLITE_OMIT_AUTOINIT
+  int rc = sqlite3_initialize();
+  if( rc ) return 0;
+#endif
+#ifndef SQLITE_MUTEX_NOOP
+  mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
 #endif
   sqlite3_vfs *pVfs = 0;
   static int isInit = 0;
@@ -244,7 +251,14 @@
 */
 int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
 #ifndef SQLITE_MUTEX_NOOP
-  sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
+  sqlite3_mutex *mutex;
+#endif
+#ifndef SQLITE_OMIT_AUTOINIT
+  int rc = sqlite3_initialize();
+  if( rc ) return rc;
+#endif
+#ifndef SQLITE_MUTEX_NOOP
+  mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
 #endif
   sqlite3_vfs_find(0);  /* Make sure we are initialized */
   sqlite3_mutex_enter(mutex);
diff --git a/src/os_os2.c b/src/os_os2.c
index a20de20..827bb53 100644
--- a/src/os_os2.c
+++ b/src/os_os2.c
@@ -12,7 +12,7 @@
 **
 ** This file contains code that is specific to OS/2.
 **
-** $Id: os_os2.c,v 1.42 2008/06/12 12:38:10 drh Exp $
+** $Id: os_os2.c,v 1.43 2008/06/13 18:24:27 drh Exp $
 */
 
 #include "sqliteInt.h"
@@ -1073,4 +1073,11 @@
   return &os2Vfs;
 }
 
+/*
+** Initialize and deinitialize the operating system interface.
+** These are stubs for now - populate with real code later...
+*/
+int sqlite3_os_init(void){ return SQLITE_OK; }
+int sqlite3_os_end(void){ return SQLITE_OK; }
+
 #endif /* OS_OS2 */
diff --git a/src/os_unix.c b/src/os_unix.c
index 63e1950..9b55339 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -12,7 +12,7 @@
 **
 ** This file contains code that is specific to Unix systems.
 **
-** $Id: os_unix.c,v 1.186 2008/06/06 15:49:30 danielk1977 Exp $
+** $Id: os_unix.c,v 1.187 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 #if OS_UNIX              /* This file is used on unix only */
@@ -2810,5 +2810,13 @@
   
   return &unixVfs;
 }
+
+/*
+** Initialize and deinitialize the operating system interface.
+** These are stubs for now - populate with real code later...
+*/
+int sqlite3_os_init(void){ return SQLITE_OK; }
+int sqlite3_os_end(void){ return SQLITE_OK; }
+
  
 #endif /* OS_UNIX */
diff --git a/src/os_win.c b/src/os_win.c
index 8f23c67..4193a16 100644
--- a/src/os_win.c
+++ b/src/os_win.c
@@ -12,7 +12,7 @@
 **
 ** This file contains code that is specific to windows.
 **
-** $Id: os_win.c,v 1.126 2008/06/06 15:49:30 danielk1977 Exp $
+** $Id: os_win.c,v 1.127 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 #if OS_WIN               /* This file is used for windows only */
@@ -1584,4 +1584,11 @@
   return &winVfs;
 }
 
+/*
+** Initialize and deinitialize the operating system interface.
+** These are stubs for now - populate with real code later...
+*/
+int sqlite3_os_init(void){ return SQLITE_OK; }
+int sqlite3_os_end(void){ return SQLITE_OK; }
+
 #endif /* OS_WIN */
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index a4648de..3e1cdcc 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -30,7 +30,7 @@
 ** the version number) and changes its name to "sqlite3.h" as
 ** part of the build process.
 **
-** @(#) $Id: sqlite.h.in,v 1.325 2008/06/12 00:07:29 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.326 2008/06/13 18:24:27 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -928,7 +928,7 @@
 ** may only be invoked prior to library initialization using
 ** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
 ** Note, however, that sqlite3_config() can be called as part of the
-** implementation of an application-defined [sqlite3_initialize()].
+** implementation of an application-defined [sqlite3_os_init()].
 **
 ** The first argument to sqlite3_config() is an integer
 ** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
@@ -937,10 +937,8 @@
 ** in the first argument.
 **
 ** When a configuration option is set, sqlite3_config() returns SQLITE_OK.
-** If the option is unknown or SQLite is unable to set the option (for
-** example if one attempts to set a threadsafe option when SQLite is
-** compiled with SQLITE_THREADSAFE=0 and is thus incapable of being
-** threadsafe) then this routine returns a non-zero [error code].
+** If the option is unknown or SQLite is unable to set the option 
+** then this routine returns a non-zero [error code].
 */
 int sqlite3_config(int, ...);
 
@@ -975,11 +973,13 @@
 ** same [prepared statement] in different threads at the same time.</dd>
 **
 ** <dt>SQLITE_CONFIG_MALLOC</dt>
-** <dd>This option takes four arguments.  The first three
+** <dd>This option takes five arguments.  The first three
 ** arguments are pointers to functions that emulate malloc(), free(),
 ** and realloc(), respectively.  The fourth argument must be a pointer to
 ** a function that returns the size of a prior allocation when handed a pointer
-** to the allocation. This option is used to replace the default memory
+** to the allocation. The fifth argument is a pointer to a function that
+** returns the rounded-up size of a memory allocation given the requested
+** allocation size.  This option is used to replace the default memory
 ** allocator with an application-defined memory allocator.</dd>
 **
 ** <dt>SQLITE_CONFIG_MEMSTATS</dt>
@@ -990,22 +990,19 @@
 **   <li> [sqlite3_memory_used()]
 **   <li> [sqlite3_memory_highwater()]
 **   <li> [sqlite3_soft_heap_limit()]
+**   <li> sqlite3_memory_status()
 **   </ul>
 ** </dd>
 ** </dl>
 */ 
-#define SQLITE_CONFIG_SINGLETHREAD       1  /* nil */
-#define SQLITE_CONFIG_MULTITHREAD        2  /* nil */
-#define SQLITE_CONFIG_SERIALIZED         3  /* nil */
-#define SQLITE_CONFIG_MALLOC             4  /* malloc, free, realloc, memsize */
-#define SQLITE_CONFIG_MEMSTATS           5  /* boolean */
+#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
+#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
+#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
+#define SQLITE_CONFIG_MALLOC        4  /* malloc,free,realloc,memsize,roundup */
+#define SQLITE_CONFIG_MEMSTATS      5  /* boolean */
 
 /* These options are to be added later.  Currently unused and undocumented. */
-#define SQLITE_CONFIG_PAGEMALLOC         6  /* malloc, free */
-#define SQLITE_CONFIG_TEMPMALLOC         7  /* malloc, free */
-#define SQLITE_CONFIG_HEAP               8  /* void*, int64 */
-#define SQLITE_CONFIG_PAGEHEAP           9  /* void*, int64 */
-#define SQLITE_CONFIG_TEMPHEAP          10  /* void*, int64 */
+#define SQLITE_CONFIG_HEAP          6  /* void*, int64, min, max, tmp */
 
 
 /*
@@ -5723,15 +5720,19 @@
 ** calling thread or is not currently allocated.  {F17033} SQLite will
 ** never do either. {END}
 **
+** If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
+** sqlite3_mutex_leave() is a NULL pointer, then all three routines
+** behave as no-ops.
+**
 ** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
 */
-int sqlite3_mutex_init();
+int sqlite3_mutex_init(void);
 sqlite3_mutex *sqlite3_mutex_alloc(int);
 void sqlite3_mutex_free(sqlite3_mutex*);
 void sqlite3_mutex_enter(sqlite3_mutex*);
 int sqlite3_mutex_try(sqlite3_mutex*);
 void sqlite3_mutex_leave(sqlite3_mutex*);
-int sqlite_mutex_end();
+int sqlite3_mutex_end(void);
 
 /*
 ** CAPI3REF: Mutex Verifcation Routines {F17080}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 0a3c2a3..d2cb424 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.707 2008/06/06 15:04:37 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.708 2008/06/13 18:24:27 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1732,6 +1732,24 @@
 } InitData;
 
 /*
+** Structure containing global configuration data for the SQLite library.
+*/
+struct Sqlite3Config {
+  void *(*xMalloc)(int);            /* Low-level malloc() */
+  void *(*xRealloc)(void*,int);     /* Low-level realloc() */
+  void (*xFree)(void*);             /* Low-level free() */
+  int (*xMemsize)(void*);           /* Return size of an allocation */
+  int (*xRoundup)(int);             /* Size of allocation given request */
+  void *pHeap;                      /* Heap storage space */
+  sqlite3_int64 nHeap;              /* Size of pHeap[] */
+  int mnReq, mxReq;                 /* Min and max memory request sizes */
+  int nTemp;                        /* Part of pHeap for temporary allos */
+  int bMemstat;                     /* True to enable memory status */
+  int bCoreMutex;                   /* True to enable core mutexing */
+  int bFullMutex;                   /* True to enable full mutexing */
+};
+
+/*
 ** Assuming zIn points to the first byte of a UTF-8 character,
 ** advance zIn to point to the first byte of the next UTF-8 character.
 */
@@ -1763,6 +1781,7 @@
 int sqlite3StrNICmp(const char *, const char *, int);
 int sqlite3IsNumber(const char*, int*, u8);
 
+int sqlite3MallocInit(void);
 void *sqlite3MallocZero(unsigned);
 void *sqlite3DbMallocZero(sqlite3*, unsigned);
 void *sqlite3DbMallocRaw(sqlite3*, unsigned);
@@ -2060,6 +2079,7 @@
 void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
 #ifndef SQLITE_AMALGAMATION
 extern const unsigned char sqlite3UpperToLower[];
+extern struct Sqlite3Config sqlite3Config;
 #endif
 void sqlite3RootPageMoved(Db*, int, int);
 void sqlite3Reindex(Parse*, Token*, Token*);
diff --git a/src/util.c b/src/util.c
index 234a7fa..2ad1417 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,7 +14,7 @@
 ** This file contains functions for allocating memory, comparing
 ** strings, and stuff like that.
 **
-** $Id: util.c,v 1.231 2008/06/12 02:16:45 shane Exp $
+** $Id: util.c,v 1.232 2008/06/13 18:24:27 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -150,46 +150,7 @@
   }
 }
 
-/* An array to map all upper-case characters into their corresponding
-** lower-case character. 
-*/
-const unsigned char sqlite3UpperToLower[] = {
-#ifdef SQLITE_ASCII
-      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
-     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
-     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
-     54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
-    104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
-    122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
-    108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
-    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
-    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
-    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
-    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
-    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
-    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
-    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
-    252,253,254,255
-#endif
-#ifdef SQLITE_EBCDIC
-      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, /* 0x */
-     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
-     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
-     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
-     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
-     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
-     96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */
-    112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */
-    128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
-    144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */
-    160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
-    176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
-    192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
-    208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
-    224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */
-    239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */
-#endif
-};
+/* Convenient short-hand */
 #define UpperToLower sqlite3UpperToLower
 
 /*