| #!/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 mktclsqliteprog.tcl 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. |
| # |
| # 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. |
| # |
| if {[llength $argv]!=1} { |
| puts stderr "Usage: $argv0 TEMPLATE >OUTPUT" |
| exit 1 |
| } |
| set infile [lindex $argv 0] |
| 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 $infile\". |
| ** To make changes, edit $infile then rerun the generator |
| ** command. |
| */}] |
| set instr 0 |
| while {1} { |
| set line [gets $in] |
| if {[eof $in]} break |
| if {[regexp {^INCLUDE (.*)} $line all path]} { |
| regsub {^\$ROOT\y} $path $ROOT path |
| regsub {^\$HOME\y} $path $HOME 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 {$instr} { |
| set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line] |
| puts "\"$x\\n\"" |
| } else { |
| puts $line |
| } |
| } |