-C Create\sinfrastructure\sfor\sdynamic\sshell\sextension.
-D 2021-07-03T19:20:48.689
+C Streamline\smost\scommon\scommand\sdefinition
+D 2021-07-04T22:38:20.110
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/resolve.c b379c5ffe3b692e9c64fa37817cc0efa204b7c9468a818309dde85fd132d9d81
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c 4fa607bab6bcc580f12dbaf9c800b2250a1e408f10321a1d3bcb1dd30c447e62
-F src/shell.c.in ab31fb9d92ab84e1abb02a2c40e910b24434e729fa7549acbb3fee9aed5973d8
+F src/shell.c.in 0a1460f9daacc06ce7618981d2d3d3b206a64ca30258a5968ffd421eccaabaeb
F src/sqlite.h.in ecf5aa981da30c33da3e9f353bf3ebf055d3c380c80d6a4f954e58d18ccd6df1
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
F tool/mkopcodeh.tcl 130b88697da6ec5b89b41844d955d08fb62c2552e889dec8c7bcecb28d8f50bd
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
F tool/mkpragmatab.tcl ae5585ae76ca26e4d6ccd5ea9cdebaf5efefb318bf989497a0e846cd711d9ab1
-F tool/mkshellc.tcl 627d5f39b306cc335e5f29d8b24945c54a64a42e635fc8eb8c2558ba257c9844
+F tool/mkshellc.tcl 270ddd503b3c6c2ea1fa6559a086cd2517ff84088b54909960fffeda4d0b816e
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 68db1ff9c44fa9c37690ce55ad304d4263ba6fac490063d9e08470de6c17cfe6
-R 347b1c92e54f1f6ec16ffdb8c5434cca
-T *branch * cli_extension
-T *sym-cli_extension *
-T -sym-trunk *
+P 5e7e0d4ef8665e924f499238b1469a5fc06d24f6cf96864b502e62734d92e7ee
+R 1911848c8c9c967a495f2da60a0478ec
U larrybr
-Z d788ab2ca1c9950dfd92c69b64866455
+Z 9f01a27b7f49ee2ea4a875a6945797b7
-5e7e0d4ef8665e924f499238b1469a5fc06d24f6cf96864b502e62734d92e7ee
\ No newline at end of file
+dd76b41a72aca94450fb6f45ff56af95d2adb9275eebe9ca67ebd04a52a63c33
\ No newline at end of file
#endif
static const char *(azHelp[]);
+static unsigned numCommands;
/* True if the timer is enabled */
static int enableTimer = 0;
}
pzH = pzHxtra;
n++;
- } else {
+ }else{
++pzH;
}
}
}
#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
+CONDITION_COMMAND(seeargs defined(SQLITE_GIMME_SEEARGS));
+/*****************
+ * The .seeargs command
+ */
+COLLECT_HELP_TEXT[
+ ".seeargs Echo arguments separated by |",
+ " A near-dummy command for use as a template (to vanish soon)",
+];
+DISPATCHABLE_COMMAND( seeargs ? 0 0 azArg nArg p ){
+ int rc = 0;
+ for (rc=1; rc<nArg; ++rc)
+ raw_printf(p->out, "%s%s", azArg[rc], (rc==nArg-1)? "\n" : "|");
+ return rc;
+}
+
+/*****************
+ * The .auth command
+ */
+CONDITION_COMMAND(auth !defined(SQLITE_OMIT_AUTHORIZATION));
+COLLECT_HELP_TEXT[
+ ".auth ON|OFF Show authorizer callbacks",
+];
+DISPATCHABLE_COMMAND( auth 3 2 2 azArg nArg p ){
+ int rc = 0;
+ open_db(p, 0);
+ if( booleanValue(azArg[1]) ){
+ sqlite3_set_authorizer(p->db, shellAuth, p);
+ }else{
+ sqlite3_set_authorizer(p->db, 0, 0);
+ }
+ return rc;
+}
+
/*****************
* The .help command
*/
EMIT_DISPATCH();
{ 0, 0, 0, -1, -1 }
};
+static unsigned numCommands = sizeof(command_table)/sizeof(struct DispatchEntry) - 1;
/*****************
* Command dispatcher
int dispatchCommand(char *azArg[], int nArg, ShellState *pSS)
{
const char *cmdName = azArg[0];
- /* A temporary, simple-minded scan */
- struct DispatchEntry *pde = command_table;
- while (pde->cmdName != 0){
- if (0==strncmp(cmdName, pde->cmdName, pde->minLen)){
- if((pde->minArgs > 0 && pde->minArgs > nArg)||(pde->maxArgs > 0 && pde->maxArgs < nArg)){
- return INVALID_ARGS;
- }
- return (pde->cmdDoer)(azArg, nArg, pSS);
- } else { ++pde; }
+ struct DispatchEntry *pde = 0;
+ int ixb = 0, ixe = numCommands-1;
+ while( ixb <= ixe ){
+ int ixm = (ixb+ixe)/2;
+ int md = strncmp(cmdName, command_table[ixm].cmdName, command_table[ixm].minLen);
+ if( md>0 ){
+ ixb = ixm+1;
+ }else if( md<0 ){
+ ixe = ixm-1;
+ }else{
+ pde = &command_table[ixm];
+ break;
+ }
}
- return NO_SUCH_COMMAND;
+ if( 0==pde ){
+ return NO_SUCH_COMMAND;
+ }
+ if((pde->minArgs > 0 && pde->minArgs > nArg)||(pde->maxArgs > 0 && pde->maxArgs < nArg)){
+ return INVALID_ARGS;
+ }
+ return (pde->cmdDoer)(azArg, nArg, pSS);
}
c = azArg[0][0];
clearTempFile(p);
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .auth ON|OFF\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- if( booleanValue(azArg[1]) ){
- sqlite3_set_authorizer(p->db, shellAuth, p);
- }else{
- sqlite3_set_authorizer(p->db, 0, 0);
- }
- }else
-#endif
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
/* The meta-command is not among the specially handled ones. Dispatch it. */
{
int dispatchResult = dispatchCommand(azArg, nArg, p);
- if( NO_SUCH_COMMAND==dispatchResult || INVALID_ARGS==dispatchResult ){
- utf8_printf(stderr, "Error: unknown command or invalid arguments: "
- " \"%s\". Enter \".help\" for help\n", azArg[0]);
+ if( NO_SUCH_COMMAND==dispatchResult ){
+ utf8_printf(stderr, "Error: unknown command: \"%s\"\n"
+ " Enter \".help\" for a list of commands.\n", azArg[0]);
+ rc = 1;
+ }
+ if( INVALID_ARGS==dispatchResult ){
+ utf8_printf(stderr, "Error: invalid arguments for \".%s\"\n"
+ " Enter \".help %s\" for help on it.\n", azArg[0],azArg[0]);
rc = 1;
}
}
" http://sqlite.org/cli.html#sqlite_archive_support",
#endif
];
-COLLECT_HELP_TEXT[
-#ifndef SQLITE_OMIT_AUTHORIZATION
- ".auth ON|OFF Show authorizer callbacks",
-#endif
-];
COLLECT_HELP_TEXT[
".backup ?DB? FILE Backup DB (default \"main\") to FILE",
" --append Use the appendvfs",
** start of the description of what that command does.
*/
static const char *(azHelp[]) = {
+/* Template for help text indents and length:
+ ".whatever ?arg? ... Summary of effects (limited to this line's length)",
+ " ^ ^ ^ ^ ",
+*/
EMIT_HELP_TEXT();
- 0
+ 0 /* Sentinel */
};
/*
fconfigure stdout -translation {auto lf}
puts $out {/* DO NOT EDIT!
** This file is automatically generated by the script in the canonical
-** SQLite source tree at tool/mkshellc.tcl. That script combines source
-** code from various constituent source files of SQLite into this single
-** "shell.c" file used to implement the SQLite command-line shell.
+** SQLite source tree at tool/mkshellc.tcl. That script combines and
+** transforms code from various constituent source files of SQLite into
+** this single "shell.c" file to implement the SQLite command-line shell.
**
** Most of the code found below comes from the "src/shell.c.in" file in
** the canonical SQLite source tree. That main file contains "INCLUDE"
set in [open $topdir/src/shell.c.in rb]
-proc omit_redundant_typedefs {line} {
-}
-
set ::cmd_help [dict create]
set ::cmd_dispatch [dict create]
+set ::cmd_condition [dict create]
set ::iShuffleErrors 0
+set ::commandFuncSuffix "Command"
+
+proc condition_command {cmd pp_expr} {
+ if {[regexp {^(!)?defined\(\s*(\w+)\s*\)} $pp_expr ma bang pp_var]} {
+ if {$bang eq "!"} {
+ set pp_expr "#ifndef $pp_var"
+ } else {
+ set pp_expr "#ifdef $pp_var"
+ }
+ } else {
+ set pp_expr "#if [string trim $pp_expr]"
+ }
+ dict set ::cmd_condition $cmd $pp_expr
+}
+
+proc emit_conditionally {cmd lines ostrm} {
+ set wrapped [dict exists $::cmd_condition $cmd]
+ if {$wrapped} {
+ puts $ostrm [dict get $::cmd_condition $cmd]
+ }
+ puts $ostrm [join $lines "\n"]
+ if {$wrapped} {
+ puts $ostrm "#endif"
+ }
+}
# Convert list of help text lines into a dict.
# Keys are the command names. Values are the help for the
}
incr iAte
set ::cmd_help [dict merge $::cmd_help [chunkify_help $help_frag]]
+ } elseif {[regexp {^\s*DISPATCHABLE_COMMAND\(([\w\? ]+)\)(\S)\s*$} $lx ma args tc]
+ && $tc eq "\x7B"} {
+ set args [split [regsub {\s+} [string trim $args] " "]]
+ incr iAte
+ if {[llength $args] != 7} {
+ puts stderr "Bad args: $lx"
+ } else {
+ set body {}
+ while {![eof $hFile]} {
+ set lb [gets $hFile]
+ incr iAte
+ lappend body $lb
+ if {[regexp "^\x7D\\s*\$" $lb]} { break }
+ }
+ foreach {cmd cmdLen naMin naMax azA nA pSS} $args {
+ if {$cmdLen eq "?"} {
+ set cmdLen [string length $cmd]
+ }
+ set func "$cmd$::commandFuncSuffix"
+ set dispEntry " \x7B \"$cmd\", $func, $cmdLen, $naMin, $naMax \x7D,"
+ set funcOpen "static int ${func}(char *$azA\[\], int $nA, ShellState *$pSS)\x7B"
+ emit_conditionally $cmd [linsert $body 0 $funcOpen] $ostrm
+ dict set ::cmd_dispatch $cmd [list $dispEntry]
+ }
+ }
} elseif {[regexp {^\s*EMIT_HELP_TEXT\(\)} $lx]} {
incr iAte
foreach htc [lsort [dict keys $::cmd_help]] {
- puts $ostrm [join [dict get $::cmd_help $htc] "\n"]
+ emit_conditionally $htc [dict get $::cmd_help $htc] $ostrm
}
} elseif {[regexp {^COLLECT_DISPATCH\(\s*(\w+)\s*\)\[} $lx ma cmd]} {
incr iAte
} elseif {[regexp {^\s*EMIT_DISPATCH\(\)} $lx]} {
incr iAte
foreach cmd [lsort [dict keys $::cmd_dispatch]] {
- puts $ostrm [join [dict get $::cmd_dispatch $cmd] "\n"]
+ emit_conditionally $cmd [dict get $::cmd_dispatch $cmd] $ostrm
}
+ } elseif {[regexp {^CONDITION_COMMAND\(\s*(\w+)\s+([^;]+)\);} $lx ma cmd pp_expr]} {
+ incr iAte
+ condition_command $cmd [string trim $pp_expr]
} else {
puts $ostrm $lx
}
}
close $in
close $out
+
exit $::iShuffleErrors