xref: /sqlite-3.40.0/tool/mkccode.tcl (revision 903b2302)
1#!/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}
94