log santization and cleanup
[sqlcipher.git] / tool / mksqlite3c.tcl
blobf278d0d8523f6ed1f42bf0133bbb54f90d1071f5
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.
109 **}]
110 set srcroot [file dirname [file dirname [info script]]]
111 if {$tcl_platform(platform)=="windows"} {
112 set vsrcprog src-verify.exe
113 } else {
114 set vsrcprog ./src-verify
116 if {[file executable $vsrcprog] && [file readable $srcroot/manifest]} {
117 set res [string trim [split [exec $vsrcprog -x $srcroot]] \n]
118 puts $out "** The content in this amalgamation comes from Fossil check-in"
119 puts -nonewline $out "** [string range [lindex $res 0] 0 35]"
120 if {[llength $res]==1} {
121 puts $out "."
122 } else {
123 puts $out " with changes in files:\n**"
124 foreach f [lrange $res 1 end] {
125 puts $out "** $f"
128 } else {
129 puts $out "** The origin of the sources used to build this amalgamation"
130 puts $out "** is unknown."
132 puts $out [subst {*/
133 #define SQLITE_CORE 1
134 #define SQLITE_AMALGAMATION 1}]
135 if {$addstatic} {
136 puts $out \
137 {#ifndef SQLITE_PRIVATE
138 # define SQLITE_PRIVATE static
139 #endif}
142 # Examine the parse.c file. If it contains lines of the form:
144 # "#ifndef SQLITE_ENABLE_UPDATE_LIMIT
146 # then set the SQLITE_UDL_CAPABLE_PARSER flag in the amalgamation.
148 set in [open $srcdir/parse.c]
149 if {[regexp {ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT} [read $in]]} {
150 puts $out "#define SQLITE_UDL_CAPABLE_PARSER 1"
152 close $in
154 # These are the header files used by SQLite. The first time any of these
155 # files are seen in a #include statement in the C code, include the complete
156 # text of the file in-line. The file only needs to be included once.
158 foreach hdr {
159 crypto.h
160 sqlcipher.h
161 btree.h
162 btreeInt.h
163 fts3.h
164 fts3Int.h
165 fts3_hash.h
166 fts3_tokenizer.h
167 geopoly.c
168 hash.h
169 hwtime.h
170 keywordhash.h
171 msvc.h
172 mutex.h
173 opcodes.h
174 os_common.h
175 os_setup.h
176 os_win.h
177 os.h
178 pager.h
179 parse.h
180 pcache.h
181 pragma.h
182 rtree.h
183 sqlite3session.h
184 sqlite3.h
185 sqlite3ext.h
186 sqlite3rbu.h
187 sqliteicu.h
188 sqliteInt.h
189 sqliteLimit.h
190 vdbe.h
191 vdbeInt.h
192 vxworks.h
193 wal.h
194 whereInt.h
195 sqlite3recover.h
197 set available_hdr($hdr) 1
199 set available_hdr(sqliteInt.h) 0
200 set available_hdr(os_common.h) 0
201 set available_hdr(sqlite3session.h) 0
203 # These headers should be copied into the amalgamation without modifying any
204 # of their function declarations or definitions.
205 set varonly_hdr(sqlite3.h) 1
207 # These are the functions that accept a variable number of arguments. They
208 # always need to use the "cdecl" calling convention even when another calling
209 # convention (e.g. "stcall") is being used for the rest of the library.
210 set cdecllist {
211 sqlite3_config
212 sqlite3_db_config
213 sqlite3_log
214 sqlite3_mprintf
215 sqlite3_snprintf
216 sqlite3_test_control
217 sqlite3_vtab_config
220 # 78 stars used for comment formatting.
221 set s78 \
222 {*****************************************************************************}
224 # Insert a comment into the code
226 proc section_comment {text} {
227 global out s78
228 set n [string length $text]
229 set nstar [expr {60 - $n}]
230 set stars [string range $s78 0 $nstar]
231 puts $out "/************** $text $stars/"
234 # Read the source file named $filename and write it into the
235 # sqlite3.c output file. If any #include statements are seen,
236 # process them appropriately.
238 proc copy_file {filename} {
239 global seen_hdr available_hdr varonly_hdr cdecllist out
240 global addstatic linemacros useapicall srcdir
241 set ln 0
242 set tail [file tail $filename]
243 section_comment "Begin file $tail"
244 if {$linemacros} {puts $out "#line 1 \"$filename\""}
245 set in [open $filename r]
246 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
247 set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
248 if {[file extension $filename]==".h"} {
249 set declpattern " *$declpattern"
251 set declpattern ^$declpattern\$
252 while {![eof $in]} {
253 set line [string trimright [gets $in]]
254 incr ln
255 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
256 if {[info exists available_hdr($hdr)]} {
257 if {$available_hdr($hdr)} {
258 set available_hdr($hdr) 0
259 section_comment "Include $hdr in the middle of $tail"
260 copy_file $srcdir/$hdr
261 section_comment "Continuing where we left off in $tail"
262 if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
263 } else {
264 # Comment out the entire line, replacing any nested comment
265 # begin/end markers with the harmless substring "**".
266 puts $out "/* [string map [list /* ** */ **] $line] */"
268 } elseif {![info exists seen_hdr($hdr)]} {
269 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
270 set seen_hdr($hdr) 1
272 puts $out $line
273 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
274 # This include file must be kept because there was a "keep"
275 # directive inside of a line comment.
276 puts $out $line
277 } else {
278 # Comment out the entire line, replacing any nested comment
279 # begin/end markers with the harmless substring "**".
280 puts $out "/* [string map [list /* ** */ **] $line] */"
282 } elseif {[regexp {^#ifdef __cplusplus} $line]} {
283 puts $out "#if 0"
284 } elseif {!$linemacros && [regexp {^#line} $line]} {
285 # Skip #line directives.
286 } elseif {$addstatic
287 && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
288 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
289 # functions if this header file does not need it.
290 if {![info exists varonly_hdr($tail)]
291 && [regexp $declpattern $line all rettype funcname rest]} {
292 regsub {^SQLITE_API } $line {} line
293 regsub {^SQLITE_API } $rettype {} rettype
295 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
296 # so that linkage can be modified at compile-time.
297 if {[regexp {^sqlite3[a-z]*_} $funcname]} {
298 set line SQLITE_API
299 append line " " [string trim $rettype]
300 if {[string index $rettype end] ne "*"} {
301 append line " "
303 if {$useapicall} {
304 if {[lsearch -exact $cdecllist $funcname] >= 0} {
305 append line SQLITE_CDECL " "
306 } else {
307 append line SQLITE_APICALL " "
310 append line $funcname $rest
311 if {$funcname=="sqlite3_sourceid"} {
312 # The sqlite3_sourceid() routine is synthesized at the end of
313 # the amalgamation
314 puts $out "/* $line */"
315 } else {
316 puts $out $line
318 } else {
319 puts $out "SQLITE_PRIVATE $line"
321 } elseif {[regexp $varpattern $line all varname]} {
322 # Add the SQLITE_PRIVATE before variable declarations or
323 # definitions for internal use
324 regsub {^SQLITE_API } $line {} line
325 if {![regexp {^sqlite3_} $varname]
326 && ![regexp {^sqlite3Show[A-Z]} $varname]} {
327 regsub {^extern } $line {} line
328 puts $out "SQLITE_PRIVATE $line"
329 } else {
330 if {[regexp {const char sqlite3_version\[\];} $line]} {
331 set line {const char sqlite3_version[] = SQLITE_VERSION;}
333 regsub {^SQLITE_EXTERN } $line {} line
334 puts $out "SQLITE_API $line"
336 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
337 regsub {^SQLITE_API } $line {} line
338 regsub {^SQLITE_EXTERN } $line {} line
339 puts $out $line
340 } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
341 regsub {^SQLITE_API } $line {} line
342 puts $out "SQLITE_PRIVATE $line"
343 } else {
344 puts $out $line
346 } else {
347 puts $out $line
350 close $in
351 section_comment "End of $tail"
355 # Process the source files. Process files containing commonly
356 # used subroutines first in order to help the compiler find
357 # inlining opportunities.
359 set flist {
360 sqliteInt.h
361 os_common.h
362 ctime.c
364 global.c
365 status.c
366 date.c
367 os.c
369 fault.c
370 mem0.c
371 mem1.c
372 mem2.c
373 mem3.c
374 mem5.c
375 mutex.c
376 mutex_noop.c
377 mutex_unix.c
378 mutex_w32.c
379 malloc.c
380 printf.c
381 treeview.c
382 random.c
383 threads.c
384 utf.c
385 util.c
386 hash.c
387 opcodes.c
389 os_kv.c
390 os_unix.c
391 os_win.c
392 memdb.c
394 bitvec.c
395 pcache.c
396 pcache1.c
397 rowset.c
398 pager.c
399 wal.c
401 btmutex.c
402 btree.c
403 backup.c
405 vdbemem.c
406 vdbeaux.c
407 vdbeapi.c
408 vdbetrace.c
409 vdbe.c
410 vdbeblob.c
411 vdbesort.c
412 vdbevtab.c
413 memjournal.c
415 crypto.c
416 crypto_impl.c
417 crypto_libtomcrypt.c
418 crypto_nss.c
419 crypto_openssl.c
420 crypto_cc.c
422 walker.c
423 resolve.c
424 expr.c
425 alter.c
426 analyze.c
427 attach.c
428 auth.c
429 build.c
430 callback.c
431 delete.c
432 func.c
433 fkey.c
434 insert.c
435 legacy.c
436 loadext.c
437 pragma.c
438 prepare.c
439 select.c
440 table.c
441 trigger.c
442 update.c
443 upsert.c
444 vacuum.c
445 vtab.c
446 wherecode.c
447 whereexpr.c
448 where.c
449 window.c
451 parse.c
453 tokenize.c
454 complete.c
456 main.c
457 notify.c
459 fts3.c
460 fts3_aux.c
461 fts3_expr.c
462 fts3_hash.c
463 fts3_porter.c
464 fts3_tokenizer.c
465 fts3_tokenizer1.c
466 fts3_tokenize_vtab.c
467 fts3_write.c
468 fts3_snippet.c
469 fts3_unicode.c
470 fts3_unicode2.c
472 json.c
473 rtree.c
474 icu.c
476 fts3_icu.c
477 sqlite3rbu.c
478 dbstat.c
479 dbpage.c
480 sqlite3session.c
481 fts5.c
482 stmt.c
484 if {$enable_recover} {
485 lappend flist sqlite3recover.c dbdata.c
487 foreach file $flist {
488 copy_file $srcdir/$file
491 puts $out \
492 "/* Return the source-id for this library */
493 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
495 puts $out \
496 "/************************** End of sqlite3.c ******************************/"
498 close $out