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