blob: 8b4fae82c99c1128a0121c2c311fcbe6d2260a21 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
#!/bin/env tclsh
#
# This script is used to amalgamate C source code files into a single
# unit.
#
# 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 mkccode.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
}
|