guard against zero block size if provider initialization fails
[sqlcipher.git] / tool / mksqlite3c.tcl
blobf6ad44ac0733d8871878e9e08e8a8127075d27d1
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 crypto.h
132 sqlcipher.h
133 btree.h
134 btreeInt.h
135 fts3.h
136 fts3Int.h
137 fts3_hash.h
138 fts3_tokenizer.h
139 geopoly.c
140 hash.h
141 hwtime.h
142 keywordhash.h
143 msvc.h
144 mutex.h
145 opcodes.h
146 os_common.h
147 os_setup.h
148 os_win.h
149 os.h
150 pager.h
151 parse.h
152 pcache.h
153 pragma.h
154 rtree.h
155 sqlite3session.h
156 sqlite3.h
157 sqlite3ext.h
158 sqlite3rbu.h
159 sqliteicu.h
160 sqliteInt.h
161 sqliteLimit.h
162 vdbe.h
163 vdbeInt.h
164 vxworks.h
165 wal.h
166 whereInt.h
168 set available_hdr($hdr) 1
170 set available_hdr(sqliteInt.h) 0
171 set available_hdr(os_common.h) 0
172 set available_hdr(sqlite3session.h) 0
174 # These headers should be copied into the amalgamation without modifying any
175 # of their function declarations or definitions.
176 set varonly_hdr(sqlite3.h) 1
178 # These are the functions that accept a variable number of arguments. They
179 # always need to use the "cdecl" calling convention even when another calling
180 # convention (e.g. "stcall") is being used for the rest of the library.
181 set cdecllist {
182 sqlite3_config
183 sqlite3_db_config
184 sqlite3_log
185 sqlite3_mprintf
186 sqlite3_snprintf
187 sqlite3_test_control
188 sqlite3_vtab_config
191 # 78 stars used for comment formatting.
192 set s78 \
193 {*****************************************************************************}
195 # Insert a comment into the code
197 proc section_comment {text} {
198 global out s78
199 set n [string length $text]
200 set nstar [expr {60 - $n}]
201 set stars [string range $s78 0 $nstar]
202 puts $out "/************** $text $stars/"
205 # Read the source file named $filename and write it into the
206 # sqlite3.c output file. If any #include statements are seen,
207 # process them appropriately.
209 proc copy_file {filename} {
210 global seen_hdr available_hdr varonly_hdr cdecllist out
211 global addstatic linemacros useapicall srcdir
212 set ln 0
213 set tail [file tail $filename]
214 section_comment "Begin file $tail"
215 if {$linemacros} {puts $out "#line 1 \"$filename\""}
216 set in [open $filename r]
217 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
218 set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)}
219 if {[file extension $filename]==".h"} {
220 set declpattern " *$declpattern"
222 set declpattern ^$declpattern\$
223 while {![eof $in]} {
224 set line [string trimright [gets $in]]
225 incr ln
226 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
227 if {[info exists available_hdr($hdr)]} {
228 if {$available_hdr($hdr)} {
229 set available_hdr($hdr) 0
230 section_comment "Include $hdr in the middle of $tail"
231 copy_file $srcdir/$hdr
232 section_comment "Continuing where we left off in $tail"
233 if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""}
234 } else {
235 # Comment out the entire line, replacing any nested comment
236 # begin/end markers with the harmless substring "**".
237 puts $out "/* [string map [list /* ** */ **] $line] */"
239 } elseif {![info exists seen_hdr($hdr)]} {
240 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} {
241 set seen_hdr($hdr) 1
243 puts $out $line
244 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} {
245 # This include file must be kept because there was a "keep"
246 # directive inside of a line comment.
247 puts $out $line
248 } else {
249 # Comment out the entire line, replacing any nested comment
250 # begin/end markers with the harmless substring "**".
251 puts $out "/* [string map [list /* ** */ **] $line] */"
253 } elseif {[regexp {^#ifdef __cplusplus} $line]} {
254 puts $out "#if 0"
255 } elseif {!$linemacros && [regexp {^#line} $line]} {
256 # Skip #line directives.
257 } elseif {$addstatic
258 && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
259 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
260 # functions if this header file does not need it.
261 if {![info exists varonly_hdr($tail)]
262 && [regexp $declpattern $line all rettype funcname rest]} {
263 regsub {^SQLITE_API } $line {} line
264 regsub {^SQLITE_API } $rettype {} rettype
266 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
267 # so that linkage can be modified at compile-time.
268 if {[regexp {^sqlite3[a-z]*_} $funcname]} {
269 set line SQLITE_API
270 append line " " [string trim $rettype]
271 if {[string index $rettype end] ne "*"} {
272 append line " "
274 if {$useapicall} {
275 if {[lsearch -exact $cdecllist $funcname] >= 0} {
276 append line SQLITE_CDECL " "
277 } else {
278 append line SQLITE_APICALL " "
281 append line $funcname $rest
282 if {$funcname=="sqlite3_sourceid"} {
283 # The sqlite3_sourceid() routine is synthesized at the end of
284 # the amalgamation
285 puts $out "/* $line */"
286 } else {
287 puts $out $line
289 } else {
290 puts $out "SQLITE_PRIVATE $line"
292 } elseif {[regexp $varpattern $line all varname]} {
293 # Add the SQLITE_PRIVATE before variable declarations or
294 # definitions for internal use
295 regsub {^SQLITE_API } $line {} line
296 if {![regexp {^sqlite3_} $varname]
297 && ![regexp {^sqlite3Show[A-Z]} $varname]} {
298 regsub {^extern } $line {} line
299 puts $out "SQLITE_PRIVATE $line"
300 } else {
301 if {[regexp {const char sqlite3_version\[\];} $line]} {
302 set line {const char sqlite3_version[] = SQLITE_VERSION;}
304 regsub {^SQLITE_EXTERN } $line {} line
305 puts $out "SQLITE_API $line"
307 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
308 regsub {^SQLITE_API } $line {} line
309 regsub {^SQLITE_EXTERN } $line {} line
310 puts $out $line
311 } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
312 regsub {^SQLITE_API } $line {} line
313 puts $out "SQLITE_PRIVATE $line"
314 } else {
315 puts $out $line
317 } else {
318 puts $out $line
321 close $in
322 section_comment "End of $tail"
326 # Process the source files. Process files containing commonly
327 # used subroutines first in order to help the compiler find
328 # inlining opportunities.
331 foreach file {
332 sqliteInt.h
333 os_common.h
334 ctime.c
336 global.c
337 status.c
338 date.c
339 os.c
341 fault.c
342 mem0.c
343 mem1.c
344 mem2.c
345 mem3.c
346 mem5.c
347 mutex.c
348 mutex_noop.c
349 mutex_unix.c
350 mutex_w32.c
351 malloc.c
352 printf.c
353 treeview.c
354 random.c
355 threads.c
356 utf.c
357 util.c
358 hash.c
359 opcodes.c
361 os_kv.c
362 os_unix.c
363 os_win.c
364 memdb.c
366 bitvec.c
367 pcache.c
368 pcache1.c
369 rowset.c
370 pager.c
371 wal.c
373 btmutex.c
374 btree.c
375 backup.c
377 vdbemem.c
378 vdbeaux.c
379 vdbeapi.c
380 vdbetrace.c
381 vdbe.c
382 vdbeblob.c
383 vdbesort.c
384 vdbevtab.c
385 memjournal.c
387 crypto.c
388 crypto_impl.c
389 crypto_libtomcrypt.c
390 crypto_nss.c
391 crypto_openssl.c
392 crypto_cc.c
394 walker.c
395 resolve.c
396 expr.c
397 alter.c
398 analyze.c
399 attach.c
400 auth.c
401 build.c
402 callback.c
403 delete.c
404 func.c
405 fkey.c
406 insert.c
407 legacy.c
408 loadext.c
409 pragma.c
410 prepare.c
411 select.c
412 table.c
413 trigger.c
414 update.c
415 upsert.c
416 vacuum.c
417 vtab.c
418 wherecode.c
419 whereexpr.c
420 where.c
421 window.c
423 parse.c
425 tokenize.c
426 complete.c
428 main.c
429 notify.c
431 fts3.c
432 fts3_aux.c
433 fts3_expr.c
434 fts3_hash.c
435 fts3_porter.c
436 fts3_tokenizer.c
437 fts3_tokenizer1.c
438 fts3_tokenize_vtab.c
439 fts3_write.c
440 fts3_snippet.c
441 fts3_unicode.c
442 fts3_unicode2.c
444 json.c
445 rtree.c
446 icu.c
448 fts3_icu.c
449 sqlite3rbu.c
450 dbstat.c
451 dbpage.c
452 sqlite3session.c
453 fts5.c
454 stmt.c
456 copy_file $srcdir/$file
459 puts $out \
460 "/* Return the source-id for this library */
461 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
463 puts $out \
464 "/************************** End of sqlite3.c ******************************/"
466 close $out