]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
CLI regularization and code cleanup
authorlarrybr <larrybr@noemail.net>
Tue, 8 Mar 2022 01:02:37 +0000 (01:02 +0000)
committerlarrybr <larrybr@noemail.net>
Tue, 8 Mar 2022 01:02:37 +0000 (01:02 +0000)
FossilOrigin-Name: 16af0e4560349f720d4e2fbb4c08211e6a9a573c1fb4eb287d8bc2aefc3c7ce0

manifest
manifest.uuid
src/shell.c.in
src/shext_linkage.h
tool/mkshellc.tcl

index 29bc1cb75ccf9a2ea011da0639c6a4b4281f1321..8e4ca1a7ac9601a7d733cd6040324e9d6b05a58c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Sync\swith\strunk
-D 2022-03-07T19:00:25.488
+C CLI\sregularization\sand\scode\scleanup
+D 2022-03-08T01:02:37.922
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -555,8 +555,8 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
 F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
 F src/select.c 4890a3cfee0bc60ff231c3a44db37968859ab0be156983dbcc0c096109832cdd
-F src/shell.c.in 92f8c98677e6e9b192ee77927ecd2ab1af2c8e3e5daca06e52f06d451037f705
-F src/shext_linkage.h bff86090e82d1df3a6dd0c566324f38ac67cb75d6e72697d9a8a3065545b4f0c
+F src/shell.c.in 52936caf57e2765e5647c70ccc8932fe510879f0abf2c331c1e83459e7778959
+F src/shext_linkage.h 76a8deb0ffc3b5ed4396f71fd7beb6c63477457d457cab873d7e2f6469819b13
 F src/sqlite.h.in e82ac380b307659d0892f502b742f825504e78729f4edaadce946003b9c00816
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h a95cb9ed106e3d39e2118e4dcc15a14faec3fa50d0093425083d340d9dfd96e6
@@ -1883,7 +1883,7 @@ F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61
 F tool/mkopcodeh.tcl 5dab48c49a25452257494e9601702ab63adaba6bd54a9b382615fa52661c8f8c
 F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
 F tool/mkpragmatab.tcl bd07bd59d45d0f3448e123d6937e9811195f9908a51e09d774609883055bfd3d
-F tool/mkshellc.tcl 8b59d0312c708acb00b9242a2eb79cdf3a84d972c06bb09447599ebadc1d5cbf
+F tool/mkshellc.tcl 173780dab3cd26a7c58a05e401af6d2fa2d12187f349b86cec3e2cafe7526678
 F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
 F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
@@ -1949,8 +1949,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P a88983ecb7e2905219898e17d11de3598ee801c57b8ba32c51cb2790456a0e5b 0021bebc162e001b788786703ce634e7b8fcd3976f7047a5956e82140791e765
-R 2e72e0cc424e9311255d66424a9824eb
+P 1194093a58978b99c7afee08483d0590ce9aff4647a46dc9a338f022647fdb42
+R 1cbe480cc9660306a182a58b06b04872
 U larrybr
-Z d510d7fd6f6e96bbcf87e6ed60b7095d
+Z eab8f0e1073c744044f30e201854ce42
 # Remove this line to create a well-formed Fossil manifest.
index 2b431c2ffb7e1ae8b41a24fdd45ddf16941e35f7..b0eb5bb5810a9452c6271e0fa925221cce96eaaa 100644 (file)
@@ -1 +1 @@
-1194093a58978b99c7afee08483d0590ce9aff4647a46dc9a338f022647fdb42
\ No newline at end of file
+16af0e4560349f720d4e2fbb4c08211e6a9a573c1fb4eb287d8bc2aefc3c7ce0
\ No newline at end of file
index 5cd6093e2bb9fc310ba097ab9737323de9676d8a..cd2e731c106b69d7ba74ee9961ba1338c055bb9f 100644 (file)
@@ -1269,7 +1269,6 @@ typedef struct OutputModeSave{
 #define DBX(psx) (psx)->dbUser
 
 typedef struct ShellInState {
-  /* sqlite3 *db;           user database moved to ShellExState.dbUser */
   int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
   u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
   sqlite3_int64 szMax;   /* --maxsize argument to .open */
@@ -1298,27 +1297,18 @@ typedef struct ShellInState {
   /* Output mode state-keep for certain ad-hoc save/restore ops: */
   u8 cMode;              /* temporary output mode for the current query */
   u8 normalMode;         /* Output mode before ".explain on" */
-#if 0 /* moved to ShellExState and renamed */
-  int *colWidth;         /* Requested width of each column in columnar modes */
-  int *actualWidth;      /* Actual width of each column */
-  int nWidth;            /* Number of slots in colWidth[] and actualWidth[] */
-#endif
   char nullValue[20];    /* Text to print for NULL retrieved from database */
 
   unsigned statsOn;      /* True to display memory stats before each finalize */
   unsigned mEqpLines;    /* Mask of veritical lines in the EQP output graph */
   int outCount;          /* Revert to stdout when reaching zero */
-#if 0 /* moved to ShellExState as resultCount */
-  int cnt;               /* Number of records displayed so far */
-#endif
+
   int inputNesting;      /* Track nesting level of .read and other redirects */
   InSource *pInSource;   /* Read commands and SQL from this stream source */
 
   FILE *out;             /* Write results here */
   FILE *traceOut;        /* Output for sqlite3_trace() */
-#if 0 /* moved to ShellExState */
-  int abruptExit;        /* Flag for immediate shell exit, exit code */
-#endif
+
   int nErr;              /* Number of errors seen */
   int writableSchema;    /* True if PRAGMA writable_schema=ON */
   int nCheck;            /* Number of ".check" commands run */
@@ -1348,6 +1338,7 @@ typedef struct ShellInState {
   char *zNonce;          /* Nonce for temporary safe-mode suspension */
   EQPGraph sGraph;       /* Information for the graphical EXPLAIN QUERY PLAN */
   ExpertInfo expert;     /* Valid if previous command was ".expert OPT..." */
+
   ShellExState *pSXS;    /* Pointer to companion, exposed shell state */
 } ShellInState;
 
@@ -4616,9 +4607,10 @@ static int run_schema_dump_query(
 DISPATCH_CONFIG[
   HELP_COALESCE=1
 ];
-#define HELP_TEXT_FMT "%s"
+#define HELP_TEXT_FMTP ".%s"
+#define HELP_TEXT_FMTS "%s"
 /* Above HELP_COALESCE config and HELP_TEXT_FMT PP vars must track.
- * Alternative is 0 and "%s\n" .
+ * Alternative is 0, ".%s\n" and "%s\n" .
  */
 
 /* Forward references */
@@ -7871,7 +7863,7 @@ CONDITION_COMMAND(seeargs !defined(SHELL_OMIT_SEEARGS));
  * The .seeargs command
  */
 COLLECT_HELP_TEXT[
-  ".seeargs                 Echo arguments suffixed with |",
+  ",seeargs                 Echo arguments suffixed with |",
 ];
 DISPATCHABLE_COMMAND( seeargs ? 0 0 azArg nArg p ){
   int rc = 0;
@@ -8011,7 +8003,7 @@ DISPATCHABLE_COMMAND( breakpoint 3 1 1 ){
  */
 COLLECT_HELP_TEXT[
   ".changes on|off          Show number of rows changed by SQL",
-  ".check GLOB              Fail if output since .testcase does not match",
+  ",check GLOB              Fail if output since .testcase does not match",
   ".clone NEWDB             Clone data into NEWDB from the existing database",
   ".connection [close] [#]  Open or close an auxiliary database connection",
 ];
@@ -8369,6 +8361,24 @@ DISPATCHABLE_COMMAND( eqp ? 0 0 ){
   }
 }
 
+/*****************
+ * The .exit and .quit commands
+ * These are together so that their subtle differences are apparent.
+ */
+COLLECT_HELP_TEXT[
+  ".exit ?CODE?             Exit this program with return-code CODE",
+  ".quit                    Exit this program or script",
+];
+DISPATCHABLE_COMMAND( exit 3 1 0 ){
+  int rc;
+  if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 )
+    p->shellAbruptExit = rc;
+  return 2;
+}
+DISPATCHABLE_COMMAND( quit 1 1 0 ){
+  return 2;
+}
+
 /*****************
  * The .expert and .explain commands
  */
@@ -8769,24 +8779,30 @@ DISPATCHABLE_COMMAND( headers 6 2 2 ){
 /*****************
  * The .help command
  */
+
+/* This literal's value AND address are used for help's workings. */
+static const char *zHelpAll = "-all";
+
 COLLECT_HELP_TEXT[
   ".help ?PATTERN?|?-all?   Show help for PATTERN or everything, or summarize",
   "                           Repeat -all to see undocumented commands",
 ];
-DISPATCHABLE_COMMAND( help 3 1 2 ){
+DISPATCHABLE_COMMAND( help 3 1 3 ){
   const char *zPat = 0;
+  FILE *out = ISS(p)->out;
   if( nArg>1 ){
     char *z = azArg[1];
-    if( strcmp(z,"-a")==0
-        || strcmp(z,"-all")==0
-        || strcmp(z,"--all")==0 ){
+    if( nArg==3 && strcmp(z, zHelpAll)==0 && strcmp(azArg[2], zHelpAll)==0 ){
+      /* Show the undocumented command help */
+      zPat = zHelpAll;
+    }else if( strcmp(z,"-a")==0 || strcmp(z,"-all")==0 || strcmp(z,"--all")==0 ){
       zPat = "";
     }else{
       zPat = z;
     }
   }
-  if( showHelp(ISS(p)->out, zPat, p)==0 ){
-    utf8_printf(ISS(p)->out, "Nothing matches '%s'\n", azArg[1]);
+  if( showHelp(out, zPat, p)==0 && nArg>1 ){
+    utf8_printf(out, "Nothing matches '%s'\n", azArg[1]);
   }
   /* Help pleas never fail! */
   return 0;
@@ -11548,16 +11564,20 @@ DISPATCHABLE_COMMAND( sha3sum 4 1 1 ){
 }
 
 /*****************
- * The .selftest, .shell, .show, .shxopts, .stats and .system commands
+ * The .selftest*, .shell, .show, .shxopts, .stats and .system commands
  */
+CONDITION_COMMAND( selftest_bool defined(SQLITE_DEBUG) );
+CONDITION_COMMAND( selftest_int defined(SQLITE_DEBUG) );
 CONDITION_COMMAND( shell !defined(SQLITE_NOHAVE_SYSTEM) );
 CONDITION_COMMAND( shxopts (SHELL_EXTENSIONS)!=0 );
 CONDITION_COMMAND( system !defined(SQLITE_NOHAVE_SYSTEM) );
 COLLECT_HELP_TEXT[
-  ".selftest ?OPTIONS?      Run tests defined in the SELFTEST table",
+  ",selftest ?OPTIONS?      Run tests defined in the SELFTEST table",
   "    Options:",
   "       --init               Create a new SELFTEST table",
   "       -v                   Verbose output",
+  ",selftest_bool ?ARGS?    Show boolean values of ARGS as flag tokens",
+  ",selftest_int ?ARGS?     Show integer values of ARGS as integer tokens",
   ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
   ".show                    Show the current values for various settings",
   ".shxopts ?SIGNED_OPTS?   Show or alter shell extension options",
@@ -11569,6 +11589,26 @@ COLLECT_HELP_TEXT[
   "   vmstep                   Show the virtual machine step count only",
   ".system CMD ARGS...      Run CMD ARGS... in a system shell",
 ];
+
+DISPATCHABLE_COMMAND( selftest_bool 10 0 0 ){
+  int i, v;
+  for(i=1; i<nArg; i++){
+    v = booleanValue(azArg[i]);
+    utf8_printf(ISS(p)->out, "%s: %d 0x%x\n", azArg[i], v, v);
+  }
+  return 0;
+}
+DISPATCHABLE_COMMAND( selftest_int 10 0 0 ){
+  int i; sqlite3_int64 v;
+  for(i=1; i<nArg; i++){
+    char zBuf[200];
+    v = integerValue(azArg[i]);
+    sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
+    utf8_printf(ISS(p)->out, "%s", zBuf);
+  }
+  return 0;
+}
+
 DISPATCHABLE_COMMAND( selftest 4 0 0 ){
   int rc;
   ShellInState *psi = ISS(p);
@@ -11994,8 +12034,8 @@ DISPATCHABLE_COMMAND( indices 3 1 2 ){
 CONDITION_COMMAND( testctrl !defined(SQLITE_UNTESTABLE) );
 CONDITION_COMMAND( trace !defined(SQLITE_OMIT_TRACE) );
 COLLECT_HELP_TEXT[
-  ".testcase NAME           Begin redirecting output to 'testcase-out.txt'",
-  ".testctrl CMD ...        Run various sqlite3_test_control() operations",
+  ",testcase NAME           Begin redirecting output to 'testcase-out.txt'",
+  ",testctrl CMD ...        Run various sqlite3_test_control() operations",
   "                            Run \".testctrl\" with no arguments for details",
   ".timeout MS              Try opening locked tables for MS milliseconds",
   ".timer on|off            Turn SQL timer on or off",
@@ -12801,7 +12841,7 @@ static void showPrimaryHelp(FILE *out, const char *zCmd, ShellExState *psx){
   MetaCommand *pmc = nextMatchingMetaCmd(&mmi);
   if( pmc!=0 ){
     const char *zH = pmc->pMethods->help(pmc, 0);
-    if( zH!=0 ) utf8_printf(out, HELP_TEXT_FMT, zH);
+    if( zH!=0 && *zH ) utf8_printf(out, HELP_TEXT_FMTP, zH+1);
   }
   freeMetaMatchIter(&mmi);
 }
@@ -12813,33 +12853,42 @@ static void showPrimaryHelp(FILE *out, const char *zCmd, ShellExState *psx){
 ** 3. For multiple commands matching a pattern, primary help text only.
 ** 4. For a single matched command, complete help text.
 ** 5. For commands whose help contains a pattern, complete help text.
+** 6. For the set of "undocumented" (without normal help) commands.
 ** These variations are indicated thusly:
 ** 1. zPattern is NULL
 ** 2. zPattern is ""
 ** 3. zPattern is a prefix matching more than one command
 ** 4. zPattern is a word or prefix matching just one command
 ** 5. zPattern is neither case 3 or 4 but is found in complete help text
+** 6. zPattern is exactly the pointer known locally as zHelpAll.
 **
 ** Return the number of matches.
 */
 static int showHelp(FILE *out, const char *zPattern, ShellExState *psx){
   u8 bNullPattern = zPattern==0;
-  u8 bEmptyPattern = (bNullPattern)? 0 : *zPattern==0;
+  u8 bShowUndoc = zPattern==zHelpAll;
+  u8 bEmptyPattern = !bNullPattern && (*zPattern==0 || bShowUndoc);
   int npm = 0; /* track how many matches found */
-  MetaMatchIter mmi = findMatchingMetaCmds(zPattern, psx);
+  MetaMatchIter mmi = findMatchingMetaCmds(bShowUndoc? "" : zPattern, psx);
   MetaCommand *pmc, *pmcLastShown = 0;
   char *zPat = 0;
+  char cLead = (bShowUndoc)? ',' : '.';
 
+  if( bShowUndoc ){
+    utf8_printf(out, "%s\n%s\n",
+                "The following commands are used for internal SQLite testing.",
+                "They are undocumented and subject to change without notice.");
+  }
   while( 0 != (pmc = nextMatchingMetaCmd(&mmi)) ){
     const char *zH = pmc->pMethods->help(pmc, 0);
-    if( zH!=0 ){
+    if( zH!=0 && *zH==cLead){
       ++npm;
       pmcLastShown = pmc;
-      utf8_printf(out, HELP_TEXT_FMT, zH);
+      utf8_printf(out, HELP_TEXT_FMTP, zH+1);
       if( bEmptyPattern ){
         zH = pmc->pMethods->help(pmc, 1);
         if( zH!=0 ){
-          utf8_printf(out, HELP_TEXT_FMT, zH);
+          utf8_printf(out, HELP_TEXT_FMTS, zH);
         }
       }
     }
@@ -12850,7 +12899,7 @@ static int showHelp(FILE *out, const char *zPattern, ShellExState *psx){
      * the secondary help of that command, even if not requested,
      * unless it was already emitted. */
     const char *zH = pmcLastShown->pMethods->help(pmcLastShown, 1);
-    if( zH!=0 ) utf8_printf(out, HELP_TEXT_FMT, zH);
+    if( zH!=0 ) utf8_printf(out, HELP_TEXT_FMTS, zH);
     return npm;
   }
   /* If found anything with provided (or NULL or empty) pattern, it's done. */
@@ -12863,10 +12912,11 @@ static int showHelp(FILE *out, const char *zPattern, ShellExState *psx){
   while( 0 != (pmc = nextMatchingMetaCmd(&mmi)) ){
     const char *zHp = pmc->pMethods->help(pmc, 0);
     const char *zHs = pmc->pMethods->help(pmc, 1);
-    if( (zHp!=0 && sqlite3_strlike(zPat, zHp, 0)==0)
+    if( zHp==0 || *zHp!='.' ) continue;
+    if( sqlite3_strlike(zPat, zHp, 0)==0
         || (zHs!=0 && sqlite3_strlike(zPat, zHs, 0)==0) ){
-      if( zHp ) utf8_printf(out, HELP_TEXT_FMT, zHp);
-      if( zHs ) utf8_printf(out, HELP_TEXT_FMT, zHs);
+      utf8_printf(out, HELP_TEXT_FMTP, zHp+1);
+      if( zHs ) utf8_printf(out, HELP_TEXT_FMTS, zHs);
       ++npm;
     }
   }
@@ -12887,6 +12937,8 @@ static int do_meta_command(char *zLine, ShellExState *psx){
   int n, c;
   int rc = 0;
   char *azArg[52];
+  char *zErr = 0;
+  int dispatchResult;
 #if SHELL_VARIABLE_EXPANSION
   int ncLineIn = strlen30(zLine);
   u8 bExpVars = SHEXT_VAREXP(ISS(psx));
@@ -12930,91 +12982,52 @@ static int do_meta_command(char *zLine, ShellExState *psx){
   c = azArg[0][0];
   clearTempFile(ISS(psx));
 
-  /* Check for the special, non-dispatched meta-commands.
-  */
-
-  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
-    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 )
-      psx->shellAbruptExit = rc;
-    rc = 2;
-  }else
-
-  if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
-    rc = 2;
-  }else
-
-#ifdef SQLITE_DEBUG
-  /* Undocumented commands for internal testing.  
-   * Subject to change without notice.
-   * These are not dispatched via lookup because the command word varies.
-   */
-  if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
-    if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
-      int i, v;
-      for(i=1; i<nArg; i++){
-        v = booleanValue(azArg[i]);
-        utf8_printf(ISS(psx)->out, "%s: %d 0x%x\n", azArg[i], v, v);
+  dispatchResult = dispatchCommand(azArg, nArg, psx, &zErr);
+  if( psx->shellAbruptExit!=0 ){
+    dispatchResult = SHELL_FORBIDDEN_OP;
+  }
+  switch( dispatchResult ){
+  case NO_SUCH_COMMAND:
+    utf8_printf(STD_ERR, "Error: unknown command: \"%s\"\n", azArg[0]);
+    if( stdin_is_interactive )
+      utf8_printf(STD_ERR, "  Enter \".help\" for a list of commands.\n");
+    rc = 1;
+    break;
+  case SHELL_INVALID_ARGS:
+    utf8_printf(STD_ERR, "Error: invalid arguments for \".%s\"\n", azArg[0]);
+    if( stdin_is_interactive ){
+      if( zErr!=0 ){
+        utf8_printf(STD_ERR, "  %s\n", zErr);
+      }else{
+        utf8_printf(STD_ERR, "Usage: ");
+        showPrimaryHelp(STD_ERR, azArg[0], psx);
       }
     }
-    if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
-      int i; sqlite3_int64 v;
-      for(i=1; i<nArg; i++){
-        char zBuf[200];
-        v = integerValue(azArg[i]);
-        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
-        utf8_printf(ISS(psx)->out, "%s", zBuf);
-      }
+    rc = 1;
+    break;
+  case SHELL_FORBIDDEN_OP:
+    if( zErr!=0 ){
+      utf8_printf
+        (STD_ERR,
+         "Error: \".%s\" may not %s in --safe mode\n", azArg[0], zErr);
+      sqlite3_free(zErr);
+    }else {
+      utf8_printf(STD_ERR,
+                  "Error: \".%s\" forbidden in --safe mode\n", azArg[0]);
     }
-  }else
-#endif
-    /* The meta-command is not among the specially handled ones. Dispatch it. */
-  {
-    char *zErr = 0;
-    int dispatchResult = dispatchCommand(azArg, nArg, psx, &zErr);
-    if( psx->shellAbruptExit!=0 ){
-      dispatchResult = SHELL_FORBIDDEN_OP;
-    }
-    switch( dispatchResult ){
-    case NO_SUCH_COMMAND:
-      utf8_printf(STD_ERR, "Error: unknown command: \"%s\"\n", azArg[0]);
-      if( stdin_is_interactive )
-        utf8_printf(STD_ERR, "  Enter \".help\" for a list of commands.\n");
-      rc = 1;
-      break;
-    case SHELL_INVALID_ARGS:
-      utf8_printf(STD_ERR, "Error: invalid arguments for \".%s\"\n", azArg[0]);
-      if( stdin_is_interactive ){
-        if( zErr!=0 ){
-          utf8_printf(STD_ERR, "  %s\n", zErr);
-        }else{
-          utf8_printf(STD_ERR, "Usage: ");
-          showPrimaryHelp(STD_ERR, azArg[0], psx);
-        }
-      }
-      rc = 1;
-      break;
-    case SHELL_FORBIDDEN_OP:
-      if( zErr!=0 ){
-        utf8_printf
-          (STD_ERR,
-           "Error: \".%s\" may not %s in --safe mode\n", azArg[0], zErr);
-        sqlite3_free(zErr);
-      }else {
-        utf8_printf(STD_ERR,
-                    "Error: \".%s\" forbidden in --safe mode\n", azArg[0]);
-      }
-      psx->shellAbruptExit = 3;
-      rc = 2;
-    default:
-      if( 0!=dispatchResult ) rc = 1;
-      if( zErr!=0 ){
-        utf8_printf(STD_ERR, "%s", zErr);
-        sqlite3_free(zErr);
-      }
+    psx->shellAbruptExit = 3;
+    /* fall thru */
+  case 2:
+    rc = 2;
+    /* fall thru */
+  default:
+    if( dispatchResult>2 ) rc = 1;
+    if( zErr!=0 ){
+      utf8_printf(STD_ERR, "%s", zErr);
+      sqlite3_free(zErr);
     }
   }
 
-meta_command_exit:
   if( ISS(psx)->outCount ){
     ISS(psx)->outCount--;
     if( ISS(psx)->outCount==0 ) output_reset(ISS(psx));
index a8496f4a44f71a3a6835c70fa6e46b849bd166d8..8be1f3a959e7f3cb39db7391a2a8d402dbaa6fe6 100644 (file)
@@ -21,8 +21,11 @@ typedef struct ShellExState {
   /* A semi-transient holder of arbitrary data used during operations
    * not interrupted by meta-command invocations. Any not-null pointer
    * left after a meta-command has completed is, by contract, to be
-   * freeable using sqlite3_free(). It is otherwise unconstrained. */
+   * freeable using sqlite3_free(), unless freeHandlerData is non-zero,
+   * in which case it is used for the free, then zeroed too. This
+   * pointer's use is otherwise unconstrained. */
   void *pvHandlerData;
+  void (*freeHandlerData)(void *);
 
   /* The user's currently open and primary DB connection
    * Extensions may use this DB, but must not modify this pointer.
@@ -72,6 +75,7 @@ typedef struct ShellExState {
   int  *pSpecWidths;
   /* The column widths last observed in query results, read-only */
   int  *pHaveWidths;
+
   /* Internal and opaque shell state, not for use by extensions */
   struct ShellInState *pSIS; /* Offset of this member is NOT STABLE. */
 } ShellExState;
index 2a1b8a93a07420869865d937f1f990081dd69666..dce7caa6ec061bd1087227af84093aaa0a5d2ab1 100644 (file)
@@ -269,7 +269,7 @@ proc emit_conditionally {cmd lines inSrc ostrm {indent ""} {cmdTagStore {}}} {
 proc coalesce_help {htin} {
   set htrv {}
   foreach hl $htin {
-    if {[regexp {^\s*"\.\w+} $hl]} { ;# "
+    if {[regexp {^\s*"[\.,/><?]\w+} $hl]} { ;# "
       lappend htrv [regsub {"\s*,\s*$} $hl {\n",}]
     } elseif {[regexp {^\s*#\s*\w+} $hl]} {
       lappend htrv $hl
@@ -284,17 +284,23 @@ proc coalesce_help {htin} {
 # Keys are the command names. Values are the help for the
 # commands as a list of lines, with .* logically first.
 # Any #if... #endif structures are maintained and do not
-# interact with "logically first" .* lines, except that
+# interact with "logically first" ?* lines, except that
 # only one such line is seen within such a conditional.
 # (The effect of this is to defeat sorting by command if
 # help for multiple commands' is within one conditional.)
+# Quoted lines beginning with a character in [.,></?],
+# followed by an alpha sequence, are used as the initial,
+# primary, single-line help text for the command named by
+# the alpha sequence. Other quoted lines which follow are
+# used as the command's secondary, expanded help text.
 proc chunkify_help {htin} {
   array set rv [list]
   set if_depth 0
   set cmd_seen ""
   set chunk {}
   foreach htx $htin {
-    if {[regexp {^\s*\"\.\w} $htx] && $cmd_seen ne "" && $if_depth == 0} {
+    if {[regexp {^\s*\"[\.,/><?]\w} $htx]
+        && $cmd_seen ne "" && $if_depth == 0} {
       # Flush accumulated chunk.
       set rv($cmd_seen) $chunk
       set cmd_seen ""
@@ -306,7 +312,7 @@ proc chunkify_help {htin} {
     } elseif {[regexp {^\s*#endif} $htx]} {
       incr if_depth -1
     } else {
-      if {[regexp {^\s*\"\.(\w+)} $htx all cmd] && $cmd_seen eq ""} {
+      if {[regexp {^\s*\"[\.,/><?](\w+)} $htx all cmd] && $cmd_seen eq ""} {
         set cmd_seen $cmd
       }
     }