1#!/usr/bin/tclsh 2# 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 6# 7# make target_source 8# 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". 16# 17# After the "tsrc" directory has been created and populated, run 18# this script: 19# 20# tclsh mksqlite3c.tcl --srcdir $SRC 21# 22# The amalgamated SQLite code will be written into sqlite3.c 23# 24 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. 28# 29set addstatic 1 30set linemacros 0 31set useapicall 0 32for {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" 42 } 43} 44set in [open tsrc/sqlite3.h] 45set cnt 0 46set VERSION ????? 47while {![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 52} 53close $in 54 55# Open the output file and write a header comment at the beginning 56# of the file. 57# 58set out [open sqlite3.c w] 59# Force the output to use unix line endings, even on Windows. 60fconfigure $out -translation lf 61set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1] 62puts $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. 71** 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. 81*/ 82#define SQLITE_CORE 1 83#define SQLITE_AMALGAMATION 1}] 84if {$addstatic} { 85 puts $out \ 86{#ifndef SQLITE_PRIVATE 87# define SQLITE_PRIVATE static 88#endif} 89} 90 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. 94# 95foreach 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 hash.h 105 hwtime.h 106 keywordhash.h 107 msvc.h 108 mutex.h 109 opcodes.h 110 os_common.h 111 os_setup.h 112 os_win.h 113 os.h 114 pager.h 115 parse.h 116 pcache.h 117 pragma.h 118 rtree.h 119 sqlite3session.h 120 sqlite3.h 121 sqlite3ext.h 122 sqlite3rbu.h 123 sqliteicu.h 124 sqliteInt.h 125 sqliteLimit.h 126 vdbe.h 127 vdbeInt.h 128 vxworks.h 129 wal.h 130 whereInt.h 131} { 132 set available_hdr($hdr) 1 133} 134set available_hdr(sqliteInt.h) 0 135set available_hdr(sqlite3session.h) 0 136 137# These headers should be copied into the amalgamation without modifying any 138# of their function declarations or definitions. 139set varonly_hdr(sqlite3.h) 1 140 141# These are the functions that accept a variable number of arguments. They 142# always need to use the "cdecl" calling convention even when another calling 143# convention (e.g. "stcall") is being used for the rest of the library. 144set cdecllist { 145 sqlite3_config 146 sqlite3_db_config 147 sqlite3_log 148 sqlite3_mprintf 149 sqlite3_snprintf 150 sqlite3_test_control 151 sqlite3_vtab_config 152} 153 154# 78 stars used for comment formatting. 155set s78 \ 156{*****************************************************************************} 157 158# Insert a comment into the code 159# 160proc section_comment {text} { 161 global out s78 162 set n [string length $text] 163 set nstar [expr {60 - $n}] 164 set stars [string range $s78 0 $nstar] 165 puts $out "/************** $text $stars/" 166} 167 168# Read the source file named $filename and write it into the 169# sqlite3.c output file. If any #include statements are seen, 170# process them appropriately. 171# 172proc copy_file {filename} { 173 global seen_hdr available_hdr varonly_hdr cdecllist out 174 global addstatic linemacros useapicall 175 set ln 0 176 set tail [file tail $filename] 177 section_comment "Begin file $tail" 178 if {$linemacros} {puts $out "#line 1 \"$filename\""} 179 set in [open $filename r] 180 set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)} 181 set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)} 182 if {[file extension $filename]==".h"} { 183 set declpattern " *$declpattern" 184 } 185 set declpattern ^$declpattern\$ 186 while {![eof $in]} { 187 set line [gets $in] 188 incr ln 189 if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} { 190 if {[info exists available_hdr($hdr)]} { 191 if {$available_hdr($hdr)} { 192 if {$hdr!="os_common.h" && $hdr!="hwtime.h"} { 193 set available_hdr($hdr) 0 194 } 195 section_comment "Include $hdr in the middle of $tail" 196 copy_file tsrc/$hdr 197 section_comment "Continuing where we left off in $tail" 198 if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""} 199 } else { 200 # Comment out the entire line, replacing any nested comment 201 # begin/end markers with the harmless substring "**". 202 puts $out "/* [string map [list /* ** */ **] $line] */" 203 } 204 } elseif {![info exists seen_hdr($hdr)]} { 205 if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} { 206 set seen_hdr($hdr) 1 207 } 208 puts $out $line 209 } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} { 210 # This include file must be kept because there was a "keep" 211 # directive inside of a line comment. 212 puts $out $line 213 } else { 214 # Comment out the entire line, replacing any nested comment 215 # begin/end markers with the harmless substring "**". 216 puts $out "/* [string map [list /* ** */ **] $line] */" 217 } 218 } elseif {[regexp {^#ifdef __cplusplus} $line]} { 219 puts $out "#if 0" 220 } elseif {!$linemacros && [regexp {^#line} $line]} { 221 # Skip #line directives. 222 } elseif {$addstatic 223 && ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} { 224 # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before 225 # functions if this header file does not need it. 226 if {![info exists varonly_hdr($tail)] 227 && [regexp $declpattern $line all rettype funcname rest]} { 228 regsub {^SQLITE_API } $line {} line 229 # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions. 230 # so that linkage can be modified at compile-time. 231 if {[regexp {^sqlite3[a-z]*_} $funcname]} { 232 set line SQLITE_API 233 append line " " [string trim $rettype] 234 if {[string index $rettype end] ne "*"} { 235 append line " " 236 } 237 if {$useapicall} { 238 if {[lsearch -exact $cdecllist $funcname] >= 0} { 239 append line SQLITE_CDECL " " 240 } else { 241 append line SQLITE_APICALL " " 242 } 243 } 244 append line $funcname $rest 245 puts $out $line 246 } else { 247 puts $out "SQLITE_PRIVATE $line" 248 } 249 } elseif {[regexp $varpattern $line all varname]} { 250 # Add the SQLITE_PRIVATE before variable declarations or 251 # definitions for internal use 252 regsub {^SQLITE_API } $line {} line 253 if {![regexp {^sqlite3_} $varname]} { 254 regsub {^extern } $line {} line 255 puts $out "SQLITE_PRIVATE $line" 256 } else { 257 if {[regexp {const char sqlite3_version\[\];} $line]} { 258 set line {const char sqlite3_version[] = SQLITE_VERSION;} 259 } 260 regsub {^SQLITE_EXTERN } $line {} line 261 puts $out "SQLITE_API $line" 262 } 263 } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} { 264 regsub {^SQLITE_API } $line {} line 265 regsub {^SQLITE_EXTERN } $line {} line 266 puts $out $line 267 } elseif {[regexp {^void \(\*sqlite3Os} $line]} { 268 regsub {^SQLITE_API } $line {} line 269 puts $out "SQLITE_PRIVATE $line" 270 } else { 271 puts $out $line 272 } 273 } else { 274 puts $out $line 275 } 276 } 277 close $in 278 section_comment "End of $tail" 279} 280 281 282# Process the source files. Process files containing commonly 283# used subroutines first in order to help the compiler find 284# inlining opportunities. 285# 286 287foreach file { 288 ctime.c 289 sqliteInt.h 290 291 crypto.c 292 crypto_impl.c 293 crypto_libtomcrypt.c 294 crypto_openssl.c 295 crypto_cc.c 296 297 global.c 298 status.c 299 date.c 300 os.c 301 302 fault.c 303 mem0.c 304 mem1.c 305 mem2.c 306 mem3.c 307 mem5.c 308 mutex.c 309 mutex_noop.c 310 mutex_unix.c 311 mutex_w32.c 312 malloc.c 313 printf.c 314 treeview.c 315 random.c 316 threads.c 317 utf.c 318 util.c 319 hash.c 320 opcodes.c 321 322 os_unix.c 323 os_win.c 324 325 bitvec.c 326 pcache.c 327 pcache1.c 328 rowset.c 329 pager.c 330 wal.c 331 332 btmutex.c 333 btree.c 334 backup.c 335 336 vdbemem.c 337 vdbeaux.c 338 vdbeapi.c 339 vdbetrace.c 340 vdbe.c 341 vdbeblob.c 342 vdbesort.c 343 memjournal.c 344 345 walker.c 346 resolve.c 347 expr.c 348 alter.c 349 analyze.c 350 attach.c 351 auth.c 352 build.c 353 callback.c 354 delete.c 355 func.c 356 fkey.c 357 insert.c 358 legacy.c 359 loadext.c 360 pragma.c 361 prepare.c 362 select.c 363 table.c 364 trigger.c 365 update.c 366 vacuum.c 367 vtab.c 368 wherecode.c 369 whereexpr.c 370 where.c 371 372 parse.c 373 374 tokenize.c 375 complete.c 376 377 main.c 378 notify.c 379 380 fts3.c 381 fts3_aux.c 382 fts3_expr.c 383 fts3_hash.c 384 fts3_porter.c 385 fts3_tokenizer.c 386 fts3_tokenizer1.c 387 fts3_tokenize_vtab.c 388 fts3_write.c 389 fts3_snippet.c 390 fts3_unicode.c 391 fts3_unicode2.c 392 393 rtree.c 394 icu.c 395 396 fts3_icu.c 397 sqlite3rbu.c 398 dbstat.c 399 sqlite3session.c 400 json1.c 401 fts5.c 402 stmt.c 403} { 404 copy_file tsrc/$file 405} 406 407close $out 408