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
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 versioon number is needed to generate the header
27# comment of the amalgamation.
28#
29if {[lsearch $argv --nostatic]>=0} {
30  set addstatic 0
31} else {
32  set addstatic 1
33}
34set in [open tsrc/sqlite3.h]
35set cnt 0
36set VERSION ?????
37while {![eof $in]} {
38  set line [gets $in]
39  if {$line=="" && [eof $in]} break
40  incr cnt
41  regexp {#define\s+SQLITE_VERSION\s+"(.*)"} $line all VERSION
42}
43close $in
44
45# Open the output file and write a header comment at the beginning
46# of the file.
47#
48set out [open sqlite3.c w]
49set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
50puts $out [subst \
51{/******************************************************************************
52** This file is an amalgamation of many separate C source files from SQLite
53** version $VERSION.  By combining all the individual C code files into this
54** single large file, the entire code can be compiled as a single translation
55** unit.  This allows many compilers to do optimizations that would not be
56** possible if the files were compiled separately.  Performance improvements
57** of 5% or more are commonly seen when SQLite is compiled as a single
58** translation unit.
59**
60** This file is all you need to compile SQLite.  To use SQLite in other
61** programs, you need this file and the "sqlite3.h" header file that defines
62** the programming interface to the SQLite library.  (If you do not have
63** the "sqlite3.h" header file at hand, you will find a copy embedded within
64** the text of this file.  Search for "Begin file sqlite3.h" to find the start
65** of the embedded sqlite3.h header file.) Additional code files may be needed
66** if you want a wrapper to interface SQLite with your choice of programming
67** language. The code for the "sqlite3" command-line shell is also in a
68** separate file. This file contains only code for the core SQLite library.
69*/
70#define SQLITE_CORE 1
71#define SQLITE_AMALGAMATION 1}]
72if {$addstatic} {
73  puts $out \
74{#ifndef SQLITE_PRIVATE
75# define SQLITE_PRIVATE static
76#endif
77#ifndef SQLITE_API
78# define SQLITE_API
79#endif}
80}
81
82# These are the header files used by SQLite.  The first time any of these
83# files are seen in a #include statement in the C code, include the complete
84# text of the file in-line.  The file only needs to be included once.
85#
86foreach hdr {
87   btree.h
88   btreeInt.h
89   fts3.h
90   fts3Int.h
91   fts3_hash.h
92   fts3_tokenizer.h
93   hash.h
94   hwtime.h
95   keywordhash.h
96   mutex.h
97   opcodes.h
98   os_common.h
99   os.h
100   os_os2.h
101   pager.h
102   parse.h
103   pcache.h
104   rtree.h
105   sqlite3ext.h
106   sqlite3.h
107   sqliteicu.h
108   sqliteInt.h
109   sqliteLimit.h
110   vdbe.h
111   vdbeInt.h
112   wal.h
113} {
114  set available_hdr($hdr) 1
115}
116set available_hdr(sqliteInt.h) 0
117
118# 78 stars used for comment formatting.
119set s78 \
120{*****************************************************************************}
121
122# Insert a comment into the code
123#
124proc section_comment {text} {
125  global out s78
126  set n [string length $text]
127  set nstar [expr {60 - $n}]
128  set stars [string range $s78 0 $nstar]
129  puts $out "/************** $text $stars/"
130}
131
132# Read the source file named $filename and write it into the
133# sqlite3.c output file.  If any #include statements are seen,
134# process them approprately.
135#
136proc copy_file {filename} {
137  global seen_hdr available_hdr out addstatic
138  set tail [file tail $filename]
139  section_comment "Begin file $tail"
140  set in [open $filename r]
141  set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)}
142  set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(}
143  if {[file extension $filename]==".h"} {
144    set declpattern " *$declpattern"
145  }
146  set declpattern ^$declpattern
147  while {![eof $in]} {
148    set line [gets $in]
149    if {[regexp {^\s*#\s*include\s+["<]([^">]+)[">]} $line all hdr]} {
150      if {[info exists available_hdr($hdr)]} {
151        if {$available_hdr($hdr)} {
152          if {$hdr!="os_common.h" && $hdr!="hwtime.h"} {
153            set available_hdr($hdr) 0
154          }
155          section_comment "Include $hdr in the middle of $tail"
156          copy_file tsrc/$hdr
157          section_comment "Continuing where we left off in $tail"
158        }
159      } elseif {![info exists seen_hdr($hdr)]} {
160        set seen_hdr($hdr) 1
161        puts $out $line
162      }
163    } elseif {[regexp {^#ifdef __cplusplus} $line]} {
164      puts $out "#if 0"
165    } elseif {[regexp {^#line} $line]} {
166      # Skip #line directives.
167    } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
168      regsub {^SQLITE_API } $line {} line
169      if {[regexp $declpattern $line all funcname]} {
170        # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
171        # so that linkage can be modified at compile-time.
172        if {[regexp {^sqlite3_} $funcname]} {
173          puts $out "SQLITE_API $line"
174        } else {
175          puts $out "SQLITE_PRIVATE $line"
176        }
177      } elseif {[regexp $varpattern $line all varname]} {
178        # Add the SQLITE_PRIVATE before variable declarations or
179        # definitions for internal use
180        if {![regexp {^sqlite3_} $varname]} {
181          regsub {^extern } $line {} line
182          puts $out "SQLITE_PRIVATE $line"
183        } else {
184          if {[regexp {const char sqlite3_version\[\];} $line]} {
185            set line {const char sqlite3_version[] = SQLITE_VERSION;}
186          }
187          regsub {^SQLITE_EXTERN } $line {} line
188          puts $out "SQLITE_API $line"
189        }
190      } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} {
191        regsub {^SQLITE_EXTERN } $line {} line
192        puts $out "SQLITE_PRIVATE $line"
193      } elseif {[regexp {^void \(\*sqlite3Os} $line]} {
194        puts $out "SQLITE_PRIVATE $line"
195      } else {
196        puts $out $line
197      }
198    } else {
199      puts $out $line
200    }
201  }
202  close $in
203  section_comment "End of $tail"
204}
205
206
207# Process the source files.  Process files containing commonly
208# used subroutines first in order to help the compiler find
209# inlining opportunities.
210#
211foreach file {
212   sqliteInt.h
213
214   global.c
215   ctime.c
216   status.c
217   date.c
218   os.c
219
220   fault.c
221   mem0.c
222   mem1.c
223   mem2.c
224   mem3.c
225   mem5.c
226   mutex.c
227   mutex_noop.c
228   mutex_os2.c
229   mutex_unix.c
230   mutex_w32.c
231   malloc.c
232   printf.c
233   random.c
234   utf.c
235   util.c
236   hash.c
237   opcodes.c
238
239   os_os2.c
240   os_unix.c
241   os_win.c
242
243   bitvec.c
244   pcache.c
245   pcache1.c
246   rowset.c
247   pager.c
248   wal.c
249
250   btmutex.c
251   btree.c
252   backup.c
253
254   vdbemem.c
255   vdbeaux.c
256   vdbeapi.c
257   vdbetrace.c
258   vdbe.c
259   vdbeblob.c
260   journal.c
261   memjournal.c
262
263   walker.c
264   resolve.c
265   expr.c
266   alter.c
267   analyze.c
268   attach.c
269   auth.c
270   build.c
271   callback.c
272   delete.c
273   func.c
274   fkey.c
275   insert.c
276   legacy.c
277   loadext.c
278   pragma.c
279   prepare.c
280   select.c
281   table.c
282   trigger.c
283   update.c
284   vacuum.c
285   vtab.c
286   where.c
287
288   parse.c
289
290   tokenize.c
291   complete.c
292
293   main.c
294   notify.c
295
296   recover.c
297
298   fts3.c
299   fts3_aux.c
300   fts3_expr.c
301   fts3_hash.c
302   fts3_porter.c
303   fts3_tokenizer.c
304   fts3_tokenizer1.c
305   fts3_write.c
306   fts3_snippet.c
307
308   rtree.c
309   icu.c
310   fts3_icu.c
311} {
312  copy_file tsrc/$file
313}
314
315close $out
316