]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
General cleanup of mkshellc.tcl, + help and options
authorlarrybr <larrybr@noemail.net>
Wed, 7 Jul 2021 18:23:07 +0000 (18:23 +0000)
committerlarrybr <larrybr@noemail.net>
Wed, 7 Jul 2021 18:23:07 +0000 (18:23 +0000)
FossilOrigin-Name: d1952ff42b26e66d8df45dcf7ba37378d0818b1db3d6df9352db1e30b9ca844e

manifest
manifest.uuid
tool/mkshellc.tcl

index 836c2d1f8ad3cfc8aa889849c7734e049102534b..110e6573f58be725932ff8e4cfe003e84cade136 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C More\scommands\sdispathed.\sDispatch\stranslation\sparameterized.
-D 2021-07-06T02:07:21.072
+C General\scleanup\sof\smkshellc.tcl,\s+\shelp\sand\soptions
+D 2021-07-07T18:23:07.856
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -1853,7 +1853,7 @@ F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
 F tool/mkopcodeh.tcl 130b88697da6ec5b89b41844d955d08fb62c2552e889dec8c7bcecb28d8f50bd
 F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
 F tool/mkpragmatab.tcl ae5585ae76ca26e4d6ccd5ea9cdebaf5efefb318bf989497a0e846cd711d9ab1
-F tool/mkshellc.tcl e671cba0dfdab17a652530c59ad7c44170f9aa31cda04222ec77079adbf73c9b
+F tool/mkshellc.tcl 71dc8ab36456a3f6af18465695f373842fef258e45f2ff09efcd29f8ac74888f
 F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
 F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
@@ -1919,7 +1919,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P dd76b41a72aca94450fb6f45ff56af95d2adb9275eebe9ca67ebd04a52a63c33
-R 8168cef1e5221cce40797275ada85323
+P 372e3241c9e87144ffb19f7e880e9c75ec80260b0db5aed24474bc2a8d7381e4
+R 5914069a310fab6276249f870b0f38bc
 U larrybr
-Z b0378e746b391ae098a6bfe801e6d972
+Z 7876787ac3b198da43fb5e6bc711a15c
index 60446aa03ffff47c0db59099108bf5812be88843..d35a1ca319430f43cd84c1edc7293bbaec74ba1a 100644 (file)
@@ -1 +1 @@
-372e3241c9e87144ffb19f7e880e9c75ec80260b0db5aed24474bc2a8d7381e4
\ No newline at end of file
+d1952ff42b26e66d8df45dcf7ba37378d0818b1db3d6df9352db1e30b9ca844e
\ No newline at end of file
index b47e4eb92e1e60da5dff821d8bb016abe62ecf94..dec2ae9a27513c6cc999e3214d2f96134a1f8179 100644 (file)
 # and $DIR/../ext/misc.
 #
 set topdir [file dir [file dir [file normal $argv0]]]
+
 set out stdout
-fconfigure stdout -translation {auto lf}
-puts $out {/* DO NOT EDIT!
+
+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
@@ -27,11 +28,44 @@ puts $out {/* DO NOT EDIT!
 ** source file to help make the command-line program easier to compile.
 **
 ** To modify this program, get a copy of the canonical SQLite source tree,
-** edit the src/shell.c.in" and/or some of the other files that are included
-** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
+** edit the src/shell.c.in" and/or some of the other files included by
+** "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
 */}
 
-set in [open $topdir/src/shell.c.in rb]
+ #  -it <inc_type>=<include_filename>
+ #   -tcl
+set customRun 0
+set infiles {}
+array set incTypes [list "*" {}]
+
+while  {[llength $argv] > 0} {
+  set argv [lassign $argv opt]
+  if {[regexp {^-{1,2}((help)|(details))$} $opt ma ho]} {
+    if {$ho eq "help"} { set customRun 2 } else { set customRun 3 }
+  } elseif {[regexp {^-it$} $opt]} {
+    set argv [lassign $argv nextOpt]
+    if {![regexp {^(\w+)=(.+)$} $nextOpt ma k v]} {
+      puts stderr "Get help with --help."
+      exit 1 
+    }
+    set incTypes($k) $v
+    puts stderr "Include types not yet implemented or needed." ; exit 1
+  } elseif {$opt eq "-tcl"} {
+    puts stderr "Tcl extension not yet implemented." ; exit 1
+  } elseif {[regexp {^[^-]} $opt]} {
+    lappend infiles $opt
+    set customRun 1
+  } else {
+    puts stderr "Skipping unknown option: $opt"
+  }
+}
+if {[llength $infiles] == 0} {
+  set in [open $topdir/src/shell.c.in rb]
+} else {
+  set infiles [lassign $infiles infile]
+  set in [open $infile rb]
+}
 
 set ::cmd_help [dict create]
 set ::cmd_dispatch [dict create]
@@ -139,121 +173,199 @@ proc chunkify_help {htin} {
   return $rv
 }
 
-# Perform any input collection or deferred output emits.
-# This function may consume additional lines via hFile.
-# Return number of lines absorbed. A 0 return means the
-# input line lx had no meaning to the shuffle processing,
-# in which case it is emitted as-is.
-proc do_shuffle {hFile lx ostrm} {
+array set ::macroTailREs [list \
+  COLLECT_DISPATCH {^\(\s*([\w\*]+)\s*\)\[} \
+  COLLECT_HELP_TEXT {^\[} \
+  CONDITION_COMMAND {^\(\s*(\w+)\s+([^;]+)\);} \
+  DISPATCH_CONFIG {^\[} \
+  DISPATCHABLE_COMMAND {^\(([\w\? ]+)\)(\S)\s*$} \
+  EMIT_DISPATCH {^\((\d*)\)} \
+  EMIT_HELP_TEXT {^\((\d*)\)} \
+]
+array set ::macroUsages [list \
+  COLLECT_DISPATCH "\[\n   <dispatch table entry lines>\n  \];" \
+  COLLECT_HELP_TEXT "\[\n   <help text lines>\n  \];" \
+  CONDITION_COMMAND "( name pp_expr );" \
+  DISPATCH_CONFIG "\[\n   <NAME=value lines>\n  \];" \
+  DISPATCHABLE_COMMAND "( name args... )\x7B\n   <code lines>\n  \x7D" \
+  EMIT_DISPATCH "( indent );" \
+  EMIT_HELP_TEXT "( indent );" \
+]
+# RE for early discard of non-macro lines, matching all above keywords
+set ::macroKeywordTailRE {^\s{0,8}((?:(?:CO)|(?:DI)|(?:EM))[A-Z_]+)\M(.+)$}
+
+# All macro processor procs return the count of extra input lines consumed.
+
+proc COLLECT_DISPATCH {hFile tailCapture ostrm} {
+  # Collect dispatch table entries, along with ordering info.
   set iAte 0
-  if {![regexp {^\s{0,4}[A-Z]+} $lx]} {
-    puts $ostrm $lx
-  } elseif {[regexp {^COLLECT_HELP_TEXT\[} $lx]} {
-    incr iAte
-    set help_frag {}
-    set lx [gets $hFile]
-    while {![eof $hFile] && ![regexp {^\s*\];} $lx]} {
-      lappend help_frag $lx
-      set lx [gets $hFile]
-      incr iAte
-    }
-    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
-    set na [llength $args]
-    set cmd [lindex $args 0]
-    set naPass [dict get $::dispCfg DC_ARG_COUNT]
-    if {$na > $naPass} {
-      puts stderr "Bad args: $lx"
+  set cmd [lindex $tailCapture 0]
+  set lx [gets $hFile]
+  while {![eof $hFile] && ![regexp {^\s*\];} $lx]} {
+    lappend disp_frag $lx
+    set grabCmd [dict get $::dispCfg CMD_CAPTURE_RE]
+    if {![regexp $grabCmd $lx ma dcmd]} {
+      puts stderr "malformed dispatch element:\n $lx"
+      incr ::iShuffleErrors
+    } elseif {$cmd ne "*" && $dcmd ne $cmd} {
+      puts stderr "misdeclared dispatch element:\n $lx"
+      incr ::iShuffleErrors
     } else {
-      while {$na < $naPass} {
-        if {![dict exists $::dispCfg "DC_ARG${na}_DEFAULT"]} {
-          puts stderr "Too few args: $lx (need $naPass)"
-          incr ::iShuffleErrors
-          break
-        } else {
-          lappend args [subst [dict get $::dispCfg "DC_ARG${na}_DEFAULT"]]
-        }
-        incr na
-      }
-      set body {}
-      while {![eof $hFile]} {
-        set lb [gets $hFile]
-        incr iAte
-        lappend body $lb
-        if {[regexp "^\x7D\\s*\$" $lb]} { break }
-      }
-      for {set aix 1} {$aix < $na} {incr aix} {
-        set av [lindex $args $aix]
-        if {$av eq "?"} {
-          set ai [expr {$aix + 1}]
-          set av [subst [dict get $::dispCfg "DC_ARG${ai}_DEFAULT"]]
-        }
-        set "arg$aix" $av
-      }
-      if {$cmd ne "?"} {
-        set rsct [dict get $::dispCfg STORAGE_CLASS]
-        set rsct "$rsct [dict get $::dispCfg RETURN_TYPE]"
-        set argexp [subst [dict get $::dispCfg ARGS_SIGNATURE]]
-        set fname [subst [dict get $::dispCfg DISPATCHEE_NAME]]
-        set funcOpen "$rsct $fname\($argexp\)\x7B"
-        set dispEntry [subst [dict get $::dispCfg DISPATCH_ENTRY]]
-        emit_conditionally $cmd [linsert $body 0 $funcOpen] $ostrm
-        dict set ::cmd_dispatch $cmd [list $dispEntry]
-      }
+      dict set ::cmd_dispatch $dcmd [list $lx]
     }
-  } elseif {[regexp {^\s*EMIT_HELP_TEXT\((\d*)\)} $lx ma indent]} {
+    set lx [gets $hFile]
     incr iAte
-    foreach htc [lsort [dict keys $::cmd_help]] {
-      emit_conditionally $htc [dict get $::cmd_help $htc] $ostrm
-    }
-  } elseif {[regexp {^COLLECT_DISPATCH\(\s*([\w\*]+)\s*\)\[} $lx ma cmd]} {
+  }
+  incr iAte
+  return $iAte
+}
+proc COLLECT_HELP_TEXT {hFile tailCaptureEmpty ostrm} {
+  # Collect help text table values, along with ordering info.
+  set iAte 0
+  set help_frag {}
+  set lx [gets $hFile]
+  while {![eof $hFile] && ![regexp {^\s*\];} $lx]} {
+    lappend help_frag $lx
+    set lx [gets $hFile]
     incr iAte
+  }
+  incr iAte
+  set ::cmd_help [dict merge $::cmd_help [chunkify_help $help_frag]]
+  return $iAte
+}
+
+proc CONDITION_COMMAND {hFile tailCap ostrm} {
+  # Name a command to be conditionally available, with the condition.
+  condition_command [lindex $tailCap 0] [string trim [lindex $tailCap 1]]
+  return 0
+}
+
+proc DISPATCH_CONFIG {hFile tailCaptureEmpty ostrm} {
+  # Set parameters affecting generated dispatchable command function
+  # signatures and generated dispatch table entries.
+  set iAte 0
+  set def_disp {}
+  set lx [gets $hFile]
+  while {![eof $hFile] && ![regexp {^\s*\];} $lx]} {
+    lappend def_disp $lx
     set lx [gets $hFile]
-    while {![eof $hFile] && ![regexp {^\s*\];} $lx]} {
-      lappend disp_frag $lx
-      set grabCmd [dict get $::dispCfg CMD_CAPTURE_RE]
-      if {![regexp $grabCmd $lx ma dcmd]} {
-        puts stderr "malformed dispatch element:\n $lx"
-        incr ::iShuffleErrors
-      } elseif {$cmd ne "*" && $dcmd ne $cmd} {
-        puts stderr "misdeclared dispatch element:\n $lx"
+    incr iAte
+  }
+  incr iAte
+  foreach line $def_disp {
+    if {[regexp {^\s*(\w+)=(.+)$} $line ma k v]} {
+      dict set ::dispCfg $k $v
+    }
+  }
+  return $iAte
+}
+
+proc DISPATCHABLE_COMMAND {hFile tailCapture ostrm} {
+  # Generate and emit a function definition, maybe wrapped as set by
+  # CONDITION_COMMAND(), and generate/collect its dispatch table entry.
+  lassign $tailCapture args tc
+  if {$tc ne "\x7B"} {
+    yap_usage "DISPATCHABLE_COMMAND($args)$tc" DISPATCHABLE_COMMAND
+    incr $::iShuffleErrors
+    return 0
+  }
+  set iAte 0
+  set args [split [regsub {\s+} [string trim $args] " "]]
+  incr iAte
+  set na [llength $args]
+  set cmd [lindex $args 0]
+  set naPass [dict get $::dispCfg DC_ARG_COUNT]
+  if {$na > $naPass} {
+    puts stderr "Bad args: $lx"
+  } else {
+    while {$na < $naPass} {
+      if {![dict exists $::dispCfg "DC_ARG${na}_DEFAULT"]} {
+        puts stderr "Too few args: $lx (need $naPass)"
         incr ::iShuffleErrors
+        break
       } else {
-        dict set ::cmd_dispatch $dcmd [list $lx]
+        lappend args [subst [dict get $::dispCfg "DC_ARG${na}_DEFAULT"]]
       }
-      set lx [gets $hFile]
-      incr iAte
-    }
-    incr iAte
-  } elseif {[regexp {^\s*EMIT_DISPATCH\((\d*)\)} $lx ma indent]} {
-    incr iAte
-    foreach cmd [lsort [dict keys $::cmd_dispatch]] {
-      emit_conditionally $cmd [dict get $::cmd_dispatch $cmd] $ostrm $indent
+      incr na
     }
-  } elseif {[regexp {^CONDITION_COMMAND\(\s*(\w+)\s+([^;]+)\);} $lx ma cmd pp_expr]} {
-    incr iAte
-    condition_command $cmd [string trim $pp_expr]
-  } elseif {[regexp {^DISPATCH_CONFIG\[} $lx]} {
-    incr iAte
-    set def_disp {}
-    set lx [gets $hFile]
-    while {![eof $hFile] && ![regexp {^\s*\];} $lx]} {
-      lappend def_disp $lx
-      set lx [gets $hFile]
+    set body {}
+    while {![eof $hFile]} {
+      set lb [gets $hFile]
       incr iAte
+      lappend body $lb
+      if {[regexp "^\x7D\\s*\$" $lb]} { break }
     }
-    incr iAte
-    foreach line $def_disp {
-      if {[regexp {^\s*(\w+)=(.+)$} $line ma k v]} {
-        dict set ::dispCfg $k $v
+    for {set aix 1} {$aix < $na} {incr aix} {
+      set av [lindex $args $aix]
+      if {$av eq "?"} {
+        set ai [expr {$aix + 1}]
+        set av [subst [dict get $::dispCfg "DC_ARG${ai}_DEFAULT"]]
       }
+      set "arg$aix" $av
     }
-  } else {
+    if {$cmd ne "?"} {
+      set rsct [dict get $::dispCfg STORAGE_CLASS]
+      set rsct "$rsct [dict get $::dispCfg RETURN_TYPE]"
+      set argexp [subst [dict get $::dispCfg ARGS_SIGNATURE]]
+      set fname [subst [dict get $::dispCfg DISPATCHEE_NAME]]
+      set funcOpen "$rsct $fname\($argexp\)\x7B"
+      set dispEntry [subst [dict get $::dispCfg DISPATCH_ENTRY]]
+      emit_conditionally $cmd [linsert $body 0 $funcOpen] $ostrm
+      dict set ::cmd_dispatch $cmd [list $dispEntry]
+    }
+  }
+  return $iAte
+}
+
+proc EMIT_DISPATCH {hFile tailCap ostrm} {
+  # Emit the collected dispatch table entries, in command order, maybe
+  # wrapped with a conditional construct as set by CONDITION_COMMAND().
+  foreach cmd [lsort [dict keys $::cmd_dispatch]] {
+    emit_conditionally $cmd [dict get $::cmd_dispatch $cmd] $ostrm $tailCap
+  }
+  return 0
+}
+
+proc EMIT_HELP_TEXT {hFile tailCap ostrm} {
+  # Emit the collected help text table entries, in command order, maybe
+  # wrapped with a conditional construct as set by CONDITION_COMMAND().
+  foreach htc [lsort [dict keys $::cmd_help]] {
+    emit_conditionally $htc [dict get $::cmd_help $htc] $ostrm $tailCap
+  }
+  return 0
+}
+
+proc say_usage {macros {extra {}}} {
+  puts stderr "Usage:$extra"
+  foreach m $macros {puts stderr "  $m$::macroUsages($m)"}
+}
+proc yap_usage {got macro} {
+  puts stderr "Bad macro use: $got"
+  say_usage $macro
+}
+
+# Perform any input collection or deferred output emits.
+# This function may consume additional lines via hFile.
+# Return number of lines absorbed. A 0 return means the
+# input line lx had no meaning to the shuffle processing,
+# in which case it is emitted as-is.
+proc do_shuffle {hFile lx ostrm} {
+  set iAte 0
+  if {![regexp $::macroKeywordTailRE $lx ma macro tail] \
+          || ![info exists ::macroTailREs($macro)]} {
     puts $ostrm $lx
+  } else {
+    # It's an attempted macro invocation line. Process or fail and yap.
+    incr iAte ; # Eat the macro and whatever it swallows (if invoked).
+    set tailCap [regexp -inline $::macroTailREs($macro) $tail]
+    if {[llength $tailCap]>0} {
+      # Call like-named proc with any args captured by the corresponding RE.
+      incr iAte [$macro $hFile [lrange $tailCap 1 end] $ostrm]
+    } else {
+      # ToDo: complain
+      incr $::iShuffleErrors
+    }
   }
   return $iAte
 }
@@ -279,6 +391,44 @@ proc transform_line {line nesting} {
   return [string map [list __declspec(dllexport) {}] $line]
 }
 
+if {$customRun == 2} {
+  # Show options and usage
+  say_usage [lsort [array names ::macroUsages]] {
+ mkshellc.tcl <options>
+  <options> may be either --help, --details, or any sequence of:
+    <input_filename>
+    -it <inc_type>=<include_filename>
+    -tcl
+ If no input files are specified, <PROJECT_ROOT>/src/shell.c.in will be
+ read. Input files are read and processed, producing output to sdout.
+ They may include macro lines or line sequences matching any of:
+  INCUDE <file_name>
+  INCUDE(<inc_type>) }
+  puts stderr { Use --details option for effects of these macros.}
+  exit 0
+} elseif {$customRun == 3} {
+  set sfd [open $argv0 r]
+  while {![eof $sfd]} {
+    if {[regexp {^proc ([A-Z_]+\M)} [gets $sfd] ma macro]} {
+      if {[info exists ::macroTailREs($macro)]} {
+        set effects {}
+        while {[regexp {^\s+#\s*(.+)$} [gets $sfd] ma effect]} {
+          lappend effects " $effect"
+        }
+        puts stderr "\nThe $macro macro will:"
+        puts stderr [join $effects "\n"]
+      }
+    }
+  }
+  close $sfd
+  exit 0
+}
+
+fconfigure stdout -translation {auto lf}
+if {$customRun == 0} {
+  puts $out $headComment
+}
+
 set iLine 0
 while {1} {
   set lx [transform_line [gets $in] 0]
@@ -300,11 +450,14 @@ while {1} {
   }
   set iAte [do_shuffle $in $lx $out]
   if {$iAte > 0} {
+if {![regexp {^\d+$} $iAte]} {puts "??? $iAte"}
     incr iLine [expr {$iAte - 1}]
   }
 
 }
-close $in
+if {$customRun < 2} {
+  close $in
+}
 close $out
 
 exit $::iShuffleErrors