Main Page | Directories | File List

tclsqlite.c

00001 /*
00002 ** 2001 September 15
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 ** A TCL Interface to SQLite
00013 **
00014 ** $Id: tclsqlite.c,v 1.59.2.1 2004/06/19 11:57:40 drh Exp $
00015 */
00016 #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
00017 
00018 #include "sqliteInt.h"
00019 #include "tcl.h"
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <assert.h>
00023 
00024 /*
00025 ** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
00026 ** have to do a translation when going between the two.  Set the 
00027 ** UTF_TRANSLATION_NEEDED macro to indicate that we need to do
00028 ** this translation.  
00029 */
00030 #if defined(TCL_UTF_MAX) && !defined(SQLITE_UTF8)
00031 # define UTF_TRANSLATION_NEEDED 1
00032 #endif
00033 
00034 /*
00035 ** New SQL functions can be created as TCL scripts.  Each such function
00036 ** is described by an instance of the following structure.
00037 */
00038 typedef struct SqlFunc SqlFunc;
00039 struct SqlFunc {
00040   Tcl_Interp *interp;   /* The TCL interpret to execute the function */
00041   char *zScript;        /* The script to be run */
00042   SqlFunc *pNext;       /* Next function on the list of them all */
00043 };
00044 
00045 /*
00046 ** There is one instance of this structure for each SQLite database
00047 ** that has been opened by the SQLite TCL interface.
00048 */
00049 typedef struct SqliteDb SqliteDb;
00050 struct SqliteDb {
00051   sqlite *db;           /* The "real" database structure */
00052   Tcl_Interp *interp;   /* The interpreter used for this database */
00053   char *zBusy;          /* The busy callback routine */
00054   char *zCommit;        /* The commit hook callback routine */
00055   char *zTrace;         /* The trace callback routine */
00056   char *zProgress;      /* The progress callback routine */
00057   char *zAuth;          /* The authorization callback routine */
00058   SqlFunc *pFunc;       /* List of SQL functions */
00059   int rc;               /* Return code of most recent sqlite_exec() */
00060 };
00061 
00062 /*
00063 ** An instance of this structure passes information thru the sqlite
00064 ** logic from the original TCL command into the callback routine.
00065 */
00066 typedef struct CallbackData CallbackData;
00067 struct CallbackData {
00068   Tcl_Interp *interp;       /* The TCL interpreter */
00069   char *zArray;             /* The array into which data is written */
00070   Tcl_Obj *pCode;           /* The code to execute for each row */
00071   int once;                 /* Set for first callback only */
00072   int tcl_rc;               /* Return code from TCL script */
00073   int nColName;             /* Number of entries in the azColName[] array */
00074   char **azColName;         /* Column names translated to UTF-8 */
00075 };
00076 
00077 #ifdef UTF_TRANSLATION_NEEDED
00078 /*
00079 ** Called for each row of the result.
00080 **
00081 ** This version is used when TCL expects UTF-8 data but the database
00082 ** uses the ISO8859 format.  A translation must occur from ISO8859 into
00083 ** UTF-8.
00084 */
00085 static int DbEvalCallback(
00086   void *clientData,      /* An instance of CallbackData */
00087   int nCol,              /* Number of columns in the result */
00088   char ** azCol,         /* Data for each column */
00089   char ** azN            /* Name for each column */
00090 ){
00091   CallbackData *cbData = (CallbackData*)clientData;
00092   int i, rc;
00093   Tcl_DString dCol;
00094   Tcl_DStringInit(&dCol);
00095   if( cbData->azColName==0 ){
00096     assert( cbData->once );
00097     cbData->once = 0;
00098     if( cbData->zArray[0] ){
00099       Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0);
00100     }
00101     cbData->azColName = malloc( nCol*sizeof(char*) );
00102     if( cbData->azColName==0 ){ return 1; }
00103     cbData->nColName = nCol;
00104     for(i=0; i<nCol; i++){
00105       Tcl_ExternalToUtfDString(NULL, azN[i], -1, &dCol);
00106       cbData->azColName[i] = malloc( Tcl_DStringLength(&dCol) + 1 );
00107       if( cbData->azColName[i] ){
00108         strcpy(cbData->azColName[i], Tcl_DStringValue(&dCol));
00109       }else{
00110         return 1;
00111       }
00112       if( cbData->zArray[0] ){
00113         Tcl_SetVar2(cbData->interp, cbData->zArray, "*",
00114              Tcl_DStringValue(&dCol), TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
00115         if( azN[nCol]!=0 ){
00116           Tcl_DString dType;
00117           Tcl_DStringInit(&dType);
00118           Tcl_DStringAppend(&dType, "typeof:", -1);
00119           Tcl_DStringAppend(&dType, Tcl_DStringValue(&dCol), -1);
00120           Tcl_DStringFree(&dCol);
00121           Tcl_ExternalToUtfDString(NULL, azN[i+nCol], -1, &dCol);
00122           Tcl_SetVar2(cbData->interp, cbData->zArray, 
00123                Tcl_DStringValue(&dType), Tcl_DStringValue(&dCol),
00124                TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
00125           Tcl_DStringFree(&dType);
00126         }
00127       }
00128       
00129       Tcl_DStringFree(&dCol);
00130     }
00131   }
00132   if( azCol!=0 ){
00133     if( cbData->zArray[0] ){
00134       for(i=0; i<nCol; i++){
00135         char *z = azCol[i];
00136         if( z==0 ) z = "";
00137         Tcl_DStringInit(&dCol);
00138         Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
00139         Tcl_SetVar2(cbData->interp, cbData->zArray, cbData->azColName[i], 
00140               Tcl_DStringValue(&dCol), 0);
00141         Tcl_DStringFree(&dCol);
00142       }
00143     }else{
00144       for(i=0; i<nCol; i++){
00145         char *z = azCol[i];
00146         if( z==0 ) z = "";
00147         Tcl_DStringInit(&dCol);
00148         Tcl_ExternalToUtfDString(NULL, z, -1, &dCol);
00149         Tcl_SetVar(cbData->interp, cbData->azColName[i],
00150                    Tcl_DStringValue(&dCol), 0);
00151         Tcl_DStringFree(&dCol);
00152       }
00153     }
00154   }
00155   rc = Tcl_EvalObj(cbData->interp, cbData->pCode);
00156   if( rc==TCL_CONTINUE ) rc = TCL_OK;
00157   cbData->tcl_rc = rc;
00158   return rc!=TCL_OK;
00159 }
00160 #endif /* UTF_TRANSLATION_NEEDED */
00161 
00162 #ifndef UTF_TRANSLATION_NEEDED
00163 /*
00164 ** Called for each row of the result.
00165 **
00166 ** This version is used when either of the following is true:
00167 **
00168 **    (1) This version of TCL uses UTF-8 and the data in the
00169 **        SQLite database is already in the UTF-8 format.
00170 **
00171 **    (2) This version of TCL uses ISO8859 and the data in the
00172 **        SQLite database is already in the ISO8859 format.
00173 */
00174 static int DbEvalCallback(
00175   void *clientData,      /* An instance of CallbackData */
00176   int nCol,              /* Number of columns in the result */
00177   char ** azCol,         /* Data for each column */
00178   char ** azN            /* Name for each column */
00179 ){
00180   CallbackData *cbData = (CallbackData*)clientData;
00181   int i, rc;
00182   if( azCol==0 || (cbData->once && cbData->zArray[0]) ){
00183     Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0);
00184     for(i=0; i<nCol; i++){
00185       Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i],
00186          TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
00187       if( azN[nCol] ){
00188         char *z = sqlite_mprintf("typeof:%s", azN[i]);
00189         Tcl_SetVar2(cbData->interp, cbData->zArray, z, azN[i+nCol],
00190            TCL_LIST_ELEMENT|TCL_APPEND_VALUE);
00191         sqlite_freemem(z);
00192       }
00193     }
00194     cbData->once = 0;
00195   }
00196   if( azCol!=0 ){
00197     if( cbData->zArray[0] ){
00198       for(i=0; i<nCol; i++){
00199         char *z = azCol[i];
00200         if( z==0 ) z = "";
00201         Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], z, 0);
00202       }
00203     }else{
00204       for(i=0; i<nCol; i++){
00205         char *z = azCol[i];
00206         if( z==0 ) z = "";
00207         Tcl_SetVar(cbData->interp, azN[i], z, 0);
00208       }
00209     }
00210   }
00211   rc = Tcl_EvalObj(cbData->interp, cbData->pCode);
00212   if( rc==TCL_CONTINUE ) rc = TCL_OK;
00213   cbData->tcl_rc = rc;
00214   return rc!=TCL_OK;
00215 }
00216 #endif
00217 
00218 /*
00219 ** This is an alternative callback for database queries.  Instead
00220 ** of invoking a TCL script to handle the result, this callback just
00221 ** appends each column of the result to a list.  After the query
00222 ** is complete, the list is returned.
00223 */
00224 static int DbEvalCallback2(
00225   void *clientData,      /* An instance of CallbackData */
00226   int nCol,              /* Number of columns in the result */
00227   char ** azCol,         /* Data for each column */
00228   char ** azN            /* Name for each column */
00229 ){
00230   Tcl_Obj *pList = (Tcl_Obj*)clientData;
00231   int i;
00232   if( azCol==0 ) return 0;
00233   for(i=0; i<nCol; i++){
00234     Tcl_Obj *pElem;
00235     if( azCol[i] && *azCol[i] ){
00236 #ifdef UTF_TRANSLATION_NEEDED
00237       Tcl_DString dCol;
00238       Tcl_DStringInit(&dCol);
00239       Tcl_ExternalToUtfDString(NULL, azCol[i], -1, &dCol);
00240       pElem = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1);
00241       Tcl_DStringFree(&dCol);
00242 #else
00243       pElem = Tcl_NewStringObj(azCol[i], -1);
00244 #endif
00245     }else{
00246       pElem = Tcl_NewObj();
00247     }
00248     Tcl_ListObjAppendElement(0, pList, pElem);
00249   }
00250   return 0;
00251 }
00252 
00253 /*
00254 ** This is a second alternative callback for database queries.  A the
00255 ** first column of the first row of the result is made the TCL result.
00256 */
00257 static int DbEvalCallback3(
00258   void *clientData,      /* An instance of CallbackData */
00259   int nCol,              /* Number of columns in the result */
00260   char ** azCol,         /* Data for each column */
00261   char ** azN            /* Name for each column */
00262 ){
00263   Tcl_Interp *interp = (Tcl_Interp*)clientData;
00264   Tcl_Obj *pElem;
00265   if( azCol==0 ) return 1;
00266   if( nCol==0 ) return 1;
00267 #ifdef UTF_TRANSLATION_NEEDED
00268   {
00269     Tcl_DString dCol;
00270     Tcl_DStringInit(&dCol);
00271     Tcl_ExternalToUtfDString(NULL, azCol[0], -1, &dCol);
00272     pElem = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1);
00273     Tcl_DStringFree(&dCol);
00274   }
00275 #else
00276   pElem = Tcl_NewStringObj(azCol[0], -1);
00277 #endif
00278   Tcl_SetObjResult(interp, pElem);
00279   return 1;
00280 }
00281 
00282 /*
00283 ** Called when the command is deleted.
00284 */
00285 static void DbDeleteCmd(void *db){
00286   SqliteDb *pDb = (SqliteDb*)db;
00287   sqlite_close(pDb->db);
00288   while( pDb->pFunc ){
00289     SqlFunc *pFunc = pDb->pFunc;
00290     pDb->pFunc = pFunc->pNext;
00291     Tcl_Free((char*)pFunc);
00292   }
00293   if( pDb->zBusy ){
00294     Tcl_Free(pDb->zBusy);
00295   }
00296   if( pDb->zTrace ){
00297     Tcl_Free(pDb->zTrace);
00298   }
00299   if( pDb->zAuth ){
00300     Tcl_Free(pDb->zAuth);
00301   }
00302   Tcl_Free((char*)pDb);
00303 }
00304 
00305 /*
00306 ** This routine is called when a database file is locked while trying
00307 ** to execute SQL.
00308 */
00309 static int DbBusyHandler(void *cd, const char *zTable, int nTries){
00310   SqliteDb *pDb = (SqliteDb*)cd;
00311   int rc;
00312   char zVal[30];
00313   char *zCmd;
00314   Tcl_DString cmd;
00315 
00316   Tcl_DStringInit(&cmd);
00317   Tcl_DStringAppend(&cmd, pDb->zBusy, -1);
00318   Tcl_DStringAppendElement(&cmd, zTable);
00319   sprintf(zVal, " %d", nTries);
00320   Tcl_DStringAppend(&cmd, zVal, -1);
00321   zCmd = Tcl_DStringValue(&cmd);
00322   rc = Tcl_Eval(pDb->interp, zCmd);
00323   Tcl_DStringFree(&cmd);
00324   if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
00325     return 0;
00326   }
00327   return 1;
00328 }
00329 
00330 /*
00331 ** This routine is invoked as the 'progress callback' for the database.
00332 */
00333 static int DbProgressHandler(void *cd){
00334   SqliteDb *pDb = (SqliteDb*)cd;
00335   int rc;
00336 
00337   assert( pDb->zProgress );
00338   rc = Tcl_Eval(pDb->interp, pDb->zProgress);
00339   if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
00340     return 1;
00341   }
00342   return 0;
00343 }
00344 
00345 /*
00346 ** This routine is called by the SQLite trace handler whenever a new
00347 ** block of SQL is executed.  The TCL script in pDb->zTrace is executed.
00348 */
00349 static void DbTraceHandler(void *cd, const char *zSql){
00350   SqliteDb *pDb = (SqliteDb*)cd;
00351   Tcl_DString str;
00352 
00353   Tcl_DStringInit(&str);
00354   Tcl_DStringAppend(&str, pDb->zTrace, -1);
00355   Tcl_DStringAppendElement(&str, zSql);
00356   Tcl_Eval(pDb->interp, Tcl_DStringValue(&str));
00357   Tcl_DStringFree(&str);
00358   Tcl_ResetResult(pDb->interp);
00359 }
00360 
00361 /*
00362 ** This routine is called when a transaction is committed.  The
00363 ** TCL script in pDb->zCommit is executed.  If it returns non-zero or
00364 ** if it throws an exception, the transaction is rolled back instead
00365 ** of being committed.
00366 */
00367 static int DbCommitHandler(void *cd){
00368   SqliteDb *pDb = (SqliteDb*)cd;
00369   int rc;
00370 
00371   rc = Tcl_Eval(pDb->interp, pDb->zCommit);
00372   if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
00373     return 1;
00374   }
00375   return 0;
00376 }
00377 
00378 /*
00379 ** This routine is called to evaluate an SQL function implemented
00380 ** using TCL script.
00381 */
00382 static void tclSqlFunc(sqlite_func *context, int argc, const char **argv){
00383   SqlFunc *p = sqlite_user_data(context);
00384   Tcl_DString cmd;
00385   int i;
00386   int rc;
00387 
00388   Tcl_DStringInit(&cmd);
00389   Tcl_DStringAppend(&cmd, p->zScript, -1);
00390   for(i=0; i<argc; i++){
00391     Tcl_DStringAppendElement(&cmd, argv[i] ? argv[i] : "");
00392   }
00393   rc = Tcl_Eval(p->interp, Tcl_DStringValue(&cmd));
00394   if( rc ){
00395     sqlite_set_result_error(context, Tcl_GetStringResult(p->interp), -1); 
00396   }else{
00397     sqlite_set_result_string(context, Tcl_GetStringResult(p->interp), -1);
00398   }
00399 }
00400 #ifndef SQLITE_OMIT_AUTHORIZATION
00401 /*
00402 ** This is the authentication function.  It appends the authentication
00403 ** type code and the two arguments to zCmd[] then invokes the result
00404 ** on the interpreter.  The reply is examined to determine if the
00405 ** authentication fails or succeeds.
00406 */
00407 static int auth_callback(
00408   void *pArg,
00409   int code,
00410   const char *zArg1,
00411   const char *zArg2,
00412   const char *zArg3,
00413   const char *zArg4
00414 ){
00415   char *zCode;
00416   Tcl_DString str;
00417   int rc;
00418   const char *zReply;
00419   SqliteDb *pDb = (SqliteDb*)pArg;
00420 
00421   switch( code ){
00422     case SQLITE_COPY              : zCode="SQLITE_COPY"; break;
00423     case SQLITE_CREATE_INDEX      : zCode="SQLITE_CREATE_INDEX"; break;
00424     case SQLITE_CREATE_TABLE      : zCode="SQLITE_CREATE_TABLE"; break;
00425     case SQLITE_CREATE_TEMP_INDEX : zCode="SQLITE_CREATE_TEMP_INDEX"; break;
00426     case SQLITE_CREATE_TEMP_TABLE : zCode="SQLITE_CREATE_TEMP_TABLE"; break;
00427     case SQLITE_CREATE_TEMP_TRIGGER: zCode="SQLITE_CREATE_TEMP_TRIGGER"; break;
00428     case SQLITE_CREATE_TEMP_VIEW  : zCode="SQLITE_CREATE_TEMP_VIEW"; break;
00429     case SQLITE_CREATE_TRIGGER    : zCode="SQLITE_CREATE_TRIGGER"; break;
00430     case SQLITE_CREATE_VIEW       : zCode="SQLITE_CREATE_VIEW"; break;
00431     case SQLITE_DELETE            : zCode="SQLITE_DELETE"; break;
00432     case SQLITE_DROP_INDEX        : zCode="SQLITE_DROP_INDEX"; break;
00433     case SQLITE_DROP_TABLE        : zCode="SQLITE_DROP_TABLE"; break;
00434     case SQLITE_DROP_TEMP_INDEX   : zCode="SQLITE_DROP_TEMP_INDEX"; break;
00435     case SQLITE_DROP_TEMP_TABLE   : zCode="SQLITE_DROP_TEMP_TABLE"; break;
00436     case SQLITE_DROP_TEMP_TRIGGER : zCode="SQLITE_DROP_TEMP_TRIGGER"; break;
00437     case SQLITE_DROP_TEMP_VIEW    : zCode="SQLITE_DROP_TEMP_VIEW"; break;
00438     case SQLITE_DROP_TRIGGER      : zCode="SQLITE_DROP_TRIGGER"; break;
00439     case SQLITE_DROP_VIEW         : zCode="SQLITE_DROP_VIEW"; break;
00440     case SQLITE_INSERT            : zCode="SQLITE_INSERT"; break;
00441     case SQLITE_PRAGMA            : zCode="SQLITE_PRAGMA"; break;
00442     case SQLITE_READ              : zCode="SQLITE_READ"; break;
00443     case SQLITE_SELECT            : zCode="SQLITE_SELECT"; break;
00444     case SQLITE_TRANSACTION       : zCode="SQLITE_TRANSACTION"; break;
00445     case SQLITE_UPDATE            : zCode="SQLITE_UPDATE"; break;
00446     case SQLITE_ATTACH            : zCode="SQLITE_ATTACH"; break;
00447     case SQLITE_DETACH            : zCode="SQLITE_DETACH"; break;
00448     default                       : zCode="????"; break;
00449   }
00450   Tcl_DStringInit(&str);
00451   Tcl_DStringAppend(&str, pDb->zAuth, -1);
00452   Tcl_DStringAppendElement(&str, zCode);
00453   Tcl_DStringAppendElement(&str, zArg1 ? zArg1 : "");
00454   Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : "");
00455   Tcl_DStringAppendElement(&str, zArg3 ? zArg3 : "");
00456   Tcl_DStringAppendElement(&str, zArg4 ? zArg4 : "");
00457   rc = Tcl_GlobalEval(pDb->interp, Tcl_DStringValue(&str));
00458   Tcl_DStringFree(&str);
00459   zReply = Tcl_GetStringResult(pDb->interp);
00460   if( strcmp(zReply,"SQLITE_OK")==0 ){
00461     rc = SQLITE_OK;
00462   }else if( strcmp(zReply,"SQLITE_DENY")==0 ){
00463     rc = SQLITE_DENY;
00464   }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){
00465     rc = SQLITE_IGNORE;
00466   }else{
00467     rc = 999;
00468   }
00469   return rc;
00470 }
00471 #endif /* SQLITE_OMIT_AUTHORIZATION */
00472 
00473 /*
00474 ** The "sqlite" command below creates a new Tcl command for each
00475 ** connection it opens to an SQLite database.  This routine is invoked
00476 ** whenever one of those connection-specific commands is executed
00477 ** in Tcl.  For example, if you run Tcl code like this:
00478 **
00479 **       sqlite db1  "my_database"
00480 **       db1 close
00481 **
00482 ** The first command opens a connection to the "my_database" database
00483 ** and calls that connection "db1".  The second command causes this
00484 ** subroutine to be invoked.
00485 */
00486 static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
00487   SqliteDb *pDb = (SqliteDb*)cd;
00488   int choice;
00489   int rc = TCL_OK;
00490   static const char *DB_strs[] = {
00491     "authorizer",         "busy",                   "changes",
00492     "close",              "commit_hook",            "complete",
00493     "errorcode",          "eval",                   "function",
00494     "last_insert_rowid",  "last_statement_changes", "onecolumn",
00495     "progress",           "rekey",                  "timeout",
00496     "trace",
00497     0                    
00498   };
00499   enum DB_enum {
00500     DB_AUTHORIZER,        DB_BUSY,                   DB_CHANGES,
00501     DB_CLOSE,             DB_COMMIT_HOOK,            DB_COMPLETE,
00502     DB_ERRORCODE,         DB_EVAL,                   DB_FUNCTION,
00503     DB_LAST_INSERT_ROWID, DB_LAST_STATEMENT_CHANGES, DB_ONECOLUMN,        
00504     DB_PROGRESS,          DB_REKEY,                  DB_TIMEOUT,
00505     DB_TRACE
00506   };
00507 
00508   if( objc<2 ){
00509     Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
00510     return TCL_ERROR;
00511   }
00512   if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){
00513     return TCL_ERROR;
00514   }
00515 
00516   switch( (enum DB_enum)choice ){
00517 
00518   /*    $db authorizer ?CALLBACK?
00519   **
00520   ** Invoke the given callback to authorize each SQL operation as it is
00521   ** compiled.  5 arguments are appended to the callback before it is
00522   ** invoked:
00523   **
00524   **   (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...)
00525   **   (2) First descriptive name (depends on authorization type)
00526   **   (3) Second descriptive name
00527   **   (4) Name of the database (ex: "main", "temp")
00528   **   (5) Name of trigger that is doing the access
00529   **
00530   ** The callback should return on of the following strings: SQLITE_OK,
00531   ** SQLITE_IGNORE, or SQLITE_DENY.  Any other return value is an error.
00532   **
00533   ** If this method is invoked with no arguments, the current authorization
00534   ** callback string is returned.
00535   */
00536   case DB_AUTHORIZER: {
00537     if( objc>3 ){
00538       Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
00539     }else if( objc==2 ){
00540       if( pDb->zAuth ){
00541         Tcl_AppendResult(interp, pDb->zAuth, 0);
00542       }
00543     }else{
00544       char *zAuth;
00545       int len;
00546       if( pDb->zAuth ){
00547         Tcl_Free(pDb->zAuth);
00548       }
00549       zAuth = Tcl_GetStringFromObj(objv[2], &len);
00550       if( zAuth && len>0 ){
00551         pDb->zAuth = Tcl_Alloc( len + 1 );
00552         strcpy(pDb->zAuth, zAuth);
00553       }else{
00554         pDb->zAuth = 0;
00555       }
00556 #ifndef SQLITE_OMIT_AUTHORIZATION
00557       if( pDb->zAuth ){
00558         pDb->interp = interp;
00559         sqlite_set_authorizer(pDb->db, auth_callback, pDb);
00560       }else{
00561         sqlite_set_authorizer(pDb->db, 0, 0);
00562       }
00563 #endif
00564     }
00565     break;
00566   }
00567 
00568   /*    $db busy ?CALLBACK?
00569   **
00570   ** Invoke the given callback if an SQL statement attempts to open
00571   ** a locked database file.
00572   */
00573   case DB_BUSY: {
00574     if( objc>3 ){
00575       Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK");
00576       return TCL_ERROR;
00577     }else if( objc==2 ){
00578       if( pDb->zBusy ){
00579         Tcl_AppendResult(interp, pDb->zBusy, 0);
00580       }
00581     }else{
00582       char *zBusy;
00583       int len;
00584       if( pDb->zBusy ){
00585         Tcl_Free(pDb->zBusy);
00586       }
00587       zBusy = Tcl_GetStringFromObj(objv[2], &len);
00588       if( zBusy && len>0 ){
00589         pDb->zBusy = Tcl_Alloc( len + 1 );
00590         strcpy(pDb->zBusy, zBusy);
00591       }else{
00592         pDb->zBusy = 0;
00593       }
00594       if( pDb->zBusy ){
00595         pDb->interp = interp;
00596         sqlite_busy_handler(pDb->db, DbBusyHandler, pDb);
00597       }else{
00598         sqlite_busy_handler(pDb->db, 0, 0);
00599       }
00600     }
00601     break;
00602   }
00603 
00604   /*    $db progress ?N CALLBACK?
00605   ** 
00606   ** Invoke the given callback every N virtual machine opcodes while executing
00607   ** queries.
00608   */
00609   case DB_PROGRESS: {
00610     if( objc==2 ){
00611       if( pDb->zProgress ){
00612         Tcl_AppendResult(interp, pDb->zProgress, 0);
00613       }
00614     }else if( objc==4 ){
00615       char *zProgress;
00616       int len;
00617       int N;
00618       if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){
00619         return TCL_ERROR;
00620       };
00621       if( pDb->zProgress ){
00622         Tcl_Free(pDb->zProgress);
00623       }
00624       zProgress = Tcl_GetStringFromObj(objv[3], &len);
00625       if( zProgress && len>0 ){
00626         pDb->zProgress = Tcl_Alloc( len + 1 );
00627         strcpy(pDb->zProgress, zProgress);
00628       }else{
00629         pDb->zProgress = 0;
00630       }
00631 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
00632       if( pDb->zProgress ){
00633         pDb->interp = interp;
00634         sqlite_progress_handler(pDb->db, N, DbProgressHandler, pDb);
00635       }else{
00636         sqlite_progress_handler(pDb->db, 0, 0, 0);
00637       }
00638 #endif
00639     }else{
00640       Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK");
00641       return TCL_ERROR;
00642     }
00643     break;
00644   }
00645 
00646   /*
00647   **     $db changes
00648   **
00649   ** Return the number of rows that were modified, inserted, or deleted by
00650   ** the most recent "eval".
00651   */
00652   case DB_CHANGES: {
00653     Tcl_Obj *pResult;
00654     int nChange;
00655     if( objc!=2 ){
00656       Tcl_WrongNumArgs(interp, 2, objv, "");
00657       return TCL_ERROR;
00658     }
00659     nChange = sqlite_changes(pDb->db);
00660     pResult = Tcl_GetObjResult(interp);
00661     Tcl_SetIntObj(pResult, nChange);
00662     break;
00663   }
00664 
00665   /*
00666   **     $db last_statement_changes
00667   **
00668   ** Return the number of rows that were modified, inserted, or deleted by
00669   ** the last statment to complete execution (excluding changes due to
00670   ** triggers)
00671   */
00672   case DB_LAST_STATEMENT_CHANGES: {
00673     Tcl_Obj *pResult;
00674     int lsChange;
00675     if( objc!=2 ){
00676       Tcl_WrongNumArgs(interp, 2, objv, "");
00677       return TCL_ERROR;
00678     }
00679     lsChange = sqlite_last_statement_changes(pDb->db);
00680     pResult = Tcl_GetObjResult(interp);
00681     Tcl_SetIntObj(pResult, lsChange);
00682     break;
00683   }
00684 
00685   /*    $db close
00686   **
00687   ** Shutdown the database
00688   */
00689   case DB_CLOSE: {
00690     Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0));
00691     break;
00692   }
00693 
00694   /*    $db commit_hook ?CALLBACK?
00695   **
00696   ** Invoke the given callback just before committing every SQL transaction.
00697   ** If the callback throws an exception or returns non-zero, then the
00698   ** transaction is aborted.  If CALLBACK is an empty string, the callback
00699   ** is disabled.
00700   */
00701   case DB_COMMIT_HOOK: {
00702     if( objc>3 ){
00703       Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
00704     }else if( objc==2 ){
00705       if( pDb->zCommit ){
00706         Tcl_AppendResult(interp, pDb->zCommit, 0);
00707       }
00708     }else{
00709       char *zCommit;
00710       int len;
00711       if( pDb->zCommit ){
00712         Tcl_Free(pDb->zCommit);
00713       }
00714       zCommit = Tcl_GetStringFromObj(objv[2], &len);
00715       if( zCommit && len>0 ){
00716         pDb->zCommit = Tcl_Alloc( len + 1 );
00717         strcpy(pDb->zCommit, zCommit);
00718       }else{
00719         pDb->zCommit = 0;
00720       }
00721       if( pDb->zCommit ){
00722         pDb->interp = interp;
00723         sqlite_commit_hook(pDb->db, DbCommitHandler, pDb);
00724       }else{
00725         sqlite_commit_hook(pDb->db, 0, 0);
00726       }
00727     }
00728     break;
00729   }
00730 
00731   /*    $db complete SQL
00732   **
00733   ** Return TRUE if SQL is a complete SQL statement.  Return FALSE if
00734   ** additional lines of input are needed.  This is similar to the
00735   ** built-in "info complete" command of Tcl.
00736   */
00737   case DB_COMPLETE: {
00738     Tcl_Obj *pResult;
00739     int isComplete;
00740     if( objc!=3 ){
00741       Tcl_WrongNumArgs(interp, 2, objv, "SQL");
00742       return TCL_ERROR;
00743     }
00744     isComplete = sqlite_complete( Tcl_GetStringFromObj(objv[2], 0) );
00745     pResult = Tcl_GetObjResult(interp);
00746     Tcl_SetBooleanObj(pResult, isComplete);
00747     break;
00748   }
00749 
00750   /*
00751   **    $db errorcode
00752   **
00753   ** Return the numeric error code that was returned by the most recent
00754   ** call to sqlite_exec().
00755   */
00756   case DB_ERRORCODE: {
00757     Tcl_SetObjResult(interp, Tcl_NewIntObj(pDb->rc));
00758     break;
00759   }
00760    
00761   /*
00762   **    $db eval $sql ?array {  ...code... }?
00763   **
00764   ** The SQL statement in $sql is evaluated.  For each row, the values are
00765   ** placed in elements of the array named "array" and ...code... is executed.
00766   ** If "array" and "code" are omitted, then no callback is every invoked.
00767   ** If "array" is an empty string, then the values are placed in variables
00768   ** that have the same name as the fields extracted by the query.
00769   */
00770   case DB_EVAL: {
00771     CallbackData cbData;
00772     char *zErrMsg;
00773     char *zSql;
00774 #ifdef UTF_TRANSLATION_NEEDED
00775     Tcl_DString dSql;
00776     int i;
00777 #endif
00778 
00779     if( objc!=5 && objc!=3 ){
00780       Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?");
00781       return TCL_ERROR;
00782     }
00783     pDb->interp = interp;
00784     zSql = Tcl_GetStringFromObj(objv[2], 0);
00785 #ifdef UTF_TRANSLATION_NEEDED
00786     Tcl_DStringInit(&dSql);
00787     Tcl_UtfToExternalDString(NULL, zSql, -1, &dSql);
00788     zSql = Tcl_DStringValue(&dSql);
00789 #endif
00790     Tcl_IncrRefCount(objv[2]);
00791     if( objc==5 ){
00792       cbData.interp = interp;
00793       cbData.once = 1;
00794       cbData.zArray = Tcl_GetStringFromObj(objv[3], 0);
00795       cbData.pCode = objv[4];
00796       cbData.tcl_rc = TCL_OK;
00797       cbData.nColName = 0;
00798       cbData.azColName = 0;
00799       zErrMsg = 0;
00800       Tcl_IncrRefCount(objv[3]);
00801       Tcl_IncrRefCount(objv[4]);
00802       rc = sqlite_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg);
00803       Tcl_DecrRefCount(objv[4]);
00804       Tcl_DecrRefCount(objv[3]);
00805       if( cbData.tcl_rc==TCL_BREAK ){ cbData.tcl_rc = TCL_OK; }
00806     }else{
00807       Tcl_Obj *pList = Tcl_NewObj();
00808       cbData.tcl_rc = TCL_OK;
00809       rc = sqlite_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg);
00810       Tcl_SetObjResult(interp, pList);
00811     }
00812     pDb->rc = rc;
00813     if( rc==SQLITE_ABORT ){
00814       if( zErrMsg ) free(zErrMsg);
00815       rc = cbData.tcl_rc;
00816     }else if( zErrMsg ){
00817       Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
00818       free(zErrMsg);
00819       rc = TCL_ERROR;
00820     }else if( rc!=SQLITE_OK ){
00821       Tcl_AppendResult(interp, sqlite_error_string(rc), 0);
00822       rc = TCL_ERROR;
00823     }else{
00824     }
00825     Tcl_DecrRefCount(objv[2]);
00826 #ifdef UTF_TRANSLATION_NEEDED
00827     Tcl_DStringFree(&dSql);
00828     if( objc==5 && cbData.azColName ){
00829       for(i=0; i<cbData.nColName; i++){
00830         if( cbData.azColName[i] ) free(cbData.azColName[i]);
00831       }
00832       free(cbData.azColName);
00833       cbData.azColName = 0;
00834     }
00835 #endif
00836     return rc;
00837   }
00838 
00839   /*
00840   **     $db function NAME SCRIPT
00841   **
00842   ** Create a new SQL function called NAME.  Whenever that function is
00843   ** called, invoke SCRIPT to evaluate the function.
00844   */
00845   case DB_FUNCTION: {
00846     SqlFunc *pFunc;
00847     char *zName;
00848     char *zScript;
00849     int nScript;
00850     if( objc!=4 ){
00851       Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
00852       return TCL_ERROR;
00853     }
00854     zName = Tcl_GetStringFromObj(objv[2], 0);
00855     zScript = Tcl_GetStringFromObj(objv[3], &nScript);
00856     pFunc = (SqlFunc*)Tcl_Alloc( sizeof(*pFunc) + nScript + 1 );
00857     if( pFunc==0 ) return TCL_ERROR;
00858     pFunc->interp = interp;
00859     pFunc->pNext = pDb->pFunc;
00860     pFunc->zScript = (char*)&pFunc[1];
00861     strcpy(pFunc->zScript, zScript);
00862     sqlite_create_function(pDb->db, zName, -1, tclSqlFunc, pFunc);
00863     sqlite_function_type(pDb->db, zName, SQLITE_NUMERIC);
00864     break;
00865   }
00866 
00867   /*
00868   **     $db last_insert_rowid 
00869   **
00870   ** Return an integer which is the ROWID for the most recent insert.
00871   */
00872   case DB_LAST_INSERT_ROWID: {
00873     Tcl_Obj *pResult;
00874     int rowid;
00875     if( objc!=2 ){
00876       Tcl_WrongNumArgs(interp, 2, objv, "");
00877       return TCL_ERROR;
00878     }
00879     rowid = sqlite_last_insert_rowid(pDb->db);
00880     pResult = Tcl_GetObjResult(interp);
00881     Tcl_SetIntObj(pResult, rowid);
00882     break;
00883   }
00884 
00885   /*
00886   **     $db onecolumn SQL
00887   **
00888   ** Return a single column from a single row of the given SQL query.
00889   */
00890   case DB_ONECOLUMN: {
00891     char *zSql;
00892     char *zErrMsg = 0;
00893     if( objc!=3 ){
00894       Tcl_WrongNumArgs(interp, 2, objv, "SQL");
00895       return TCL_ERROR;
00896     }
00897     zSql = Tcl_GetStringFromObj(objv[2], 0);
00898     rc = sqlite_exec(pDb->db, zSql, DbEvalCallback3, interp, &zErrMsg);
00899     if( rc==SQLITE_ABORT ){
00900       rc = SQLITE_OK;
00901     }else if( zErrMsg ){
00902       Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
00903       free(zErrMsg);
00904       rc = TCL_ERROR;
00905     }else if( rc!=SQLITE_OK ){
00906       Tcl_AppendResult(interp, sqlite_error_string(rc), 0);
00907       rc = TCL_ERROR;
00908     }
00909     break;
00910   }
00911 
00912   /*
00913   **     $db rekey KEY
00914   **
00915   ** Change the encryption key on the currently open database.
00916   */
00917   case DB_REKEY: {
00918     int nKey;
00919     void *pKey;
00920     if( objc!=3 ){
00921       Tcl_WrongNumArgs(interp, 2, objv, "KEY");
00922       return TCL_ERROR;
00923     }
00924     pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
00925 #ifdef SQLITE_HAS_CODEC
00926     rc = sqlite_rekey(pDb->db, pKey, nKey);
00927     if( rc ){
00928       Tcl_AppendResult(interp, sqlite_error_string(rc), 0);
00929       rc = TCL_ERROR;
00930     }
00931 #endif
00932     break;
00933   }
00934 
00935   /*
00936   **     $db timeout MILLESECONDS
00937   **
00938   ** Delay for the number of milliseconds specified when a file is locked.
00939   */
00940   case DB_TIMEOUT: {
00941     int ms;
00942     if( objc!=3 ){
00943       Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS");
00944       return TCL_ERROR;
00945     }
00946     if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR;
00947     sqlite_busy_timeout(pDb->db, ms);
00948     break;
00949   }
00950 
00951   /*    $db trace ?CALLBACK?
00952   **
00953   ** Make arrangements to invoke the CALLBACK routine for each SQL statement
00954   ** that is executed.  The text of the SQL is appended to CALLBACK before
00955   ** it is executed.
00956   */
00957   case DB_TRACE: {
00958     if( objc>3 ){
00959       Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
00960     }else if( objc==2 ){
00961       if( pDb->zTrace ){
00962         Tcl_AppendResult(interp, pDb->zTrace, 0);
00963       }
00964     }else{
00965       char *zTrace;
00966       int len;
00967       if( pDb->zTrace ){
00968         Tcl_Free(pDb->zTrace);
00969       }
00970       zTrace = Tcl_GetStringFromObj(objv[2], &len);
00971       if( zTrace && len>0 ){
00972         pDb->zTrace = Tcl_Alloc( len + 1 );
00973         strcpy(pDb->zTrace, zTrace);
00974       }else{
00975         pDb->zTrace = 0;
00976       }
00977       if( pDb->zTrace ){
00978         pDb->interp = interp;
00979         sqlite_trace(pDb->db, DbTraceHandler, pDb);
00980       }else{
00981         sqlite_trace(pDb->db, 0, 0);
00982       }
00983     }
00984     break;
00985   }
00986 
00987   } /* End of the SWITCH statement */
00988   return rc;
00989 }
00990 
00991 /*
00992 **   sqlite DBNAME FILENAME ?MODE? ?-key KEY?
00993 **
00994 ** This is the main Tcl command.  When the "sqlite" Tcl command is
00995 ** invoked, this routine runs to process that command.
00996 **
00997 ** The first argument, DBNAME, is an arbitrary name for a new
00998 ** database connection.  This command creates a new command named
00999 ** DBNAME that is used to control that connection.  The database
01000 ** connection is deleted when the DBNAME command is deleted.
01001 **
01002 ** The second argument is the name of the directory that contains
01003 ** the sqlite database that is to be accessed.
01004 **
01005 ** For testing purposes, we also support the following:
01006 **
01007 **  sqlite -encoding
01008 **
01009 **       Return the encoding used by LIKE and GLOB operators.  Choices
01010 **       are UTF-8 and iso8859.
01011 **
01012 **  sqlite -version
01013 **
01014 **       Return the version number of the SQLite library.
01015 **
01016 **  sqlite -tcl-uses-utf
01017 **
01018 **       Return "1" if compiled with a Tcl uses UTF-8.  Return "0" if
01019 **       not.  Used by tests to make sure the library was compiled 
01020 **       correctly.
01021 */
01022 static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
01023   int mode;
01024   SqliteDb *p;
01025   void *pKey = 0;
01026   int nKey = 0;
01027   const char *zArg;
01028   char *zErrMsg;
01029   const char *zFile;
01030   char zBuf[80];
01031   if( objc==2 ){
01032     zArg = Tcl_GetStringFromObj(objv[1], 0);
01033     if( strcmp(zArg,"-encoding")==0 ){
01034       Tcl_AppendResult(interp,sqlite_encoding,0);
01035       return TCL_OK;
01036     }
01037     if( strcmp(zArg,"-version")==0 ){
01038       Tcl_AppendResult(interp,sqlite_version,0);
01039       return TCL_OK;
01040     }
01041     if( strcmp(zArg,"-has-codec")==0 ){
01042 #ifdef SQLITE_HAS_CODEC
01043       Tcl_AppendResult(interp,"1",0);
01044 #else
01045       Tcl_AppendResult(interp,"0",0);
01046 #endif
01047       return TCL_OK;
01048     }
01049     if( strcmp(zArg,"-tcl-uses-utf")==0 ){
01050 #ifdef TCL_UTF_MAX
01051       Tcl_AppendResult(interp,"1",0);
01052 #else
01053       Tcl_AppendResult(interp,"0",0);
01054 #endif
01055       return TCL_OK;
01056     }
01057   }
01058   if( objc==5 || objc==6 ){
01059     zArg = Tcl_GetStringFromObj(objv[objc-2], 0);
01060     if( strcmp(zArg,"-key")==0 ){
01061       pKey = Tcl_GetByteArrayFromObj(objv[objc-1], &nKey);
01062       objc -= 2;
01063     }
01064   }
01065   if( objc!=3 && objc!=4 ){
01066     Tcl_WrongNumArgs(interp, 1, objv, 
01067 #ifdef SQLITE_HAS_CODEC
01068       "HANDLE FILENAME ?-key CODEC-KEY?"
01069 #else
01070       "HANDLE FILENAME ?MODE?"
01071 #endif
01072     );
01073     return TCL_ERROR;
01074   }
01075   if( objc==3 ){
01076     mode = 0666;
01077   }else if( Tcl_GetIntFromObj(interp, objv[3], &mode)!=TCL_OK ){
01078     return TCL_ERROR;
01079   }
01080   zErrMsg = 0;
01081   p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
01082   if( p==0 ){
01083     Tcl_SetResult(interp, "malloc failed", TCL_STATIC);
01084     return TCL_ERROR;
01085   }
01086   memset(p, 0, sizeof(*p));
01087   zFile = Tcl_GetStringFromObj(objv[2], 0);
01088 #ifdef SQLITE_HAS_CODEC
01089   p->db = sqlite_open_encrypted(zFile, pKey, nKey, 0, &zErrMsg);
01090 #else
01091   p->db = sqlite_open(zFile, mode, &zErrMsg);
01092 #endif
01093   if( p->db==0 ){
01094     Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
01095     Tcl_Free((char*)p);
01096     free(zErrMsg);
01097     return TCL_ERROR;
01098   }
01099   zArg = Tcl_GetStringFromObj(objv[1], 0);
01100   Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);
01101 
01102   /* The return value is the value of the sqlite* pointer
01103   */
01104   sprintf(zBuf, "%p", p->db);
01105   if( strncmp(zBuf,"0x",2) ){
01106     sprintf(zBuf, "0x%p", p->db);
01107   }
01108   Tcl_AppendResult(interp, zBuf, 0);
01109 
01110   /* If compiled with SQLITE_TEST turned on, then register the "md5sum"
01111   ** SQL function.
01112   */
01113 #ifdef SQLITE_TEST
01114   {
01115     extern void Md5_Register(sqlite*);
01116     Md5_Register(p->db);
01117    }
01118 #endif  
01119   return TCL_OK;
01120 }
01121 
01122 /*
01123 ** Provide a dummy Tcl_InitStubs if we are using this as a static
01124 ** library.
01125 */
01126 #ifndef USE_TCL_STUBS
01127 # undef  Tcl_InitStubs
01128 # define Tcl_InitStubs(a,b,c)
01129 #endif
01130 
01131 /*
01132 ** Initialize this module.
01133 **
01134 ** This Tcl module contains only a single new Tcl command named "sqlite".
01135 ** (Hence there is no namespace.  There is no point in using a namespace
01136 ** if the extension only supplies one new name!)  The "sqlite" command is
01137 ** used to open a new SQLite database.  See the DbMain() routine above
01138 ** for additional information.
01139 */
01140 int Sqlite_Init(Tcl_Interp *interp){
01141   Tcl_InitStubs(interp, "8.0", 0);
01142   Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
01143   Tcl_PkgProvide(interp, "sqlite", "2.0");
01144   return TCL_OK;
01145 }
01146 int Tclsqlite_Init(Tcl_Interp *interp){
01147   Tcl_InitStubs(interp, "8.0", 0);
01148   Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
01149   Tcl_PkgProvide(interp, "sqlite", "2.0");
01150   return TCL_OK;
01151 }
01152 int Sqlite_SafeInit(Tcl_Interp *interp){
01153   return TCL_OK;
01154 }
01155 int Tclsqlite_SafeInit(Tcl_Interp *interp){
01156   return TCL_OK;
01157 }
01158 
01159 #if 0
01160 /*
01161 ** If compiled using mktclapp, this routine runs to initialize
01162 ** everything.
01163 */
01164 int Et_AppInit(Tcl_Interp *interp){
01165   return Sqlite_Init(interp);
01166 }
01167 #endif
01168 /***************************************************************************
01169 ** The remaining code is only included if the TCLSH macro is defined to
01170 ** be an integer greater than 0
01171 */
01172 #if defined(TCLSH) && TCLSH>0
01173 
01174 /*
01175 ** If the macro TCLSH is defined and is one, then put in code for the
01176 ** "main" routine that implement a interactive shell into which the user
01177 ** can type TCL commands.
01178 */
01179 #if TCLSH==1
01180 static char zMainloop[] =
01181   "set line {}\n"
01182   "while {![eof stdin]} {\n"
01183     "if {$line!=\"\"} {\n"
01184       "puts -nonewline \"> \"\n"
01185     "} else {\n"
01186       "puts -nonewline \"% \"\n"
01187     "}\n"
01188     "flush stdout\n"
01189     "append line [gets stdin]\n"
01190     "if {[info complete $line]} {\n"
01191       "if {[catch {uplevel #0 $line} result]} {\n"
01192         "puts stderr \"Error: $result\"\n"
01193       "} elseif {$result!=\"\"} {\n"
01194         "puts $result\n"
01195       "}\n"
01196       "set line {}\n"
01197     "} else {\n"
01198       "append line \\n\n"
01199     "}\n"
01200   "}\n"
01201 ;
01202 #endif /* TCLSH==1 */
01203 
01204 int Libsqlite_Init( Tcl_Interp *interp) {
01205 #ifdef TCL_THREADS
01206   if (Thread_Init(interp) == TCL_ERROR) {
01207     return TCL_ERROR;
01208   }
01209 #endif
01210   Sqlite_Init(interp);
01211 #ifdef SQLITE_TEST
01212   {
01213     extern int Sqlitetest1_Init(Tcl_Interp*);
01214     extern int Sqlitetest2_Init(Tcl_Interp*);
01215     extern int Sqlitetest3_Init(Tcl_Interp*);
01216     extern int Md5_Init(Tcl_Interp*);
01217     Sqlitetest1_Init(interp);
01218     Sqlitetest2_Init(interp);
01219     Sqlitetest3_Init(interp);
01220     Md5_Init(interp);
01221     Tcl_StaticPackage(interp, "sqlite", Libsqlite_Init, Libsqlite_Init);
01222   }
01223 #endif
01224   return TCL_OK;
01225 }
01226 
01227 #define TCLSH_MAIN main   /* Needed to fake out mktclapp */
01228 #if TCLSH==1
01229 int TCLSH_MAIN(int argc, char **argv){
01230 #ifndef TCL_THREADS
01231   Tcl_Interp *interp;
01232   Tcl_FindExecutable(argv[0]);
01233   interp = Tcl_CreateInterp();
01234   Libsqlite_Init(interp);
01235   if( argc>=2 ){
01236     int i;
01237     Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
01238     Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
01239     for(i=2; i<argc; i++){
01240       Tcl_SetVar(interp, "argv", argv[i],
01241           TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
01242     }
01243     if( Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
01244       const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
01245       if( zInfo==0 ) zInfo = interp->result;
01246       fprintf(stderr,"%s: %s\n", *argv, zInfo);
01247       return TCL_ERROR;
01248     }
01249   }else{
01250     Tcl_GlobalEval(interp, zMainloop);
01251   }
01252   return 0;
01253 #else
01254   Tcl_Main(argc, argv, Libsqlite_Init);
01255 #endif /* TCL_THREADS */
01256   return 0;
01257 }
01258 #endif /* TCLSH==1 */
01259 
01260 
01261 /*
01262 ** If the macro TCLSH is set to 2, then implement a space analysis tool.
01263 */
01264 #if TCLSH==2
01265 static char zAnalysis[] = 
01266 #include "spaceanal_tcl.h"
01267 ;
01268 
01269 int main(int argc, char **argv){
01270   Tcl_Interp *interp;
01271   int i;
01272   Tcl_FindExecutable(argv[0]);
01273   interp = Tcl_CreateInterp();
01274   Libsqlite_Init(interp);
01275   Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY);
01276   Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
01277   for(i=1; i<argc; i++){
01278     Tcl_SetVar(interp, "argv", argv[i],
01279         TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
01280   }
01281   if( Tcl_GlobalEval(interp, zAnalysis)!=TCL_OK ){
01282     const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
01283     if( zInfo==0 ) zInfo = interp->result;
01284     fprintf(stderr,"%s: %s\n", *argv, zInfo);
01285     return TCL_ERROR;
01286   }
01287   return 0;
01288 }
01289 #endif /* TCLSH==2 */
01290 
01291 #endif /* TCLSH */
01292 
01293 #endif /* NO_TCL */

Generated on Sun Dec 25 12:29:52 2005 for sqlite 2.8.17 by  doxygen 1.4.2