]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
For shell extensions, generate a single-file header. For TCL extension, provide Makef...
authorlarrybr <larrybr@noemail.net>
Sat, 9 Apr 2022 02:31:50 +0000 (02:31 +0000)
committerlarrybr <larrybr@noemail.net>
Sat, 9 Apr 2022 02:31:50 +0000 (02:31 +0000)
FossilOrigin-Name: 2cd49df502a7cd250c453cbbd6a2651e588d69dd755bbdf5a55b58715e548760

Makefile.in
configure
configure.ac
ext/misc/tclshext.c.in
manifest
manifest.uuid
src/shext_linkage.h
src/test_shellext.c
tool/mkshellc.tcl

index bbd6ae231d2de6ce963490f88cec084831b6e969..a56b01ef98aad77545a5601b547ab08614e43dcf 100644 (file)
@@ -53,6 +53,12 @@ TCC += @TCL_INCLUDE_SPEC@
 #
 LIBTCL = @TCL_LIB_SPEC@
 
+# TCCX is the C Compile and options for use in building shell extensions
+# that will run on the target platform. It relies on no in-tree includes,
+# using only pre-glommed source/header files in the current directory.
+TCCX = ${CC} ${CFLAGS} -fPIC -shared -I. @TCL_INCLUDE_SPEC@
+TCCX += @EXTENSION_DEBUG@ $(LIBTCL)
+
 # Compiler options needed for programs that use the readline() library.
 #
 READLINE_FLAGS = -DHAVE_READLINE=@TARGET_HAVE_READLINE@ @TARGET_READLINE_INC@
@@ -161,6 +167,9 @@ LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(TCC) $(LTCOMPILE_EXTRAS)
 LTLINK = $(LIBTOOL) --mode=link $(TCC) $(LTCOMPILE_EXTRAS) @LDFLAGS@ $(LTLINK_EXTRAS)
 LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL)
 
+# Shell and extension source builder tool
+MKSHELL_TOOL = $(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl
+
 # You should not have to change anything below this line
 ###############################################################################
 
@@ -1114,7 +1123,7 @@ SHELL_SRC = \
         $(TOP)/src/obj_interfaces.h
 
 shell.c:       $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
-       $(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
+       $(MKSHELL_TOOL) >shell.c
 
 
 
@@ -1229,6 +1238,27 @@ fts5.lo: fts5.c $(HDR) $(EXTHDR)
 sqlite3rbu.lo: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
        $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rbu/sqlite3rbu.c
 
+# Rule to build shx_link.h (for use by shell extensions)
+
+SHX_LINK_SRC = \
+ $(TOP)/src/shext_linkage.h \
+ $(TOP)/src/obj_interfaces.h \
+ sqlite3ext.h \
+ sqlite3.h
+
+shx_link.h:    $(SHX_LINK_SRC)
+       $(MKSHELL_TOOL) -short-head -header-gen \
+                $(TOP)/src/shext_linkage.h > $@
+
+# Rules to build the TCL shell extension (tclshext.{so,dll,dylib})
+
+tcl_shell_extension:   tclshext$(SHLIB_SUFFIX)
+
+tclshext.c:    $(TOP)/ext/misc/tclshext.c.in $(TOP)/src/tclsqlite.c
+       $(MKSHELL_TOOL) $(TOP)/ext/misc/tclshext.c.in > $@
+
+tclshext$(SHLIB_SUFFIX): tclshext.c shx_link.h
+       $(TCCX) $(TCLEXT_OPTS) tclshext.c -o $@
 
 # Rules to build the 'testfixture' application.
 #
@@ -1490,6 +1520,7 @@ clean:
        rm -f sqlite3.c
        rm -f sqlite3rc.h
        rm -f shell.c sqlite3ext.h
+       rm -f shx_link.h tclshext.c tclshext$(SHLIB_SUFFIX)
        rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c
        rm -f sqlite-*-output.vsix
        rm -f mptester mptester.exe
index c5d122423d1fac08b0ac219f6d272add580a8e06..004044865a5d58608dbb138bb7f5c03b570c0460 100755 (executable)
--- a/configure
+++ b/configure
@@ -776,6 +776,7 @@ OPT_FEATURE_FLAGS
 HAVE_ZLIB
 USE_AMALGAMATION
 TARGET_DEBUG
+EXTENSION_DEBUG
 TARGET_HAVE_EDITLINE
 TARGET_HAVE_READLINE
 TARGET_READLINE_INC
 $as_echo_n "checking build type... " >&6; }
 if test "${enable_debug}" = "yes" ; then
   TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
+  EXTENSION_DEBUG="-DSQLITE_DEBUG=1"
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5
 $as_echo "debug" >&6; }
 else
   TARGET_DEBUG="-DNDEBUG"
+  EXTENSION_DEBUG="-DNDEBUG"
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: release" >&5
 $as_echo "release" >&6; }
 fi
index cc805a00d57a591e2af93a84c6b6120740f67274..a83ec75b066435ceb45cacf5b25407a8c9f77605 100644 (file)
@@ -558,12 +558,15 @@ AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose
 AC_MSG_CHECKING([build type])
 if test "${enable_debug}" = "yes" ; then
   TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
+  EXTENSION_DEBUG="-DSQLITE_DEBUG=1"
   AC_MSG_RESULT([debug])
 else
   TARGET_DEBUG="-DNDEBUG"
+  EXTENSION_DEBUG="-DNDEBUG"
   AC_MSG_RESULT([release])
 fi
 AC_SUBST(TARGET_DEBUG)
+AC_SUBST(EXTENSION_DEBUG)
 
 #########
 # See whether we should use the amalgamation to build
index 8f6e0befa20e500de67f370c44e076d3db56741e..677843ebb388ee0c21cfd33598467306a7e22a95 100644 (file)
 ** This file contains code to implement the "tclshext" shell extension
 ** for use with the extensible "sqlite3" CLI shell. On *Nix, build thusly:
      tool/mkshellc.tcl ext/misc/tclshext.c.in > tclshext.c
-     gcc -shared -fPIC -O2 -I. -Isrc -I/usr/include/tcl8.6 tclshext.c \
-       -o tclshext.so -ltcl8.6
+     gcc -shared -fPIC -O2 -I. -Isrc -I/usr/include/tcl8.6 \
+       tclshext.c -o tclshext.so -ltcl8.6
+** Or, use the provided Makefile and build target tcl_shell_extension .
+   If the Tk library is available, it can be linked and used thusly:
+     gcc -shared -fPIC -O2 -I. -Isrc -I/usr/include/tcl8.6 \
+       -DSHELL_ENABLE_TK tclshext.c -o tclshext.so -ltcl8.6 -ltk8.6
+** Or, make the same target, with 'TCLEXT_OPTS=-DSHELL_ENABLE_TK'.
 ** Later TCL versions can be used if desired.
   "TCL scripting support is added with a registerScripting() call in the\n"
   "ShellExtensionAPI, per ScriptingSupport interface requirements. This\n"
@@ -100,7 +105,7 @@ static const char * const zTclHelp =
 ** from the shell in the dot command execution context.
 */
 
-#include "shext_linkage.h"
+#include "shx_link.h"
 
 /* Extension boiler-plate to dynamically link into host's SQLite library */
 SQLITE_EXTENSION_INIT1;
@@ -125,9 +130,9 @@ int sqlite3_tclshext_init(sqlite3*, char**, const sqlite3_api_routines*);
 #define STATIC_BUILD /* Not publishing TCL API */
 #undef SQLITE_AMALGAMATION
 #undef TCLSH
-#include <tclOO.h>
-#ifndef SHELL_OMIT_TK
-#include <tk.h> /* Only used if option -tk passed during load. */
+#include "tclOO.h"
+#ifdef SHELL_ENABLE_TK
+#include "tk.h" /* Only used if option -tk passed during load. */
 #endif
 INCLUDE tclsqlite.c
 
@@ -163,7 +168,11 @@ static void Tcl_TakeDown(void *pv){
   }
 }
 
-static int Tcl_BringUp(int *pWithTk, char **pzErrMsg){
+static int Tcl_BringUp(
+#ifdef SHELL_ENABLE_TK
+                       int *pWithTk,
+#endif
+                       char **pzErrMsg){
   if( ++interpKeep.nRefs==1 ){
     const char *zShellName = SHX_HELPER(shellInvokedAs)();
     const char *zShellDir = SHX_HELPER(shellStartupDir)();
@@ -188,17 +197,16 @@ static int Tcl_BringUp(int *pWithTk, char **pzErrMsg){
       *pzErrMsg = sqlite3_mprintf("Tcl interpreter startup failed.\n");
       Tcl_TakeDown(&interpKeep);
       return SQLITE_ERROR;
-    }else if( *pWithTk ){
-#ifndef SHELL_OMIT_TK
+    }
+#ifdef SHELL_ENABLE_TK
+    else if( *pWithTk ){
       if( TCL_OK!=Tk_Init(interpKeep.pInterp) ){
         fprintf(stderr, "Could not load/initialize Tk."
-                " (non-fatal, extension is loaded.)\n");
+                " (Non-fatal, extension is loaded.)\n");
         *pWithTk = 0;
       }
-#else
-      fprintf(stderr, "This tclshext extension has no Tk support.\n");
-#endif
     }
+#endif
   }
   return (interpKeep.pInterp!=0)? SQLITE_OK : SQLITE_ERROR;
 }
@@ -714,7 +722,7 @@ static int nowInteractive(void *pvSS, Tcl_Interp *interp,
   }
 }
 
-#ifndef SHELL_OMIT_TK
+#ifdef SHELL_ENABLE_TK
 static int numEventLoops = 0;
 static int inOuterLoop = 0;
 
@@ -773,7 +781,7 @@ static int runTkGUI(void *pvSS, Tcl_Interp *interp,
   runTclEventLoop();
   return TCL_OK;
 }
-#endif
+#endif /* defined(SHELL_ENABLE_TK) */
 
 #define UNKNOWN_RENAME "::_original_unknown"
 
@@ -1113,15 +1121,24 @@ int sqlite3_tclshext_init(
     Tcl_Obj *targv = Tcl_NewListObj(0, NULL);
     const char *zAppName = "tclshext";
     int tnarg = 0;
+#ifdef SHELL_ENABLE_TK
     int ldTk = 0;
+#endif
     int rc = 0;
 
     if( pShExtLink->nLoadArgs>0 ){
       int ila;
       for( ila=0; ila<pShExtLink->nLoadArgs; ++ila ){
         const char *zA = pShExtLink->azLoadArgs[ila];
-        if( strcmp(zA,"-tk")==0 ) ldTk = 1;
-        else {
+        if( strcmp(zA,"-tk")==0 ){
+#ifdef SHELL_ENABLE_TK
+          ldTk = 1;
+#else
+          *pzErrMsg = sqlite3_mprintf("Option -tk not supported by this"
+                                      "tclshext extension as built.\n");
+          return SQLITE_ERROR;
+#endif
+        }else{
           /* Collect args not affecting init into the argv list. */
           Tcl_ListObjAppendElement(NULL, targv, Tcl_NewStringObj(zA, -1));
           ++tnarg;
@@ -1132,7 +1149,13 @@ int sqlite3_tclshext_init(
                                       (MetaCommand *)&unkcmd);
     rc = SHX_API(registerMetaCommand)(psx, sqlite3_tclshext_init,
                                       (MetaCommand *)&tclcmd);
-    if( rc==SQLITE_OK && (rc = Tcl_BringUp(&ldTk, pzErrMsg))==SQLITE_OK ){
+    if( rc==SQLITE_OK &&
+        (rc = Tcl_BringUp(
+#ifdef SHELL_ENABLE_TK
+                          &ldTk,
+#endif
+                          pzErrMsg))==SQLITE_OK
+        ){
       Tcl_Interp *interp = getInterp();
       if( TCL_OK==userDbInit(interp, psx) ){
         UserDb *pudb = udbCreate(interp, psx);
@@ -1160,7 +1183,7 @@ int sqlite3_tclshext_init(
       /* Define this proc so that ".." either gets to the TCL REPL loop
        * or does nothing (if already in it), as a user convenience. */
       Tcl_Eval(interp, "proc .. {} {}");
-#ifndef SHELL_OMIT_TK
+#ifdef SHELL_ENABLE_TK
       if( ldTk ){
         /* Create a proc to launch GUI programs, in faint mimicry of wish. 
          *
@@ -1249,7 +1272,7 @@ int sqlite3_tclshext_init(
         Tcl_SetMainLoop(runTclEventLoop);
         zAppName = "tclshext_tk";
       }
-#endif
+#endif /* ..TK */
       Tcl_SetVar2Ex(interp, "::argv0", NULL,
                     Tcl_NewStringObj(zAppName,-1), TCL_GLOBAL_ONLY);
       Tcl_SetVar2Ex(interp, "::argc", NULL,
index 55d493b3daceec092969f1fee3d9aa1e41937618..055fa988f9a8ccb6dbd494d8dc2b6936be2fa53d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Sync\sw/trunk,\sincluding\sall\sCLI\supdates
-D 2022-04-08T04:24:34.844
+C For\sshell\sextensions,\sgenerate\sa\ssingle-file\sheader.\sFor\sTCL\sextension,\sprovide\sMakefile\starget,\sand\smake\sTk\sopt-in\srather\sthan\sdefault.\s(a\sWIP)
+D 2022-04-09T02:31:50.173
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 204f3f2e09c721ef2e0414e0e4cda0bbf52428b9557d44e26ab81c4f2558fe95
+F Makefile.in eac9e7e2b337314bcfa445c5cfb52417c9a3b208f11d577eb51137e2b69662ec
 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
 F Makefile.msc 689726a2785027e0eb34ea9ce8e67ac94bc4aebbaa6def20ddb6fa9f7b0c43b5
 F README.md 2dd87a5c1d108b224921f3dd47dea567973f706e1f6959386282a626f459a70c
@@ -34,8 +34,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
 F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
 F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
 F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
-F configure 00378d14cca0ce02fa9eca28fd494789c2eda7d10d86003a5f9a42f34b0af418 x
-F configure.ac 3ef6eeff4387585bfcab76b0c3f6e15a0618587bb90245dd5d44e4378141bb35
+F configure f03fac8b39d72d4f5bf3df81e03195cca31b169add8e9ef1b55047cba3285e2d x
+F configure.ac f8e54c0c89f5c96fb073528afa53b41ff4e6a91b04d893dc0bce433ff8c84f91
 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
 F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
 F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
@@ -329,7 +329,7 @@ F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
 F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
 F ext/misc/sqlar.c 0ace5d3c10fe736dc584bf1159a36b8e2e60fab309d310cd8a0eecd9036621b6
 F ext/misc/stmt.c 35063044a388ead95557e4b84b89c1b93accc2f1c6ddea3f9710e8486a7af94a
-F ext/misc/tclshext.c.in 4ca2d623f9d2fd5b8de443a261a1e245b8935004c7c2aa1017e2ac68ef50bbb4
+F ext/misc/tclshext.c.in 419d8dde92b5be9ef289056e6d661d5aeccb48bb93deb4e6cb7986b8bc1cd4dc
 F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
 F ext/misc/totype.c fa4aedeb07f66169005dffa8de3b0a2b621779fd44f85c103228a42afa71853b
 F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a030b
@@ -557,7 +557,7 @@ F src/resolve.c 18d99e7146852d6064559561769fcca0743eb32b14a97da6dbed373a30ee0e76
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
 F src/select.c d6c04eb93395024af80f61a8c278a33c2a0333aeb7d57bb6aa737a6f1c4af4b8
 F src/shell.c.in a32d50c687fc79e4d19992810dfa358d0342f4b9e464f791e6db011cc6c5f0ec
-F src/shext_linkage.h 8a3990b43db032451e8ea04030ed67d99b15c7af10400032e9e8f6985e88ff73
+F src/shext_linkage.h 88a3f215fdb090fcc3b3577a05bafd234f1a556bad3f2f4ac990a177aebf4b2c
 F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e
@@ -606,7 +606,7 @@ F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
 F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b
 F src/test_schema.c f5d6067dfc2f2845c4dd56df63e66ee826fb23877855c785f75cc2ca83fd0c1b
 F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
-F src/test_shellext.c f66d9e7ab6df95edcd3e6d578fbbc6536c377c30478ae3ba51e4ec1ba3c70d81
+F src/test_shellext.c 0794ffe8c7762d027a28a2b445277c72a68b28eafba27d38ef197a9655599b42
 F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a
 F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
 F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
@@ -1885,7 +1885,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 21a84ef869e5b4de1e103730d8eac8e95c424226fcf73c6ccfc7a6b13370f2c5 x
+F tool/mkshellc.tcl e6fd439b1c2934d666cd43d4d1698e223dbbcf40f5c824a898454b5437242493 x
 F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
 F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
@@ -1951,8 +1951,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 52be86685006ac66cce79a7d8026d671030b308823c6ba427b52377591ba7064 1b5475d212cf9de0bff69eee8c607b4fcd8e04bf4df72171429e7609c4153951
-R da63d16a878892655dc7695acf7c75f4
+P ad8b48d6326b253e5d62dd262130820e4e6e56896abf17ddc6f1f7802204503a
+R 4ed9420c03213a06d36bd8ef7f0cba49
 U larrybr
-Z 6053491e5a01d46a84a7d2c19c674132
+Z 26a14ee919721f442cbec402bfe3cacc
 # Remove this line to create a well-formed Fossil manifest.
index c0135891e4e8dd526c9db1b781fdaf61deaa17a5..1a3cc18d0b0022145b6d756bbff7f8d7bdfb7d85 100644 (file)
@@ -1 +1 @@
-ad8b48d6326b253e5d62dd262130820e4e6e56896abf17ddc6f1f7802204503a
\ No newline at end of file
+2cd49df502a7cd250c453cbbd6a2651e588d69dd755bbdf5a55b58715e548760
\ No newline at end of file
index 0369d4aa35bf473409909b9e408fe1ed8bb79b22..fcac113c064cd6d9e1c3d1e99994f2e70e4aef51 100644 (file)
@@ -1,3 +1,16 @@
+/*
+** 2022 April 8
+**
+** 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.
+**
+*************************************************************************
+*/
+
 #ifndef SQLITE3SHX_H
 #define SQLITE3SHX_H
 #include <stdio.h>
index 5b4641f0e262b0646ea8c27893295617e1eeb804..809cd427fc139d1209e4e415169941089f87b288 100644 (file)
 **
 *************************************************************************
 ** Test extension for testing the shell's .load -shellext ... function.
-** gcc -shared -fPIC -Wall -I. -I.. -g test_shellext.c -o test_shellext.so
+** To build from the SQLite project root:
+** gcc -shared -fPIC -Wall -I. -g src/test_shellext.c -o test_shellext.so
 */
 #include <stdio.h>
-#include "shext_linkage.h"
+#include "shx_link.h"
 
 SQLITE_EXTENSION_INIT1;
 
index 7e98b4bdcc6a0b1231174c8ffce1dcf414f7eeae..0d3e270ea963e2b1fb9a0f996a6b0042ebd170ff 100755 (executable)
@@ -19,20 +19,28 @@ set ::help {
  mkshellc.tcl <options>
   <options> may be either --help, --details, --parameters or any sequence of:
     <input_filename>
+    -header-gen
     -ignored <signed_command_list>
     -inc-type <inc_type>=<include_filename>
+    -short-head
     -source-tags <tags_degree>
     -top-dir <project_root>
     -tcl
  If no input files are specified, <PROJECT_ROOT>/src/shell.c.in is read.
  Input files are read and processed in order, producing output to sdout.
 
+ The -header-gen option alters the treatment of #include directives for
+ generation of .h files to be amassed and used in top-level, .c sources.
+
  The -ignored option affects a list of commands which, during processing,
  will be ignored and generate no output. The list starts empty.
 
  The -inc-type option associates a filename with an <inc_type> word which
  may be used during execution of INCLUDE(...) directives in the input.
 
+ The -short-head option is used for generation of include files to emit
+ a shorter, "DO NOT EDIT" prefix with fewer stated assumptions.
+
  The -source-tags option sets the degree of #line directive emission via
  the <tags_degree> value. 0 turns tagging off. 1, which is the default,
  yields tagging only on source file switching. 2 also produces tagging in
@@ -49,11 +57,18 @@ set ::helpMore {
  Use --parameters option for CONFIGURE_DISPATCH parameter names and effects.
 }
 
+set ::headCommentShort {/* DO NOT EDIT!
+** This file is automatically generated by the script in the canonical
+** SQLite source tree at tool/mkshellc.tcl.  That script combines and
+** transforms code from various source files within the SQLite project
+** into this single OUT_FILE file to simplify out-of-tree builds.
+*/}
+
 set ::headComment {/* DO NOT EDIT!
 ** This file is automatically generated by the script in the canonical
 ** SQLite source tree at tool/mkshellc.tcl.  That script combines and
 ** transforms code from various constituent source files of SQLite into
-** this single OUT_FILE file to implement TARGET_PROGRAM.
+** this single OUT_FILE file to implement the SQLite command-line shell.
 **
 ** Much of the code found below comes from the SOURCE_FILE file in
 ** the canonical SQLite source tree.  That main file contains "INCLUDE"
@@ -69,11 +84,29 @@ set ::headComment {/* DO NOT EDIT!
 ** then rerun the tool/mkshellc.tcl script.
 */}
 
-set ::headCommentLines [expr 1+[regexp -all "\n" $::headComment]]
+set ::useShortHead 0
+
+proc prepare_emit_header {ostr outFile srcFile targPgm} {
+  if {$::useShortHead} {
+    upvar #0 ::headCommentShort head
+  } else {
+    upvar #0 ::headComment head
+  }
+  set hcNumLines [expr 1+[regexp -all "\n" $head]]
+  set hc [regsub -all {OUT_FILE} $head $outFile]
+  set hc [regsub -all {SOURCE_FILE} $hc $srcFile]
+  set hc [regsub -all {TARGET_PROGRAM} $hc $targPgm]
+  emit_sync [list $hc] $ostr $hcNumLines
+}
 
 set ::topDir [file dir [file dir [file normal $argv0]]]
 set runMode normal
 
+# Whether generation is for a top-level .c file or an .h header file.
+# This affects when #include "x" is treated as INCLUDE x and other
+# details of #include pass-thru or suppression (via commenting).
+set ::topLevelGen 1
+
 set ::lineTags 0 ; # 0 => none, 1 => source change, 2 => line syncs, 3 => more
 
 set ::tclGenerate 0
@@ -106,6 +139,8 @@ while  {[llength $argv] > 0} {
       exit 1 
     }
     set ::incTypes($k) $v
+  } elseif {$opt eq "-header-gen"} {
+    set ::topLevelGen 0
   } elseif {$opt eq "-top-dir"} {
     set ::topDir [lshift argv]
     if {::topDir eq ""} { set ::topDir . }
@@ -114,6 +149,8 @@ while  {[llength $argv] > 0} {
     if {![regexp {^\d$} $nextOpt ::lineTags]} {
       puts stderr "Argument following -source-tags must be a digit."
     }
+  } elseif {$opt eq "-short-head"} {
+    set ::useShortHead 1
   } elseif {$opt eq "-tcl"} {
     puts stderr "Warning: Tcl extension not implemented."
     set ::tclGenerate 1
@@ -175,7 +212,7 @@ proc get_src_tags {which cmd} {
 # To faciliate non-excessive line tagging, track these values before emits:
 # These 2 variables are set/used only by procs line_tag and emit_sync .
 set ::apparentSrcFile ""
-set ::apparentSrcPrecLines $::headCommentLines
+set ::apparentSrcPrecLines 0
 
 # Maybe put a #line directive if ::lineTags not 0. Directive style depends
 # on its value and whether srcFile input is provided as follows:
@@ -709,15 +746,36 @@ proc transform_line {lineVar nesting} {
       set ::typedefsSeen($line) 1
     }
     return 0
-  } elseif {$nesting == 0} {
+  } elseif {$nesting == 0 && $::topLevelGen} {
     return 0
   }
-  if {[regexp {^#include "sqlite.*"} $line]
-    || [regexp {^# *include "test_windirent.h"} $line]} {
-    set line "/* $line */"
-    return 1
+  # This next logic needs to be re-thought and rewritten. It was highly
+  # specialized to generate shell.c, and then complexified to generate
+  # other sources, to the detriment of clarity and robustness. Presently,
+  # topLevelGen 1 is used for shell.c and other C source(s), and 0 is used
+  # for generated .h files.
+  if {[regexp {^# *include } $line]} {
+    if {$::topLevelGen} {
+      set noInc [regexp {^# *include "test_windirent.h"} $line]
+      incr noInc [regexp {^#include "sqlite.*"} $line]
+      if {$noInc > 0} {
+        set line "/* $line */"
+        return 1
+      }
+    } else {
+      set pass [regexp {^# *include "sqlite3.h"} $line]
+      if {$pass} {
+        set block [info exists ::includesDone(sqlite3.h)]
+        if {!$block} {
+          set ::includesDone(sqlite3.h) 1
+        } else {
+          set line "/* $line */"
+        }
+        return 1
+      }
+    }
   }
-  if {$nesting > 0 && [regexp {^#include "([\w\.]+)"} $line _ incRelPath]} {
+  if {[regexp {^#include "([\w\.]+)"} $line _ incRelPath]} {
     set fromPath [lindex $::incFileStack end]
     set incPath [file join [file dirname $fromPath] $incRelPath]
     set inTree [file exists $incPath]
@@ -833,10 +891,9 @@ if {$runMode == "help"} {
 if {$runMode == "normal"} {
   fconfigure $outStrm -translation {auto lf}
   set infName [lindex $::inFiles 0]
-  set hc [regsub -all {OUT_FILE} $::headComment $::presumedOutfile]
-  set hc [regsub -all {SOURCE_FILE} $hc "\"$::topInfile\""]
-  set hc [regsub -all {TARGET_PROGRAM} $hc "$::targetProgram"]
-  emit_sync [list $hc] $outStrm $::headCommentLines
+  prepare_emit_header  $outStrm \
+      $::presumedOutfile "\"$::topInfile\"" "$::targetProgram"
   foreach {f} $::inFiles {
     process_file $f $outStrm
   }