blob: 41b09f1e8100d4258b12c233c993109bcc993a1b [file] [log] [blame]
drh903b2302017-10-13 18:58:55 +00001#!/usr/bin/tclsh
2#
3# Use this script to build C-language source code for a program that uses
4# tclsqlite.c together with custom TCL scripts and/or C extensions for
5# either SQLite or TCL.
6#
7# Usage example:
8#
9# tclsh mktclsqliteprog.tcl demoapp.c.in >demoapp.c
10#
11# The demoapp.c.in file contains a mixture of C code, TCL script, and
12# processing directives used by mktclsqliteprog.tcl to build the final C-code
13# output file. Most lines of demoapp.c.in are copied straight through into
14# the output. The following control directives are recognized:
15#
16# BEGIN_STRING
17#
18# This marks the beginning of large string literal - usually a TCL
19# script of some kind. Subsequent lines of text through the first
20# line that begins with END_STRING are converted into a C-language
21# string literal.
22#
23# INCLUDE path
24#
25# The path argument is the name of a file to be inserted in place of
26# the INCLUDE line. The path can begin with $ROOT to signify the
27# root of the SQLite source tree, or $HOME to signify the directory
28# that contains the demoapp.c.in input script itself. If the path does
29# not begin with either $ROOT or $HOME, then it is interpreted relative
30# to the current working directory.
31#
32# If the INCLUDE occurs in the middle of BEGIN_STRING...END_STRING
33# then all of the text in the input file is converted into C-language
34# string literals.
35#
36# None of the control directives described above will nest. Only the
37# top-level input file ("demoapp.c.in" in the example) is interpreted.
38# referenced files are copied verbatim.
39#
40if {[llength $argv]!=1} {
41 puts stderr "Usage: $argv0 TEMPLATE >OUTPUT"
42 exit 1
43}
44set infile [lindex $argv 0]
45set ROOT [file normalize [file dir $argv0]/..]
46set HOME [file normalize [file dir $infile]]
47set in [open $infile rb]
48puts [subst {/* DO NOT EDIT
49**
50** This file was generated by \"$argv0 $infile\".
51** To make changes, edit $infile then rerun the generator
52** command.
53*/}]
54set instr 0
55while {1} {
56 set line [gets $in]
57 if {[eof $in]} break
58 if {[regexp {^INCLUDE (.*)} $line all path]} {
59 regsub {^\$ROOT\y} $path $ROOT path
60 regsub {^\$HOME\y} $path $HOME path
61 set in2 [open $path rb]
62 puts "/* INCLUDE $path */"
63 if {$instr} {
64 while {1} {
65 set line [gets $in2]
66 if {[eof $in2]} break
67 set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
68 puts "\"$x\\n\""
69 }
70 } else {
71 puts [read $in2]
72 }
73 puts "/* END $path */"
74 close $in2
75 continue
76 }
77 if {[regexp {^BEGIN_STRING} $line]} {
78 set instr 1
79 puts "/* BEGIN_STRING */"
80 continue
81 }
82 if {[regexp {^END_STRING} $line]} {
83 set instr 0
84 puts "/* END_STRING */"
85 continue
86 }
87 if {$instr} {
88 set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
89 puts "\"$x\\n\""
90 } else {
91 puts $line
92 }
93}