Enhance the command-line completion extension to return the names of
[sqlite.git] / tool / mksqlite3c.tcl
blobf2d93aadd0c852bc265dc4e75c8fd9dd8527aa4a
1 #!/usr/bin/tclsh
3 # To build a single huge source file holding all of SQLite (or at
4 # least the core components - the test harness, shell, and TCL
5 # interface are omitted.) first do
7 # make target_source
9 # The make target above moves all of the source code files into
10 # a subdirectory named "tsrc". (This script expects to find the files
11 # there and will not work if they are not found.) There are a few
12 # generated C code files that are also added to the tsrc directory.
13 # For example, the "parse.c" and "parse.h" files to implement the
14 # the parser are derived from "parse.y" using lemon. And the
15 # "keywordhash.h" files is generated by a program named "mkkeywordhash".
17 # After the "tsrc" directory has been created and populated, run
18 # this script:
20 # tclsh mksqlite3c.tcl --srcdir $SRC
22 # The amalgamated SQLite code will be written into sqlite3.c
25 # Begin by reading the "sqlite3.h" header file. Extract the version number
26 # from in this file. The version number is needed to generate the header
27 # comment of the amalgamation.
29 set addstatic 1
30 set linemacros 0
31 set useapicall 0
32 for {set i 0} {$i<[llength $argv]} {incr i} {
33 set x [lindex $argv $i]
34 if {[regexp {^-+nostatic$} $x]} {
35 set addstatic 0
36 } elseif {[regexp {^-+linemacros} $x]} {
37 set linemacros 1
38 } elseif {[regexp {^-+useapicall} $x]} {
39 set useapicall 1
40 } else {
41 error "unknown command-line option: $x"
44 set in [open tsrc/sqlite3.h]
45 set cnt 0
46 set VERSION ?????
47 while {![eof $in]} {
48 set line [gets $in]
49 if {$line=="" && [eof $in]} break
50 incr cnt
51 regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
53 close $in
55 # Open the output file and write a header comment at the beginning
56 # of the file.
58 set out [open sqlite3.c w]
59 # Force the output to use unix line endings, even on Windows.
60 fconfigure $out -translation lf
61 set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
62 puts $out [subst \
63 {/******************************************************************************
64 ** This file is an amalgamation of many separate C source files from SQLite
65 ** version $VERSION. By combining all the individual C code files into this
66 ** single large file, the entire code can be compiled as a single translation
67 ** unit. This allows many compilers to do optimizations that would not be
68 ** possible if the files were compiled separately. Performance improvements
69 ** of 5% or more are commonly seen when SQLite is compiled as a single
70 ** translation unit.
72 ** This file is all you need to compile SQLite. To use SQLite in other
73 ** programs, you need this file and the "sqlite3.h" header file that defines
74 ** the programming interface to the SQLite library. (If you do not have
75 ** the "sqlite3.h" header file at hand, you will find a copy embedded within
76 ** the text of this file. Search for "Begin file sqlite3.h" to find the start
77 ** of the embedded sqlite3.h header file.) Additional code files may be needed
78 ** if you want a wrapper to interface SQLite with your choice of programming
79 ** language. The code for the "sqlite3" command-line shell is also in a
80 ** separate file. This file contains only code for the core SQLite library.
82 #define SQLITE_CORE 1
83 #define SQLITE_AMALGAMATION 1}]
84 if {$addstatic} {
85 puts $out \
86 {#ifndef SQLITE_PRIVATE
87 # define SQLITE_PRIVATE static
88 #endif}
91 # These are the header files used by SQLite. The first time any of these
92 # files are seen in a #include statement in the C code, include the complete
93 # text of the file in-line. The file only needs to be included once.
95 foreach hdr {
96 btree.h
97 btreeInt.h
98 fts3.h
99 fts3Int.h
100 fts3_hash.h
101 fts3_tokenizer.h
102 hash.h
103 hwtime.h
104 keywordhash.h
105 msvc.h
106 mutex.h
107 opcodes.h
108 os_common.h
109 os_setup.h
110 os_win.h
111 os.h
112 pager.h
113 parse.h
114 pcache.h
115 pragma.h
116 rtree.h
117 sqlite3session.h
118 sqlite3.h
119 sqlite3ext.h
120 sqlite3rbu.h
121 sqliteicu.h
122 sqliteInt.h
123 sqliteLimit.h
124 vdbe.h
125 vdbeInt.h
126 vxworks.h
127 wal.h
128 whereInt.h
130 set available_hdr($hdr) 1
132 set available_hdr(sqliteInt.h) 0
133 set available_hdr(sqlite3session.h) 0
135 # These headers should be copied into the amalgamation without modifying any
136 # of their function declarations or definitions.
137 set varonly_hdr(sqlite3.h) 1
139 # These are the functions that accept a variable number of arguments. They
140 # always need to use the "cdecl" calling convention even when another calling
141 # convention (e.g. "stcall") is being used for the rest of the library.
142 set cdecllist {
143 sqlite3_config
144 sqlite3_db_config
145 sqlite3_log
146 sqlite3_mprintf
147 sqlite3_snprintf
148 sqlite3_test_control
149 sqlite3_vtab_config
152 # 78 stars used for comment formatting.
153 set s78 \
154 {*****************************************************************************}
156 # Insert a comment into the code
158 proc section_comment {text} {
159 global out s78
160 set n [string length $text]
161 set nstar [expr {60 - $n}]
162 set stars [string range $s78 0 $nstar]
163 puts $out "/************** $text $stars/"
166 # Read the source file named $filename and write it into the
167 # sqlite3.c output file. If any #include statements are seen,
168 # process them appropriately.
170 proc copy_file {filename} {
171 global seen_hdr available_hdr varonly_hdr cdecllist out
172 global addstatic linemacros useapicall
173 set ln 0
174 set tail [file tail $filename]
175 section_comment "Begin file $tail"
176 if {$linemacros} {puts $out "#line 1 \"$filename\""}
177 set in [open $filename r]
178 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
179 set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
180 if {[file extension $filename]==".h"} {
181 set declpattern " *$declpattern"
183 set declpattern ^$declpattern\$
184 while {![eof $in]} {
185 set line [gets $in]
186 incr ln
187 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
188 if {[info exists available_hdr($hdr)]} {
189 if {$available_hdr($hdr)} {
190 if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
191 set available_hdr($hdr) 0
193 section_comment "Include $hdr in the middle of $tail"
194 copy_file tsrc/$hdr
195 section_comment "Continuing where we left off in $tail"
196 if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
197 } else {
198 # Comment out the entire line, replacing any nested comment
199 # begin/end markers with the harmless substring "**".
200 puts $out "/* [string map [list /* ** */ **] $line] */"
202 } elseif {![info exists seen_hdr($hdr)]} {
203 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
204 set seen_hdr($hdr) 1
206 puts $out $line
207 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
208 # This include file must be kept because there was a "keep"
209 # directive inside of a line comment.
210 puts $out $line
211 } else {
212 # Comment out the entire line, replacing any nested comment
213 # begin/end markers with the harmless substring "**".
214 puts $out "/* [string map [list /* ** */ **] $line] */"
216 } elseif {[regexp {^#ifdef __cplusplus} $line]} {
217 puts $out "#if 0"
218 } elseif {!$linemacros && [regexp {^#line} $line]} {
219 # Skip #line directives.
220 } elseif {$addstatic
221 && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
222 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
223 # functions if this header file does not need it.
224 if {![info exists varonly_hdr($tail)]
225 && [regexp $declpattern $line all rettype funcname rest]} {
226 regsub {^SQLITE_API } $line {} line
227 regsub {^SQLITE_API } $rettype {} rettype
229 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
230 # so that linkage can be modified at compile-time.
231 if {[regexp {^sqlite3[a-z]*_} $funcname]} {
232 set line SQLITE_API
233 append line " " [string trim $rettype]
234 if {[string index $rettype end] ne "*"} {
235 append line " "
237 if {$useapicall} {
238 if {[lsearch -exact $cdecllist $funcname] >= 0} {
239 append line SQLITE_CDECL " "
240 } else {
241 append line SQLITE_APICALL " "
244 append line $funcname $rest
245 if {$funcname=="sqlite3_sourceid" && !$linemacros} {
246 # The sqlite3_sourceid() routine is synthesized at the end of
247 # the amalgamation
248 puts $out "/* $line */"
249 } else {
250 puts $out $line
252 } else {
253 puts $out "SQLITE_PRIVATE $line"
255 } elseif {[regexp $varpattern $line all varname]} {
256 # Add the SQLITE_PRIVATE before variable declarations or
257 # definitions for internal use
258 regsub {^SQLITE_API } $line {} line
259 if {![regexp {^sqlite3_} $varname]} {
260 regsub {^extern } $line {} line
261 puts $out "SQLITE_PRIVATE $line"
262 } else {
263 if {[regexp {const char sqlite3_version\[\];} $line]} {
264 set line {const char sqlite3_version[] = SQLITE_VERSION;}
266 regsub {^SQLITE_EXTERN } $line {} line
267 puts $out "SQLITE_API $line"
269 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
270 regsub {^SQLITE_API } $line {} line
271 regsub {^SQLITE_EXTERN } $line {} line
272 puts $out $line
273 } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
274 regsub {^SQLITE_API } $line {} line
275 puts $out "SQLITE_PRIVATE $line"
276 } else {
277 puts $out $line
279 } else {
280 puts $out $line
283 close $in
284 section_comment "End of $tail"
288 # Process the source files. Process files containing commonly
289 # used subroutines first in order to help the compiler find
290 # inlining opportunities.
292 foreach file {
293 ctime.c
294 sqliteInt.h
296 global.c
297 status.c
298 date.c
299 os.c
301 fault.c
302 mem0.c
303 mem1.c
304 mem2.c
305 mem3.c
306 mem5.c
307 mutex.c
308 mutex_noop.c
309 mutex_unix.c
310 mutex_w32.c
311 malloc.c
312 printf.c
313 treeview.c
314 random.c
315 threads.c
316 utf.c
317 util.c
318 hash.c
319 opcodes.c
321 os_unix.c
322 os_win.c
323 memdb.c
325 bitvec.c
326 pcache.c
327 pcache1.c
328 rowset.c
329 pager.c
330 wal.c
332 btmutex.c
333 btree.c
334 backup.c
336 vdbemem.c
337 vdbeaux.c
338 vdbeapi.c
339 vdbetrace.c
340 vdbe.c
341 vdbeblob.c
342 vdbesort.c
343 memjournal.c
345 walker.c
346 resolve.c
347 expr.c
348 alter.c
349 analyze.c
350 attach.c
351 auth.c
352 build.c
353 callback.c
354 delete.c
355 func.c
356 fkey.c
357 insert.c
358 legacy.c
359 loadext.c
360 pragma.c
361 prepare.c
362 select.c
363 table.c
364 trigger.c
365 update.c
366 vacuum.c
367 vtab.c
368 wherecode.c
369 whereexpr.c
370 where.c
372 parse.c
374 tokenize.c
375 complete.c
377 main.c
378 notify.c
380 fts3.c
381 fts3_aux.c
382 fts3_expr.c
383 fts3_hash.c
384 fts3_porter.c
385 fts3_tokenizer.c
386 fts3_tokenizer1.c
387 fts3_tokenize_vtab.c
388 fts3_write.c
389 fts3_snippet.c
390 fts3_unicode.c
391 fts3_unicode2.c
393 rtree.c
394 icu.c
395 fts3_icu.c
396 sqlite3rbu.c
397 dbstat.c
398 dbpage.c
399 sqlite3session.c
400 json1.c
401 fts5.c
402 stmt.c
404 copy_file tsrc/$file
407 # Synthesize an alternative sqlite3_sourceid() implementation that
408 # that tries to detects changes in the amalgamation source text
409 # and modify returns a modified source-id if changes are detected.
411 # The only detection mechanism we have is the __LINE__ macro. So only
412 # edits that changes the number of lines of source code are detected.
414 if {!$linemacros} {
415 flush $out
416 set in2 [open sqlite3.c]
417 set cnt 0
418 set oldsrcid {}
419 while {![eof $in2]} {
420 incr cnt
421 gets $in2 line
422 if {[regexp {^#define SQLITE_SOURCE_ID } $line]} {set oldsrcid $line}
424 close $in2
425 regsub {[0-9a-flt]{4}"} $oldsrcid {alt2"} oldsrcid
426 puts $out \
427 "#if __LINE__!=[expr {$cnt+0}]
428 #undef SQLITE_SOURCE_ID
429 $oldsrcid
430 #endif
431 /* Return the source-id for this library */
432 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
434 puts $out \
435 "/************************** End of sqlite3.c ******************************/"
437 close $out