Snapshot of upstream SQLite 3.37.2
[sqlcipher.git] / tool / mksqlite3c.tcl
blob9d59e17b166238a47a74f908bb0e577997184257
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
22 # The amalgamated SQLite code will be written into sqlite3.c
25 set help {Usage: tclsh mksqlite3c.tcl <options>
26 where <options> is zero or more of the following with these effects:
27 --nostatic => Do not generate with compile-time modifiable linkage.
28 --linemacros=? => Emit #line directives into output or not. (? = 1 or 0)
29 --useapicall => Prepend functions with SQLITE_APICALL or SQLITE_CDECL.
30 --srcdir $SRC => Specify the directory containing constituent sources.
31 --help => See this.
32 The value setting options default to --linemacros=1 and '--srcdir tsrc' .
35 # Begin by reading the "sqlite3.h" header file. Extract the version number
36 # from in this file. The version number is needed to generate the header
37 # comment of the amalgamation.
40 set addstatic 1
41 set linemacros 0
42 set useapicall 0
43 set srcdir tsrc
45 for {set i 0} {$i<[llength $argv]} {incr i} {
46 set x [lindex $argv $i]
47 if {[regexp {^-?-nostatic$} $x]} {
48 set addstatic 0
49 } elseif {[regexp {^-?-linemacros(?:=([01]))?$} $x ma ulm]} {
50 if {$ulm == ""} {set ulm 1}
51 set linemacros $ulm
52 } elseif {[regexp {^-?-useapicall$} $x]} {
53 set useapicall 1
54 } elseif {[regexp {^-?-srcdir$} $x]} {
55 incr i
56 if {$i==[llength $argv]} {
57 error "No argument following $x"
59 set srcdir [lindex $argv $i]
60 } elseif {[regexp {^-?-((help)|\?)$} $x]} {
61 puts $help
62 exit 0
63 } else {
64 error "unknown command-line option: $x"
67 set in [open $srcdir/sqlite3.h]
68 set cnt 0
69 set VERSION ?????
70 while {![eof $in]} {
71 set line [gets $in]
72 if {$line=="" && [eof $in]} break
73 incr cnt
74 regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
76 close $in
78 # Open the output file and write a header comment at the beginning
79 # of the file.
81 set out [open sqlite3.c w]
82 # Force the output to use unix line endings, even on Windows.
83 fconfigure $out -translation lf
84 set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
85 puts $out [subst \
86 {/******************************************************************************
87 ** This file is an amalgamation of many separate C source files from SQLite
88 ** version $VERSION. By combining all the individual C code files into this
89 ** single large file, the entire code can be compiled as a single translation
90 ** unit. This allows many compilers to do optimizations that would not be
91 ** possible if the files were compiled separately. Performance improvements
92 ** of 5% or more are commonly seen when SQLite is compiled as a single
93 ** translation unit.
95 ** This file is all you need to compile SQLite. To use SQLite in other
96 ** programs, you need this file and the "sqlite3.h" header file that defines
97 ** the programming interface to the SQLite library. (If you do not have
98 ** the "sqlite3.h" header file at hand, you will find a copy embedded within
99 ** the text of this file. Search for "Begin file sqlite3.h" to find the start
100 ** of the embedded sqlite3.h header file.) Additional code files may be needed
101 ** if you want a wrapper to interface SQLite with your choice of programming
102 ** language. The code for the "sqlite3" command-line shell is also in a
103 ** separate file. This file contains only code for the core SQLite library.
105 #define SQLITE_CORE 1
106 #define SQLITE_AMALGAMATION 1}]
107 if {$addstatic} {
108 puts $out \
109 {#ifndef SQLITE_PRIVATE
110 # define SQLITE_PRIVATE static
111 #endif}
114 # Examine the parse.c file. If it contains lines of the form:
116 # "#ifndef SQLITE_ENABLE_UPDATE_LIMIT
118 # then set the SQLITE_UDL_CAPABLE_PARSER flag in the amalgamation.
120 set in [open $srcdir/parse.c]
121 if {[regexp {ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT} [read $in]]} {
122 puts $out "#define SQLITE_UDL_CAPABLE_PARSER 1"
124 close $in
126 # These are the header files used by SQLite. The first time any of these
127 # files are seen in a #include statement in the C code, include the complete
128 # text of the file in-line. The file only needs to be included once.
130 foreach hdr {
131 btree.h
132 btreeInt.h
133 fts3.h
134 fts3Int.h
135 fts3_hash.h
136 fts3_tokenizer.h
137 geopoly.c
138 hash.h
139 hwtime.h
140 keywordhash.h
141 msvc.h
142 mutex.h
143 opcodes.h
144 os_common.h
145 os_setup.h
146 os_win.h
147 os.h
148 pager.h
149 parse.h
150 pcache.h
151 pragma.h
152 rtree.h
153 sqlite3session.h
154 sqlite3.h
155 sqlite3ext.h
156 sqlite3rbu.h
157 sqliteicu.h
158 sqliteInt.h
159 sqliteLimit.h
160 vdbe.h
161 vdbeInt.h
162 vxworks.h
163 wal.h
164 whereInt.h
166 set available_hdr($hdr) 1
168 set available_hdr(sqliteInt.h) 0
169 set available_hdr(os_common.h) 0
170 set available_hdr(sqlite3session.h) 0
172 # These headers should be copied into the amalgamation without modifying any
173 # of their function declarations or definitions.
174 set varonly_hdr(sqlite3.h) 1
176 # These are the functions that accept a variable number of arguments. They
177 # always need to use the "cdecl" calling convention even when another calling
178 # convention (e.g. "stcall") is being used for the rest of the library.
179 set cdecllist {
180 sqlite3_config
181 sqlite3_db_config
182 sqlite3_log
183 sqlite3_mprintf
184 sqlite3_snprintf
185 sqlite3_test_control
186 sqlite3_vtab_config
189 # 78 stars used for comment formatting.
190 set s78 \
191 {*****************************************************************************}
193 # Insert a comment into the code
195 proc section_comment {text} {
196 global out s78
197 set n [string length $text]
198 set nstar [expr {60 - $n}]
199 set stars [string range $s78 0 $nstar]
200 puts $out "/************** $text $stars/"
203 # Read the source file named $filename and write it into the
204 # sqlite3.c output file. If any #include statements are seen,
205 # process them appropriately.
207 proc copy_file {filename} {
208 global seen_hdr available_hdr varonly_hdr cdecllist out
209 global addstatic linemacros useapicall srcdir
210 set ln 0
211 set tail [file tail $filename]
212 section_comment "Begin file $tail"
213 if {$linemacros} {puts $out "#line 1 \"$filename\""}
214 set in [open $filename r]
215 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
216 set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
217 if {[file extension $filename]==".h"} {
218 set declpattern " *$declpattern"
220 set declpattern ^$declpattern\$
221 while {![eof $in]} {
222 set line [string trimright [gets $in]]
223 incr ln
224 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
225 if {[info exists available_hdr($hdr)]} {
226 if {$available_hdr($hdr)} {
227 set available_hdr($hdr) 0
228 section_comment "Include $hdr in the middle of $tail"
229 copy_file $srcdir/$hdr
230 section_comment "Continuing where we left off in $tail"
231 if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
232 } else {
233 # Comment out the entire line, replacing any nested comment
234 # begin/end markers with the harmless substring "**".
235 puts $out "/* [string map [list /* ** */ **] $line] */"
237 } elseif {![info exists seen_hdr($hdr)]} {
238 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
239 set seen_hdr($hdr) 1
241 puts $out $line
242 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
243 # This include file must be kept because there was a "keep"
244 # directive inside of a line comment.
245 puts $out $line
246 } else {
247 # Comment out the entire line, replacing any nested comment
248 # begin/end markers with the harmless substring "**".
249 puts $out "/* [string map [list /* ** */ **] $line] */"
251 } elseif {[regexp {^#ifdef __cplusplus} $line]} {
252 puts $out "#if 0"
253 } elseif {!$linemacros && [regexp {^#line} $line]} {
254 # Skip #line directives.
255 } elseif {$addstatic
256 && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
257 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
258 # functions if this header file does not need it.
259 if {![info exists varonly_hdr($tail)]
260 && [regexp $declpattern $line all rettype funcname rest]} {
261 regsub {^SQLITE_API } $line {} line
262 regsub {^SQLITE_API } $rettype {} rettype
264 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
265 # so that linkage can be modified at compile-time.
266 if {[regexp {^sqlite3[a-z]*_} $funcname]} {
267 set line SQLITE_API
268 append line " " [string trim $rettype]
269 if {[string index $rettype end] ne "*"} {
270 append line " "
272 if {$useapicall} {
273 if {[lsearch -exact $cdecllist $funcname] >= 0} {
274 append line SQLITE_CDECL " "
275 } else {
276 append line SQLITE_APICALL " "
279 append line $funcname $rest
280 if {$funcname=="sqlite3_sourceid"} {
281 # The sqlite3_sourceid() routine is synthesized at the end of
282 # the amalgamation
283 puts $out "/* $line */"
284 } else {
285 puts $out $line
287 } else {
288 puts $out "SQLITE_PRIVATE $line"
290 } elseif {[regexp $varpattern $line all varname]} {
291 # Add the SQLITE_PRIVATE before variable declarations or
292 # definitions for internal use
293 regsub {^SQLITE_API } $line {} line
294 if {![regexp {^sqlite3_} $varname]} {
295 regsub {^extern } $line {} line
296 puts $out "SQLITE_PRIVATE $line"
297 } else {
298 if {[regexp {const char sqlite3_version\[\];} $line]} {
299 set line {const char sqlite3_version[] = SQLITE_VERSION;}
301 regsub {^SQLITE_EXTERN } $line {} line
302 puts $out "SQLITE_API $line"
304 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
305 regsub {^SQLITE_API } $line {} line
306 regsub {^SQLITE_EXTERN } $line {} line
307 puts $out $line
308 } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
309 regsub {^SQLITE_API } $line {} line
310 puts $out "SQLITE_PRIVATE $line"
311 } else {
312 puts $out $line
314 } else {
315 puts $out $line
318 close $in
319 section_comment "End of $tail"
323 # Process the source files. Process files containing commonly
324 # used subroutines first in order to help the compiler find
325 # inlining opportunities.
327 foreach file {
328 sqliteInt.h
329 os_common.h
330 ctime.c
332 global.c
333 status.c
334 date.c
335 os.c
337 fault.c
338 mem0.c
339 mem1.c
340 mem2.c
341 mem3.c
342 mem5.c
343 mutex.c
344 mutex_noop.c
345 mutex_unix.c
346 mutex_w32.c
347 malloc.c
348 printf.c
349 treeview.c
350 random.c
351 threads.c
352 utf.c
353 util.c
354 hash.c
355 opcodes.c
357 os_unix.c
358 os_win.c
359 memdb.c
361 bitvec.c
362 pcache.c
363 pcache1.c
364 rowset.c
365 pager.c
366 wal.c
368 btmutex.c
369 btree.c
370 backup.c
372 vdbemem.c
373 vdbeaux.c
374 vdbeapi.c
375 vdbetrace.c
376 vdbe.c
377 vdbeblob.c
378 vdbesort.c
379 vdbevtab.c
380 memjournal.c
382 walker.c
383 resolve.c
384 expr.c
385 alter.c
386 analyze.c
387 attach.c
388 auth.c
389 build.c
390 callback.c
391 delete.c
392 func.c
393 fkey.c
394 insert.c
395 legacy.c
396 loadext.c
397 pragma.c
398 prepare.c
399 select.c
400 table.c
401 trigger.c
402 update.c
403 upsert.c
404 vacuum.c
405 vtab.c
406 wherecode.c
407 whereexpr.c
408 where.c
409 window.c
411 parse.c
413 tokenize.c
414 complete.c
416 main.c
417 notify.c
419 fts3.c
420 fts3_aux.c
421 fts3_expr.c
422 fts3_hash.c
423 fts3_porter.c
424 fts3_tokenizer.c
425 fts3_tokenizer1.c
426 fts3_tokenize_vtab.c
427 fts3_write.c
428 fts3_snippet.c
429 fts3_unicode.c
430 fts3_unicode2.c
432 json1.c
433 rtree.c
434 icu.c
435 fts3_icu.c
436 sqlite3rbu.c
437 dbstat.c
438 dbpage.c
439 sqlite3session.c
440 fts5.c
441 stmt.c
443 copy_file $srcdir/$file
446 puts $out \
447 "/* Return the source-id for this library */
448 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
450 puts $out \
451 "/************************** End of sqlite3.c ******************************/"
453 close $out