File size: 4,744 Bytes
7510827
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/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 {[lindex $argv 0]!=""} {
  set output_file [lindex $argv 0]
  file delete -force $output_file
  set out [open $output_file wb]
} else {
  set output_file {}
}

############################## FIRST PASS ################################
# Read through the shell.c.in source file to gather information.  Do not
# yet generate any code
#
set in [open $topdir/src/shell.c.in]
fconfigure $in -translation binary
set allSource(src/shell.c.in) 1
set inUsage 0
set dotcmd {}
while {1} {
  set lx [gets $in]
  if {[eof $in]} break;
  if {[regexp {^INCLUDE } $lx]} {
    set cfile [lindex $lx 1]
    if {[string match ../* $cfile]} {
      set xfile [string range $cfile 3 end]
    } else {
      set xfile "src/$cfile"
    }
    set allSource($xfile) 1
  } elseif {[regexp {^\*\* USAGE:\s+([^\s]+)} $lx all dotcmd]} {
    set inUsage 1
    set details [string trim [string range $lx 2 end]]
  } elseif {$inUsage} {
    if {![regexp {^\*\*} $lx] || [regexp { DOT-COMMAND: } $lx]} {
      set inUsage 0
      set Usage($dotcmd) [string trim $details]
    } else {
      append details \n
      append details [string range [string trimright $lx] 3 end]
    }
  }
}

# Generate dot-command usage text based on the data accumulated in
# the Usage() array.
#
proc generate_usage {out} {
  global Usage
  puts $out "/**************************************************************"
  puts $out "** \"Usage\" help text automatically generated from comments */"
  puts $out "static const struct \173"
  puts $out "  const char *zCmd;   /* Name of the dot-command */"
  puts $out "  const char *zUsage; /* Documentation */"
  puts $out "\175 aUsage\[\] = \173"
  foreach dotcmd [array names Usage] {
     puts $out "  \173 \"$dotcmd\","
     foreach line [split $Usage($dotcmd) \n] {
       set x [string map [list \\ \\\\ \" \\\"] $line]
       puts $out "\"$x\\n\""
     }
     puts $out "  \175,"
  }
  puts $out "\175;"
}
# generate_usage stderr

###### SECOND PASS #######
# Make a second pass through shell.c.in to generate the the final
# output, based on data gathered during the first pass.
#

puts $out {/*
** This is the amalgamated source code to the "sqlite3" or "sqlite3.exe"
** command-line shell (CLI) for SQLite.  This file is automatically
** generated by the tool/mkshellc.tcl script from the following sources:
**}
foreach fn [lsort [array names allSource]] {
  puts $out "**   $fn"
}
puts $out {**
** To modify this program, get a copy of the canonical SQLite source tree,
** edit the src/shell.c.in file and/or some of the other files that are
** listed above, then rerun the rerun "make shell.c".
*/}
seek $in 0 start
puts $out "/************************* Begin src/shell.c.in ******************/"
proc omit_redundant_typedefs {line} {
  global typedef_seen
  if {[regexp {^typedef .* ([a-zA-Z0-9_]+);} $line all typename]} {
    # --------------------\y jimtcl does not support \y
    if {[info exists typedef_seen($typename)]} {
      return "/* [string map {/* // */ //} $line] */"
    }
    set typedef_seen($typename) 1
  }
  return $line
}
set iLine 0
while {1} {
  set lx [omit_redundant_typedefs [gets $in]]
  if {[eof $in]} break;
  incr iLine
  if {[regexp {^INCLUDE } $lx]} {
    set cfile [lindex $lx 1]
    if {[string match ../* $cfile]} {
      set xfile [string range $cfile 3 end]
    } else {
      set xfile "src/$cfile"
    }
    puts $out "/************************* Begin $xfile ******************/"
#   puts $out "#line 1 \"$xfile\""
    set in2 [open $topdir/$xfile]
    fconfigure $in2 -translation binary
    while {![eof $in2]} {
      set lx [omit_redundant_typedefs [gets $in2]]
      if {[regexp {^# *include "sqlite} $lx]} {
        set lx "/* $lx */"
      }
      if {[regexp {^# *include "windirent.h"} $lx]} {
        set lx "/* $lx */"
      }
      set lx [string map [list __declspec(dllexport) {}] $lx]
      puts $out $lx
    }
    close $in2
    puts $out "/************************* End $xfile ********************/"
#   puts $out "#line [expr $iLine+1] \"shell.c.in\""
  } elseif {[regexp {^INSERT-USAGE-TEXT-HERE} $lx]} {
    generate_usage $out
  } else {
    puts $out $lx
  }
}
puts $out "/************************* End src/shell.c.in ******************/"
close $in
close $out