blob: 727fac459c0f4670560c597bb232a01ef589dc4f [file] [log] [blame] [edit]
#!/usr/bin/tclsh
#
# Run this script to generate the "shell.c" source file from
# constituent parts.
#
# No arguments are required. This script determines the location
# of its input files relative to the location of the script itself.
# This script should be tool/mkshellc.tcl. If the directory holding
# the script is $DIR, then the component parts are located in $DIR/../src
# and $DIR/../ext/misc.
#
set ::topdir [file dir [file dir [file normal $argv0]]]
set ::out stdout
fconfigure stdout -translation binary
if {$argc == 0} {
set inSources [list shell.c.in]
puts $::out {/* DO NOT EDIT!
** This file is automatically generated by the script in the canonical
** SQLite source tree at tool/mkshellc.tcl. That script combines source
** code from various constituent source files of SQLite into this single
** "shell.c" file used to implement the SQLite command-line shell.
**
** Most of the code found below comes from the "src/shell.c.in" file in
** the canonical SQLite source tree. That main file contains "INCLUDE"
** lines that specify other files in the canonical source tree that are
** inserted to getnerate this complete program source file.
**
** The code from multiple files is combined into this single "shell.c"
** source file to help make the command-line program easier to compile.
**
** To modify this program, get a copy of the canonical SQLite source tree,
** edit "src/shell.c.in" and/or some of the other files that are included
** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
*/}
} else {
set inSources $argv
}
array set ::filesInput {}
proc omit_redundant_typedefs {line} {
global typedef_seen
if {[regexp {^typedef .*\y([a-zA-Z0-9_]+);} $line all typename]} {
if {[info exists typedef_seen($typename)]} {
return "/* [string map {/* // */ //} $line] */"
}
set typedef_seen($typename) 1
}
return $line
}
# For INCLUDED files, suppress redundant #include directives and
# eliminate a Windows-specific attribute not needed for the shell.
proc misc_sieve {line} {
if {[regexp {^# *include "([^"]+)"} $line _ finc]} {
set finc [regsub {".*$} $finc ""]
# Project headers #include'd at top level (by shell.c.in), or
# files already the object of INCLUDE, need not be #include'd.
if {[regexp {^sqlite} $finc] || [info exists ::filesInput($finc)]} {
return "/* $line */"
}
}
return [string map [list __declspec(dllexport) {}] $line]
}
# Read, process and emit the named file, and track recursion level.
proc include_file {fname rlevel} {
if {[info exists ::filesInput($fname)]} return ;# Block revisits.
set in [open $::topdir/src/$fname]
fconfigure $in -translation binary
set ::filesInput($fname) 1
if {$rlevel > 0} {
puts $::out "/************************* Begin $fname ******************/"
}
set iLine 0
# puts $::out "#line 1 \"$fname\""
while {![eof $in]} {
set lx [omit_redundant_typedefs [gets $in]]
incr iLine
if {[regexp {^INCLUDE( |\()} $lx _ sep]} {
if {$sep eq " "} {
set ifn [lindex $lx 1]
} elseif {![regexp {^INCLUDE\( *([^ ]+) *\)} $lx _ ifn]} {
puts stderr "Bad INCLUDE at $iLine in $fname"
exit 1
}
include_file $ifn [expr $rlevel + 1]
# puts $::out "#line [expr $iLine+1] \"$fname\""
} else {
if {$rlevel > 0} {
puts $::out [misc_sieve $lx]
} elseif {$lx ne "" || ![eof $in]} {
puts $::out $lx
}
}
}
close $in
if {$rlevel > 0} {
puts $::out "/************************* End $fname ********************/"
}
}
foreach {source} $inSources {
include_file $source 0
}
close $::out