mirror of
https://github.com/sqlite/sqlite.git
synced 2024-11-21 19:29:09 +01:00
c73b85c156
FossilOrigin-Name: 80f3bf8c2ee31ba1ab9187d64d5dcbbf97a61845a21b036f89ea9133153575c0
168 lines
4.7 KiB
Tcl
Executable File
168 lines
4.7 KiB
Tcl
Executable File
#!/usr/bin/tclsh
|
|
#
|
|
# Use this script to build C-language source code for a program that uses
|
|
# tclsqlite.c together with custom TCL scripts and/or C extensions for
|
|
# either SQLite or TCL.
|
|
#
|
|
# Usage example:
|
|
#
|
|
# tclsh mkccode.tcl -DENABLE_FEATURE_XYZ demoapp.c.in >demoapp.c
|
|
#
|
|
# The demoapp.c.in file contains a mixture of C code, TCL script, and
|
|
# processing directives used by mktclsqliteprog.tcl to build the final C-code
|
|
# output file. Most lines of demoapp.c.in are copied straight through into
|
|
# the output. The following control directives are recognized:
|
|
#
|
|
# BEGIN_STRING
|
|
#
|
|
# This marks the beginning of large string literal - usually a TCL
|
|
# script of some kind. Subsequent lines of text through the first
|
|
# line that begins with END_STRING are converted into a C-language
|
|
# string literal.
|
|
#
|
|
# INCLUDE path
|
|
#
|
|
# The path argument is the name of a file to be inserted in place of
|
|
# the INCLUDE line. The path can begin with $ROOT to signify the
|
|
# root of the SQLite source tree, or $HOME to signify the directory
|
|
# that contains the demoapp.c.in input script itself. If the path does
|
|
# not begin with either $ROOT or $HOME, then it is interpreted relative
|
|
# to the current working directory.
|
|
#
|
|
# If the INCLUDE occurs in the middle of BEGIN_STRING...END_STRING
|
|
# then all of the text in the input file is converted into C-language
|
|
# string literals.
|
|
#
|
|
# IFDEF macro
|
|
# IFNDEF macro
|
|
# ELSE
|
|
# ENDIF
|
|
#
|
|
# The text from "IFDEF macro" down to the next ELSE or ENDIF is
|
|
# included only if -Dmacro appears as a command-line argument.
|
|
# The "IFNDEF macro" simply inverts the initial test.
|
|
#
|
|
# None of the control directives described above will nest. Only the
|
|
# top-level input file ("demoapp.c.in" in the example) is interpreted.
|
|
# referenced files are copied verbatim.
|
|
#
|
|
proc usage {} {
|
|
puts stderr "Usage: $::argv0 \[OPTIONS\] TEMPLATE >OUTPUT"
|
|
exit 1
|
|
}
|
|
set infile {}
|
|
foreach ax $argv {
|
|
if {[string match -D* $ax]} {
|
|
if {[string match *=* $ax]} {
|
|
regexp -- {-D([^=]+)=(.*)} $ax all name value
|
|
set DEF($name) $value
|
|
} else {
|
|
set DEF([string range $ax 2 end]) 1
|
|
}
|
|
continue
|
|
}
|
|
if {[string match -* $ax]} {
|
|
puts stderr "$::argv0: Unknown option \"$ax\""
|
|
usage
|
|
}
|
|
if {$infile!=""} {
|
|
puts stderr "$::argv0: Surplus argument: \"$ax\""
|
|
usage
|
|
}
|
|
set infile $ax
|
|
}
|
|
set ROOT [file normalize [file dir $argv0]/..]
|
|
set HOME [file normalize [file dir $infile]]
|
|
set in [open $infile rb]
|
|
puts [subst {/* DO NOT EDIT
|
|
**
|
|
** This file was generated by \"$argv0 $argv\".
|
|
** To make changes, edit $infile then rerun the generator
|
|
** command.
|
|
*/}]
|
|
set instr 0
|
|
set omit {}
|
|
set nomit 0
|
|
set ln 0
|
|
while {1} {
|
|
set line [gets $in]
|
|
incr ln
|
|
if {[eof $in]} break
|
|
if {[regexp {^INCLUDE (.*)} $line all path]} {
|
|
if {$nomit>0 && [string match *1* $omit]} continue
|
|
if {0} {
|
|
# https://github.com/msteveb/jimtcl/issues/320
|
|
regsub {^\$ROOT\y} $path $ROOT path
|
|
regsub {^\$HOME\y} $path $HOME path
|
|
} else {
|
|
set path [string map "\$ROOT $ROOT" $path]
|
|
set path [string map "\$HOME $HOME" $path]
|
|
# or: set path [string map "\$HOME $HOME \$ROOT $ROOT" $path]
|
|
}
|
|
set in2 [open $path rb]
|
|
puts "/* INCLUDE $path */"
|
|
if {$instr} {
|
|
while {1} {
|
|
set line [gets $in2]
|
|
if {[eof $in2]} break
|
|
set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
|
|
puts "\"$x\\n\""
|
|
}
|
|
} else {
|
|
puts [read $in2]
|
|
}
|
|
puts "/* END $path */"
|
|
close $in2
|
|
continue
|
|
}
|
|
if {[regexp {^BEGIN_STRING} $line]} {
|
|
set instr 1
|
|
puts "/* BEGIN_STRING */"
|
|
continue
|
|
}
|
|
if {[regexp {^END_STRING} $line]} {
|
|
set instr 0
|
|
puts "/* END_STRING */"
|
|
continue
|
|
}
|
|
if {[regexp {^IFNDEF +([A-Za-z_0-9]+)} $line all name]} {
|
|
set omit $omit[info exists DEF($name)]
|
|
incr nomit
|
|
continue
|
|
}
|
|
if {[regexp {^IFDEF +([A-Za-z_0-9]+)} $line all name]} {
|
|
set omit $omit[expr {![info exists DEF($name)]}]
|
|
incr nomit
|
|
continue
|
|
}
|
|
if {[regexp {^ELSE} $line]} {
|
|
if {!$nomit} {
|
|
puts stderr "$infile:$ln: ELSE without a prior IFDEF"
|
|
exit 1
|
|
}
|
|
set omit [string range $omit 0 end-1][expr {![string index $omit end]}]
|
|
continue
|
|
}
|
|
if {[regexp {^ENDIF} $line]} {
|
|
if {!$nomit} {
|
|
puts stderr "$infile:$ln: ENDIF without a prior IFDEF"
|
|
exit 1
|
|
}
|
|
incr nomit -1
|
|
set omit [string range $omit 0 [expr {$nomit-1}]]
|
|
continue
|
|
}
|
|
if {$nomit>0 && [string match *1* $omit]} {
|
|
# noop
|
|
} elseif {$instr} {
|
|
set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
|
|
puts "\"$x\\n\""
|
|
} else {
|
|
puts $line
|
|
}
|
|
}
|
|
if {$nomit} {
|
|
puts stderr "$infile:$ln: One or more unterminated IFDEFs"
|
|
exit 1
|
|
}
|