PRAGMA cipher_default_settings queries current default SQLCipher options
[sqlcipher.git] / tool / mksqlite3c.tcl
blob5a1de8b41bf022e9bf712c4b16b58082810efb9f
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 crypto.h
97 sqlcipher.h
98 btree.h
99 btreeInt.h
100 fts3.h
101 fts3Int.h
102 fts3_hash.h
103 fts3_tokenizer.h
104 geopoly.c
105 hash.h
106 hwtime.h
107 keywordhash.h
108 msvc.h
109 mutex.h
110 opcodes.h
111 os_common.h
112 os_setup.h
113 os_win.h
114 os.h
115 pager.h
116 parse.h
117 pcache.h
118 pragma.h
119 rtree.h
120 sqlite3session.h
121 sqlite3.h
122 sqlite3ext.h
123 sqlite3rbu.h
124 sqliteicu.h
125 sqliteInt.h
126 sqliteLimit.h
127 vdbe.h
128 vdbeInt.h
129 vxworks.h
130 wal.h
131 whereInt.h
133 set available_hdr($hdr) 1
135 set available_hdr(sqliteInt.h) 0
136 set available_hdr(sqlite3session.h) 0
138 # These headers should be copied into the amalgamation without modifying any
139 # of their function declarations or definitions.
140 set varonly_hdr(sqlite3.h) 1
142 # These are the functions that accept a variable number of arguments. They
143 # always need to use the "cdecl" calling convention even when another calling
144 # convention (e.g. "stcall") is being used for the rest of the library.
145 set cdecllist {
146 sqlite3_config
147 sqlite3_db_config
148 sqlite3_log
149 sqlite3_mprintf
150 sqlite3_snprintf
151 sqlite3_test_control
152 sqlite3_vtab_config
155 # 78 stars used for comment formatting.
156 set s78 \
157 {*****************************************************************************}
159 # Insert a comment into the code
161 proc section_comment {text} {
162 global out s78
163 set n [string length $text]
164 set nstar [expr {60 - $n}]
165 set stars [string range $s78 0 $nstar]
166 puts $out "/************** $text $stars/"
169 # Read the source file named $filename and write it into the
170 # sqlite3.c output file. If any #include statements are seen,
171 # process them appropriately.
173 proc copy_file {filename} {
174 global seen_hdr available_hdr varonly_hdr cdecllist out
175 global addstatic linemacros useapicall
176 set ln 0
177 set tail [file tail $filename]
178 section_comment "Begin file $tail"
179 if {$linemacros} {puts $out "#line 1 \"$filename\""}
180 set in [open $filename r]
181 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
182 set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
183 if {[file extension $filename]==".h"} {
184 set declpattern " *$declpattern"
186 set declpattern ^$declpattern\$
187 while {![eof $in]} {
188 set line [gets $in]
189 incr ln
190 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
191 if {[info exists available_hdr($hdr)]} {
192 if {$available_hdr($hdr)} {
193 if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
194 set available_hdr($hdr) 0
196 section_comment "Include $hdr in the middle of $tail"
197 copy_file tsrc/$hdr
198 section_comment "Continuing where we left off in $tail"
199 if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
200 } else {
201 # Comment out the entire line, replacing any nested comment
202 # begin/end markers with the harmless substring "**".
203 puts $out "/* [string map [list /* ** */ **] $line] */"
205 } elseif {![info exists seen_hdr($hdr)]} {
206 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
207 set seen_hdr($hdr) 1
209 puts $out $line
210 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
211 # This include file must be kept because there was a "keep"
212 # directive inside of a line comment.
213 puts $out $line
214 } else {
215 # Comment out the entire line, replacing any nested comment
216 # begin/end markers with the harmless substring "**".
217 puts $out "/* [string map [list /* ** */ **] $line] */"
219 } elseif {[regexp {^#ifdef __cplusplus} $line]} {
220 puts $out "#if 0"
221 } elseif {!$linemacros && [regexp {^#line} $line]} {
222 # Skip #line directives.
223 } elseif {$addstatic
224 && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
225 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
226 # functions if this header file does not need it.
227 if {![info exists varonly_hdr($tail)]
228 && [regexp $declpattern $line all rettype funcname rest]} {
229 regsub {^SQLITE_API } $line {} line
230 regsub {^SQLITE_API } $rettype {} rettype
232 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
233 # so that linkage can be modified at compile-time.
234 if {[regexp {^sqlite3[a-z]*_} $funcname]} {
235 set line SQLITE_API
236 append line " " [string trim $rettype]
237 if {[string index $rettype end] ne "*"} {
238 append line " "
240 if {$useapicall} {
241 if {[lsearch -exact $cdecllist $funcname] >= 0} {
242 append line SQLITE_CDECL " "
243 } else {
244 append line SQLITE_APICALL " "
247 append line $funcname $rest
248 if {$funcname=="sqlite3_sourceid" && !$linemacros} {
249 # The sqlite3_sourceid() routine is synthesized at the end of
250 # the amalgamation
251 puts $out "/* $line */"
252 } else {
253 puts $out $line
255 } else {
256 puts $out "SQLITE_PRIVATE $line"
258 } elseif {[regexp $varpattern $line all varname]} {
259 # Add the SQLITE_PRIVATE before variable declarations or
260 # definitions for internal use
261 regsub {^SQLITE_API } $line {} line
262 if {![regexp {^sqlite3_} $varname]} {
263 regsub {^extern } $line {} line
264 puts $out "SQLITE_PRIVATE $line"
265 } else {
266 if {[regexp {const char sqlite3_version\[\];} $line]} {
267 set line {const char sqlite3_version[] = SQLITE_VERSION;}
269 regsub {^SQLITE_EXTERN } $line {} line
270 puts $out "SQLITE_API $line"
272 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
273 regsub {^SQLITE_API } $line {} line
274 regsub {^SQLITE_EXTERN } $line {} line
275 puts $out $line
276 } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
277 regsub {^SQLITE_API } $line {} line
278 puts $out "SQLITE_PRIVATE $line"
279 } else {
280 puts $out $line
282 } else {
283 puts $out $line
286 close $in
287 section_comment "End of $tail"
291 # Process the source files. Process files containing commonly
292 # used subroutines first in order to help the compiler find
293 # inlining opportunities.
296 foreach file {
297 ctime.c
298 sqliteInt.h
300 crypto.c
301 crypto_impl.c
302 crypto_libtomcrypt.c
303 crypto_openssl.c
304 crypto_cc.c
306 global.c
307 status.c
308 date.c
309 os.c
311 fault.c
312 mem0.c
313 mem1.c
314 mem2.c
315 mem3.c
316 mem5.c
317 mutex.c
318 mutex_noop.c
319 mutex_unix.c
320 mutex_w32.c
321 malloc.c
322 printf.c
323 treeview.c
324 random.c
325 threads.c
326 utf.c
327 util.c
328 hash.c
329 opcodes.c
331 os_unix.c
332 os_win.c
333 memdb.c
335 bitvec.c
336 pcache.c
337 pcache1.c
338 rowset.c
339 pager.c
340 wal.c
342 btmutex.c
343 btree.c
344 backup.c
346 vdbemem.c
347 vdbeaux.c
348 vdbeapi.c
349 vdbetrace.c
350 vdbe.c
351 vdbeblob.c
352 vdbesort.c
353 memjournal.c
355 walker.c
356 resolve.c
357 expr.c
358 alter.c
359 analyze.c
360 attach.c
361 auth.c
362 build.c
363 callback.c
364 delete.c
365 func.c
366 fkey.c
367 insert.c
368 legacy.c
369 loadext.c
370 pragma.c
371 prepare.c
372 select.c
373 table.c
374 trigger.c
375 update.c
376 upsert.c
377 vacuum.c
378 vtab.c
379 wherecode.c
380 whereexpr.c
381 where.c
382 window.c
384 parse.c
386 tokenize.c
387 complete.c
389 main.c
390 notify.c
392 fts3.c
393 fts3_aux.c
394 fts3_expr.c
395 fts3_hash.c
396 fts3_porter.c
397 fts3_tokenizer.c
398 fts3_tokenizer1.c
399 fts3_tokenize_vtab.c
400 fts3_write.c
401 fts3_snippet.c
402 fts3_unicode.c
403 fts3_unicode2.c
405 json1.c
406 rtree.c
407 icu.c
409 fts3_icu.c
410 sqlite3rbu.c
411 dbstat.c
412 dbpage.c
413 sqlite3session.c
414 fts5.c
415 stmt.c
417 copy_file tsrc/$file
420 # Synthesize an alternative sqlite3_sourceid() implementation that
421 # that tries to detects changes in the amalgamation source text
422 # and modify returns a modified source-id if changes are detected.
424 # The only detection mechanism we have is the __LINE__ macro. So only
425 # edits that changes the number of lines of source code are detected.
427 if {!$linemacros} {
428 flush $out
429 set in2 [open sqlite3.c]
430 set cnt 0
431 set oldsrcid {}
432 while {![eof $in2]} {
433 incr cnt
434 gets $in2 line
435 if {[regexp {^#define SQLITE_SOURCE_ID } $line]} {set oldsrcid $line}
437 close $in2
438 regsub {[0-9a-flt]{4}"} $oldsrcid {alt2"} oldsrcid
439 puts $out \
440 "#if __LINE__!=[expr {$cnt+0}]
441 #undef SQLITE_SOURCE_ID
442 $oldsrcid
443 #endif
444 /* Return the source-id for this library */
445 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
447 puts $out \
448 "/************************** End of sqlite3.c ******************************/"
450 close $out