Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c493177e10 | |||
| 3cd92ce875 | |||
| 963aa5bdbf | |||
| d3e44d4fa0 | |||
| 03e2f9da23 | |||
| 4dd457c3ce | |||
| 63725a467f | |||
| 30c605e8ae | |||
| ba96468b9b | |||
| 8a61fe879d | |||
| 360abdca9c | |||
| f15a16e00a | |||
| 5e3ef1e524 | |||
| b36434d0d6 | |||
| e4f445e587 | |||
| 40c674e54a | |||
| 46701fcccf | |||
| 613929c59f | |||
| 967a5e8b75 | |||
| 26787f3538 | |||
| 15e556f552 | |||
| 75b9706776 | |||
| 2c9a970eb8 | |||
| ecf0462e8f | |||
| f10e7bcd1e | |||
| 9f10d81707 | |||
| 82afe06bb4 | |||
| 3022685857 | |||
| 6d3751ebd4 | |||
| db109887e8 | |||
| 97056a2a21 | |||
| 53d352b5c2 | |||
| aebe9962ab | |||
| 23b10e9ff3 |
@@ -1 +0,0 @@
|
||||
*.db
|
||||
+16
-10
@@ -30,12 +30,14 @@ The public domain source files usually contain a header comment
|
||||
similar to the following to make it clear that the software is
|
||||
public domain.
|
||||
|
||||
> The author disclaims copyright to this source code. In place of
|
||||
> a legal notice, here is a blessing:
|
||||
>
|
||||
> * May you do good and not evil.
|
||||
> * May you find forgiveness for yourself and forgive others.
|
||||
> * May you share freely, never taking more than you give.
|
||||
> ~~~
|
||||
The author disclaims copyright to this source code. In place of
|
||||
a legal notice, here is a blessing:
|
||||
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
~~~
|
||||
|
||||
Almost every file you find in this source repository will be
|
||||
public domain. But there are a small number of exceptions:
|
||||
@@ -47,7 +49,9 @@ This repository contains a (relatively) small amount of non-public-domain
|
||||
code used to help implement the configuration and build logic. In other
|
||||
words, there are some non-public-domain files used to implement:
|
||||
|
||||
> ./configure && make
|
||||
> ~~~
|
||||
./configure && make
|
||||
~~~
|
||||
|
||||
In all cases, the non-public-domain files included with this
|
||||
repository have generous BSD-style licenses. So anyone is free to
|
||||
@@ -65,7 +69,7 @@ third-party build scripts in order to compile SQLite.
|
||||
Non-public-domain code included in this respository includes:
|
||||
|
||||
* The ["autosetup"](http://msteveb.github.io/autosetup/) configuration
|
||||
system that is contained (mostly) in the autosetup/ directory, but also
|
||||
system that is contained (mostly) the autosetup/ directory, but also
|
||||
includes the "./configure" script at the top-level of this archive.
|
||||
Autosetup has a separate BSD-style license. See the
|
||||
[autosetup/LICENSE](http://msteveb.github.io/autosetup/license/)
|
||||
@@ -75,11 +79,13 @@ Non-public-domain code included in this respository includes:
|
||||
software found in the legacy autoconf/ directory and its
|
||||
subdirectories.
|
||||
|
||||
The following unix shell command can be run from the top-level
|
||||
The following unix shell command is can be run from the top-level
|
||||
of this source repository in order to remove all non-public-domain
|
||||
code:
|
||||
|
||||
> rm -rf configure autosetup autoconf
|
||||
> ~~~
|
||||
rm -rf configure autosetup autoconf
|
||||
~~~
|
||||
|
||||
If you unpack this source repository and then run the command above, what
|
||||
is left will be 100% public domain.
|
||||
|
||||
+36
-34
@@ -11,6 +11,17 @@
|
||||
#
|
||||
all:
|
||||
########################################################################
|
||||
#
|
||||
# Known TODOs/FIXMEs/TOIMPROVEs for the autosetup port, in no
|
||||
# particular order...
|
||||
#
|
||||
# - TEA pieces.
|
||||
#
|
||||
# - Replace the autotools-specific distribution deliverable(s).
|
||||
#
|
||||
# - Confirm whether cross-compilation works and patch it
|
||||
# appropriately.
|
||||
#
|
||||
# Maintenance reminders:
|
||||
#
|
||||
# - This makefile should remain as POSIX-make-compatible as possible:
|
||||
@@ -68,7 +79,7 @@ libdir = @libdir@
|
||||
|
||||
INSTALL = @BIN_INSTALL@
|
||||
AR = @AR@
|
||||
AR.flags = cr
|
||||
AR.flags = cr # TODO? Add a configure test to determine this?
|
||||
CC = @CC@
|
||||
B.cc = @CC_FOR_BUILD@ @BUILD_CFLAGS@
|
||||
T.cc = $(CC)
|
||||
@@ -111,29 +122,24 @@ LDFLAGS.rt = @LDFLAGS_RT@
|
||||
CFLAGS.icu = @CFLAGS_ICU@
|
||||
LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@
|
||||
# soname: see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
LDFLAGS.libsqlite3.os-specific = \
|
||||
@LDFLAGS_MAC_CVERSION@ @LDFLAGS_MAC_INSTALL_NAME@ @LDFLAGS_OUT_IMPLIB@
|
||||
LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
|
||||
# os-specific: see
|
||||
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# - https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
# - https://sqlite.org/forum/forumpost/5651662b8875ec0a
|
||||
|
||||
libsqlite3.DLL.basename = @SQLITE_DLL_BASENAME@
|
||||
# DLL.basename: see https://sqlite.org/forum/forumpost/828fdfe904
|
||||
libsqlite3.out.implib = @SQLITE_OUT_IMPLIB@
|
||||
# libsqlite3.out.implib => the output filename part of LDFLAGS_OUT_IMPLIB.
|
||||
ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@
|
||||
ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@
|
||||
ENABLE_SHARED = @ENABLE_SHARED@
|
||||
ENABLE_STATIC = @ENABLE_STATIC@
|
||||
HAVE_WASI_SDK = @HAVE_WASI_SDK@
|
||||
libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@
|
||||
|
||||
# -fsanitize flags for the fuzzcheck-asap app
|
||||
CFLAGS.fuzzcheck-asan.fsanitize = @CFLAGS_ASAN_FSANITIZE@
|
||||
T.cc.sqlite = $(T.cc) @TARGET_DEBUG@
|
||||
|
||||
#
|
||||
# Intended to either be empty or be set to -g -DSQLITE_DEBUG=1.
|
||||
# Define -D_HAVE_SQLITE_CONFIG_H so that the code knows it
|
||||
# can include the generated sqlite_cfg.h.
|
||||
#
|
||||
T.cc.TARGET_DEBUG = @TARGET_DEBUG@
|
||||
# main.mk will fill out T.cc.sqlite with additional flags common to
|
||||
# all builds.
|
||||
#
|
||||
T.cc.sqlite += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite
|
||||
|
||||
#
|
||||
# $(JIMSH) and $(CFLAGS.jimsh) are documented in main.mk. $(JIMSH)
|
||||
@@ -202,13 +208,6 @@ TCL_CONFIG_SH = @TCL_CONFIG_SH@
|
||||
#TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
|
||||
#TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@
|
||||
#TCL_VERSION = @TCL_VERSION@
|
||||
TCL_MAJOR_VERSION = @TCL_MAJOR_VERSION@
|
||||
# ^^^ main.mk optionally uses this for determining the Tcl extension's
|
||||
# DLL name.
|
||||
TCL_EXT_DLL_BASENAME = @TCL_EXT_DLL_BASENAME@
|
||||
# ^^^ base name of the Tcl extension DLL. It varies by platform and
|
||||
# Tcl version.
|
||||
|
||||
#
|
||||
# $(TCLLIBDIR) = where to install the tcl plugin. If this is empty, it
|
||||
# is calculated at make-time by the targets which need it but we
|
||||
@@ -239,8 +238,8 @@ TSTRNNR_OPTS = @TSTRNNR_OPTS@
|
||||
CFLAGS.gcov1 = -DSQLITE_COVERAGE_TEST=1 -fprofile-arcs -ftest-coverage
|
||||
LDFLAGS.gcov1 = -lgcov
|
||||
USE_GCOV = @USE_GCOV@
|
||||
T.compile.gcov = $(CFLAGS.gcov$(USE_GCOV))
|
||||
T.link.gcov = $(LDFLAGS.gcov$(USE_GCOV))
|
||||
T.compile.extras = $(CFLAGS.gcov$(USE_GCOV))
|
||||
T.link.extras = $(LDFLAGS.gcov$(USE_GCOV))
|
||||
|
||||
#
|
||||
# Vars with the AS_ prefix are specifically related to AutoSetup.
|
||||
@@ -253,15 +252,10 @@ AS_AUTO_DEF = $(TOP)/auto.def
|
||||
# invoked with to produce this makefile.
|
||||
#
|
||||
AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@
|
||||
.PHONY: config reconfigure
|
||||
config reconfigure:
|
||||
$(AS_AUTORECONFIG)
|
||||
|
||||
USE_AMALGAMATION ?= @USE_AMALGAMATION@
|
||||
LINK_TOOLS_DYNAMICALLY ?= @LINK_TOOLS_DYNAMICALLY@
|
||||
AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@
|
||||
EXTRA_SRC ?= @AMALGAMATION_EXTRA_SRC@
|
||||
STATIC_TCLSQLITE3 = @STATIC_TCLSQLITE3@
|
||||
STATIC_CLI_SHELL = @STATIC_CLI_SHELL@
|
||||
|
||||
#
|
||||
# CFLAGS for sqlite3$(T.exe)
|
||||
@@ -313,8 +307,9 @@ fiddle: sqlite3.c shell.c
|
||||
./custom.rws: ./tool/custom.txt
|
||||
@echo 'Updating custom dictionary from tool/custom.txt'
|
||||
aspell --lang=en create master ./custom.rws < ./tool/custom.txt
|
||||
# Note that jimsh does not work here:
|
||||
# https://github.com/msteveb/jimtcl/issues/319
|
||||
misspell: ./custom.rws has_tclsh84
|
||||
# $(JIMSH) does not work with spellsift.tcl
|
||||
$(TCLSH_CMD) ./tool/spellsift.tcl ./src/*.c ./src/*.h ./src/*.in
|
||||
|
||||
#
|
||||
@@ -322,7 +317,13 @@ misspell: ./custom.rws has_tclsh84
|
||||
# perform cleanup known to be relevant to (only) the autosetup-driven
|
||||
# build.
|
||||
#
|
||||
distclean-autosetup:
|
||||
#clean-autosetup:
|
||||
# -if [ -f ext/wasm/GNUmakefile ]; then \
|
||||
# gmake --no-print-directory --ignore-errors -C ext/wasm clean; \
|
||||
# fi >/dev/null 2>&1; true
|
||||
#clean: clean-autosetup
|
||||
|
||||
distclean-autosetup: clean
|
||||
rm -f sqlite_cfg.h config.log config.status config.defines.* Makefile sqlite3.pc
|
||||
rm -f $(TOP)/tool/emcc.sh
|
||||
rm -f libsqlite3*$(T.dll)
|
||||
@@ -331,9 +332,10 @@ distclean: distclean-autosetup
|
||||
|
||||
#
|
||||
# tool/version-info: a utility for emitting sqlite3 version info
|
||||
# in various forms. It's used by ext/wasm/.
|
||||
# in various forms.
|
||||
#
|
||||
version-info$(T.exe): $(TOP)/tool/version-info.c Makefile sqlite3.h
|
||||
$(T.link) $(ST_OPT) -o $@ $(TOP)/tool/version-info.c
|
||||
|
||||
IS_CROSS_COMPILING = @IS_CROSS_COMPILING@
|
||||
include $(TOP)/main.mk
|
||||
|
||||
+51
-191
@@ -294,12 +294,6 @@ SESSION = 0
|
||||
RBU = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this to non-0 to enable support for blocking locks.
|
||||
#
|
||||
!IFNDEF SETLK_TIMEOUT
|
||||
SETLK_TIMEOUT = 0
|
||||
!ENDIF
|
||||
|
||||
# Set the source code file to be used by executables and libraries when
|
||||
# they need the amalgamation.
|
||||
#
|
||||
@@ -405,7 +399,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_CARRAY=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
@@ -428,7 +421,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
|
||||
|
||||
# Always enable math functions on Windows
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PERCENTILE
|
||||
|
||||
# Should the rbu extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
@@ -458,10 +450,6 @@ EXT_FEATURE_FLAGS =
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IF $(SETLK_TIMEOUT)!=0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SETLK_TIMEOUT
|
||||
!ENDIF
|
||||
|
||||
###############################################################################
|
||||
############################### END OF OPTIONS ################################
|
||||
###############################################################################
|
||||
@@ -805,21 +793,17 @@ BCC = $(BCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
|
||||
!IF $(DEBUG)>1
|
||||
TCC = $(TCC) -MDd
|
||||
BCC = $(BCC) -MDd
|
||||
ZLIBCFLAGS = -nologo -MDd -W3 -O2 -Oy- -Zi
|
||||
!ELSE
|
||||
TCC = $(TCC) -MD
|
||||
BCC = $(BCC) -MD
|
||||
ZLIBCFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi
|
||||
!ENDIF
|
||||
!ELSE
|
||||
!IF $(DEBUG)>1
|
||||
TCC = $(TCC) -MTd
|
||||
BCC = $(BCC) -MTd
|
||||
ZLIBCFLAGS = -nologo -MTd -W3 -O2 -Oy- -Zi
|
||||
!ELSE
|
||||
TCC = $(TCC) -MT
|
||||
BCC = $(BCC) -MT
|
||||
ZLIBCFLAGS = -nologo -MT -W3 -O2 -Oy- -Zi
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@@ -890,7 +874,7 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>2
|
||||
TCC = $(TCC) -DSQLITE_DEBUG=1 -DSQLITE_USE_W32_FOR_CONSOLE_IO
|
||||
TCC = $(TCC) -DSQLITE_DEBUG=1
|
||||
RCC = $(RCC) -DSQLITE_DEBUG=1
|
||||
!IF $(DYNAMIC_SHELL)==0
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
|
||||
@@ -1349,7 +1333,7 @@ LTLIBS = $(LTLIBS) $(LIBICU)
|
||||
#
|
||||
LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
|
||||
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
|
||||
callback.lo carray.lo complete.lo ctime.lo \
|
||||
callback.lo complete.lo ctime.lo \
|
||||
date.lo dbpage.lo dbstat.lo delete.lo \
|
||||
expr.lo fault.lo fkey.lo \
|
||||
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
|
||||
@@ -1411,9 +1395,8 @@ SRC00 = \
|
||||
$(TOP)\src\btree.c \
|
||||
$(TOP)\src\build.c \
|
||||
$(TOP)\src\callback.c \
|
||||
$(TOP)\src\carray.c \
|
||||
$(TOP)\src\complete.c \
|
||||
ctime.c \
|
||||
$(TOP)\src\ctime.c \
|
||||
$(TOP)\src\date.c \
|
||||
$(TOP)\src\dbpage.c \
|
||||
$(TOP)\src\dbstat.c \
|
||||
@@ -1512,7 +1495,7 @@ SRC04 = \
|
||||
SRC05 = \
|
||||
$(TOP)\src\pager.h \
|
||||
$(TOP)\src\pcache.h \
|
||||
pragma.h \
|
||||
$(TOP)\src\pragma.h \
|
||||
$(TOP)\src\sqlite.h.in \
|
||||
$(TOP)\src\sqlite3ext.h \
|
||||
$(TOP)\src\sqliteInt.h \
|
||||
@@ -1630,6 +1613,7 @@ TESTSRC = \
|
||||
$(TOP)\src\test_thread.c \
|
||||
$(TOP)\src\test_vdbecov.c \
|
||||
$(TOP)\src\test_vfs.c \
|
||||
$(TOP)\src\test_windirent.c \
|
||||
$(TOP)\src\test_window.c \
|
||||
$(TOP)\src\test_wsd.c \
|
||||
$(TOP)\ext\fts3\fts3_term.c \
|
||||
@@ -1645,6 +1629,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\amatch.c \
|
||||
$(TOP)\ext\misc\appendvfs.c \
|
||||
$(TOP)\ext\misc\basexx.c \
|
||||
$(TOP)\ext\misc\carray.c \
|
||||
$(TOP)\ext\misc\cksumvfs.c \
|
||||
$(TOP)\ext\misc\closure.c \
|
||||
$(TOP)\ext\misc\csv.c \
|
||||
@@ -1660,6 +1645,7 @@ TESTEXT = \
|
||||
$(TOP)\ext\misc\mmapwarm.c \
|
||||
$(TOP)\ext\misc\nextchar.c \
|
||||
$(TOP)\ext\misc\normalize.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\prefixes.c \
|
||||
$(TOP)\ext\misc\qpvtab.c \
|
||||
$(TOP)\ext\misc\randomjson.c \
|
||||
@@ -1712,7 +1698,7 @@ HDR = \
|
||||
$(TOP)\src\pager.h \
|
||||
$(TOP)\src\pcache.h \
|
||||
parse.h \
|
||||
pragma.h \
|
||||
$(TOP)\src\pragma.h \
|
||||
$(SQLITE3H) \
|
||||
sqlite3ext.h \
|
||||
$(TOP)\src\sqliteInt.h \
|
||||
@@ -1771,7 +1757,6 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_DQS=0
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_PERCENTILE=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_STMT_SCANSTATUS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_STRICT_SUBTYPE=1
|
||||
@@ -1786,7 +1771,6 @@ FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -I$(TOP)\test -I$(TOP)\ext\recover
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_MEMSYS5
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_OSS_FUZZ
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_CARRAY
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
@@ -1800,7 +1784,6 @@ FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_MATH_FUNCTIONS
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_MEMSYS5
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_NORMALIZE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_PERCENTILE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_PREUPDATE_HOOK
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_SESSION
|
||||
@@ -1831,6 +1814,7 @@ FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\fuzzinvariants.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\test\vt02.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\dbdata.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\recover\sqlite3recover.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\percentile.c
|
||||
FUZZCHECK_SRC = $(FUZZCHECK_SRC) $(TOP)\ext\misc\randomjson.c
|
||||
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
@@ -1978,6 +1962,10 @@ fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
fuzzcheck-asan.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) /fsanitize=address $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
run-fuzzcheck: fuzzcheck.exe fuzzcheck-asan.exe
|
||||
fuzzcheck --spinner $(FUZZDB)
|
||||
fuzzcheck-asan --spinner $(FUZZDB)
|
||||
|
||||
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
@@ -2108,17 +2096,11 @@ build.lo: $(TOP)\src\build.c $(HDR)
|
||||
callback.lo: $(TOP)\src\callback.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\callback.c
|
||||
|
||||
carray.lo: $(TOP)\src\carray.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\carray.c
|
||||
|
||||
complete.lo: $(TOP)\src\complete.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\complete.c
|
||||
|
||||
ctime.c: $(TOP)\tool\mkctimec.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkctimec.tcl
|
||||
|
||||
ctime.lo: ctime.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c ctime.c
|
||||
ctime.lo: $(TOP)\src\ctime.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\ctime.c
|
||||
|
||||
date.lo: $(TOP)\src\date.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
|
||||
@@ -2351,9 +2333,6 @@ parse.c: $(TOP)\src\parse.y lemon.exe
|
||||
copy /B parse.y +,,
|
||||
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S parse.y
|
||||
|
||||
pragma.h: $(TOP)\tool\mkpragmatab.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkpragmatab.tcl
|
||||
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mksqlite3h.tcl "$(TOP:\=/)" -o $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
|
||||
@@ -2394,6 +2373,7 @@ SHELL_DEP = \
|
||||
$(TOP)\ext\misc\ieee754.c \
|
||||
$(TOP)\ext\misc\memtrace.c \
|
||||
$(TOP)\ext\misc\pcachetrace.c \
|
||||
$(TOP)\ext\misc\percentile.c \
|
||||
$(TOP)\ext\misc\regexp.c \
|
||||
$(TOP)\ext\misc\series.c \
|
||||
$(TOP)\ext\misc\sha1.c \
|
||||
@@ -2403,11 +2383,12 @@ SHELL_DEP = \
|
||||
$(TOP)\ext\misc\sqlite3_stdio.h \
|
||||
$(TOP)\ext\misc\uint.c \
|
||||
$(TOP)\ext\misc\vfstrace.c \
|
||||
$(TOP)\ext\misc\windirent.h \
|
||||
$(TOP)\ext\misc\zipfile.c \
|
||||
$(TOP)\ext\recover\dbdata.c \
|
||||
$(TOP)\ext\recover\sqlite3recover.c \
|
||||
$(TOP)\ext\recover\sqlite3recover.h
|
||||
$(TOP)\ext\recover\sqlite3recover.h \
|
||||
$(TOP)\src\test_windirent.c \
|
||||
$(TOP)\src\test_windirent.h
|
||||
|
||||
# If use of zlib is enabled, add the "zipfile.c" source file.
|
||||
#
|
||||
@@ -2420,7 +2401,7 @@ shell.c: $(SHELL_DEP) $(TOP)\tool\mkshellc.tcl $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\tool\mkshellc.tcl shell.c
|
||||
|
||||
zlib:
|
||||
pushd $(ZLIBDIR) && $(MAKE) /f win32\Makefile.msc clean $(ZLIBLIB) CFLAGS="$(ZLIBCFLAGS)" && popd
|
||||
pushd $(ZLIBDIR) && $(MAKE) /f win32\Makefile.msc clean $(ZLIBLIB) && popd
|
||||
|
||||
# Rules to build the extension objects.
|
||||
#
|
||||
@@ -2494,6 +2475,24 @@ FTS5_SRC = \
|
||||
$(TOP)\ext\fts5\fts5_varint.c \
|
||||
$(TOP)\ext\fts5\fts5_vocab.c
|
||||
|
||||
LSM1_SRC = \
|
||||
$(TOP)\ext\lsm1\lsm.h \
|
||||
$(TOP)\ext\lsm1\lsmInt.h \
|
||||
$(TOP)\ext\lsm1\lsm_ckpt.c \
|
||||
$(TOP)\ext\lsm1\lsm_file.c \
|
||||
$(TOP)\ext\lsm1\lsm_log.c \
|
||||
$(TOP)\ext\lsm1\lsm_main.c \
|
||||
$(TOP)\ext\lsm1\lsm_mem.c \
|
||||
$(TOP)\ext\lsm1\lsm_mutex.c \
|
||||
$(TOP)\ext\lsm1\lsm_shared.c \
|
||||
$(TOP)\ext\lsm1\lsm_sorted.c \
|
||||
$(TOP)\ext\lsm1\lsm_str.c \
|
||||
$(TOP)\ext\lsm1\lsm_tree.c \
|
||||
$(TOP)\ext\lsm1\lsm_unix.c \
|
||||
$(TOP)\ext\lsm1\lsm_varint.c \
|
||||
$(TOP)\ext\lsm1\lsm_vtab.c \
|
||||
$(TOP)\ext\lsm1\lsm_win32.c
|
||||
|
||||
fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
|
||||
copy /Y $(TOP)\ext\fts5\fts5parse.y .
|
||||
copy /B fts5parse.y +,,
|
||||
@@ -2507,6 +2506,11 @@ fts5.c: $(FTS5_SRC) $(JIM_TCLSH)
|
||||
copy /Y $(TOP)\ext\fts5\fts5.h .
|
||||
copy /B fts5.h +,,
|
||||
|
||||
lsm1.c: $(LSM1_SRC) $(JIM_TCLSH)
|
||||
$(JIM_TCLSH) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
|
||||
copy /Y $(TOP)\ext\lsm1\lsm.h .
|
||||
copy /B lsm.h +,,
|
||||
|
||||
fts5.lo: fts5.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c
|
||||
|
||||
@@ -2534,8 +2538,6 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_CARRAY=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_PERCENTILE=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_STATIC_RANDOMJSON
|
||||
@@ -2571,25 +2573,17 @@ sqlite_tcl.h:
|
||||
|
||||
testfixture.exe: $(TESTFIXTURE_SRC) $(TESTFIXTURE_DEP) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
|
||||
-DBUILD_sqlite -I$(TCLINCDIR) -I$(TOP)\ext\misc \
|
||||
-DBUILD_sqlite -I$(TCLINCDIR) \
|
||||
$(TESTFIXTURE_SRC) \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
# A small helper for manually running individual tests
|
||||
tf.bat: testfixture.exe Makefile.msc
|
||||
echo @set PATH=$(LIBTCLPATH);%PATH% > $@
|
||||
echo .\testfixture.exe %* >> $@
|
||||
|
||||
extensiontest: testfixture.exe testloadext.dll
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
|
||||
|
||||
tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe sqlite3_rsync.exe sqlite3.dll $(TOP)\tool\mktoolzip.tcl
|
||||
tool-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe sqlite3_rsync.exe $(TOP)\tool\mktoolzip.tcl
|
||||
.\testfixture.exe $(TOP)\tool\mktoolzip.tcl
|
||||
|
||||
snapshot-zip: testfixture.exe sqlite3.exe sqldiff.exe sqlite3_analyzer.exe sqlite3_rsync.exe sqlite3.dll $(TOP)\tool\mktoolzip.tcl
|
||||
.\testfixture.exe $(TOP)\tool\mktoolzip.tcl --snapshot
|
||||
|
||||
coretestprogs: testfixture.exe sqlite3.exe
|
||||
|
||||
testprogs: $(TESTPROGS) srcck1.exe fuzzcheck.exe sessionfuzz.exe
|
||||
@@ -2663,14 +2657,7 @@ srctree-check: $(TOP)\tool\srctree-check.tcl
|
||||
|
||||
# Testing for a release
|
||||
#
|
||||
releasetest: verify-source
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
|
||||
|
||||
# xdevtest is like releasetest, except that it skips the
|
||||
# dependency on verify-source so that xdevtest can be run from
|
||||
# a modified source tree.
|
||||
#
|
||||
xdevtest:
|
||||
releasetest:
|
||||
$(TCLSH_CMD) $(TOP)\test\testrunner.tcl release
|
||||
|
||||
|
||||
@@ -2815,133 +2802,8 @@ tcl-env:
|
||||
@echo JIM_TCLSH = $(JIM_TCLSH)
|
||||
@echo VISUALSTUDIOVERSION = $(VISUALSTUDIOVERSION)
|
||||
|
||||
env:
|
||||
@echo ALL_TCL_TARGETS = $(ALL_TCL_TARGETS)
|
||||
@echo API_ARMOR = $(API_ARMOR)
|
||||
@echo ASAN = $(ASAN)
|
||||
@echo BCC = $(BCC)
|
||||
@echo BUILD_ZLIB = $(BUILD_ZLIB)
|
||||
@echo CC = $(CC)
|
||||
@echo CCOPTS = $(CCOPTS)
|
||||
@echo CHECKER_DEPS = $(CHECKER_DEPS)
|
||||
@echo CORE_CCONV_OPTS = $(CORE_CCONV_OPTS)
|
||||
@echo CORE_COMPILE_OPTS = $(CORE_COMPILE_OPTS)
|
||||
@echo CORE_LINK_DEP = $(CORE_LINK_DEP)
|
||||
@echo CORE_LINK_OPTS = $(CORE_LINK_OPTS)
|
||||
@echo CRTLIBPATH = $(CRTLIBPATH)
|
||||
@echo CSC = $(CSC)
|
||||
@echo DBFUZZ_COMPILE_OPTS = $(DBFUZZ_COMPILE_OPTS)
|
||||
@echo DEBUG = $(DEBUG)
|
||||
@echo DYNAMIC_SHELL = $(DYNAMIC_SHELL)
|
||||
@echo EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS)
|
||||
@echo EXTHDR = $(EXTHDR)
|
||||
@echo EXTRA_SRC = $(EXTRA_SRC)
|
||||
@echo FOR_UWP = $(FOR_UWP)
|
||||
@echo FUZZCHECK_OPTS = $(FUZZCHECK_OPTS)
|
||||
@echo FUZZCHECK_SRC = $(FUZZCHECK_SRC)
|
||||
@echo FUZZDATA = $(FUZZDATA)
|
||||
@echo FUZZERSHELL_COMPILE_OPTS = $(FUZZERSHELL_COMPILE_OPTS)
|
||||
@echo HDR = $(HDR)
|
||||
@echo ICUDIR = $(ICUDIR)
|
||||
@echo ICUINCDIR = $(ICUINCDIR)
|
||||
@echo ICULIBDIR = $(ICULIBDIR)
|
||||
@echo JIM_TCLSH = $(JIM_TCLSH)
|
||||
@echo KV_COMPILE_OPTS = $(KV_COMPILE_OPTS)
|
||||
@echo LDFLAGS = $(LDFLAGS)
|
||||
@echo LD = $(LD)
|
||||
@echo LIBICU = $(LIBICU)
|
||||
@echo LIBOBJ = $(LIBOBJ)
|
||||
@echo LIBREADLINE = $(LIBREADLINE)
|
||||
@echo LIBRESOBJS = $(LIBRESOBJS)
|
||||
@echo LIBTCLPATH = $(LIBTCLPATH)
|
||||
@echo LIBTCLSTUB = $(LIBTCLSTUB)
|
||||
@echo LIBTCL = $(LIBTCL)
|
||||
@echo LTCOMPILE = $(LTCOMPILE)
|
||||
@echo LTLIB = $(LTLIB)
|
||||
@echo LTLIBOPTS = $(LTLIBOPTS)
|
||||
@echo LTLIBPATHS = $(LTLIBPATHS)
|
||||
@echo LTLIBS = $(LTLIBS)
|
||||
@echo LTLINK = $(LTLINK)
|
||||
@echo LTLINKOPTS = $(LTLINKOPTS)
|
||||
@echo LTRCOMPILE = $(LTRCOMPILE)
|
||||
@echo MEMDEBUG = $(MEMDEBUG)
|
||||
@echo MINIMAL_AMALGAMATION = $(MINIMAL_AMALGAMATION)
|
||||
@echo MPTESTER_COMPILE_OPTS = $(MPTESTER_COMPILE_OPTS)
|
||||
@echo NCC = $(NCC)
|
||||
@echo NCRTLIBPATH = $(NCRTLIBPATH)
|
||||
@echo NLTLIBPATHS = $(NLTLIBPATHS)
|
||||
@echo NO_LINEMACROS = $(NO_LINEMACROS)
|
||||
@echo NO_TCL = $(NO_TCL)
|
||||
@echo NO_WARN = $(NO_WARN)
|
||||
@echo NSDKLIBPATH = $(NSDKLIBPATH)
|
||||
@echo NUCRTLIBPATH = $(NUCRTLIBPATH)
|
||||
@echo OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS)
|
||||
@echo OPTIMIZATIONS = $(OPTIMIZATIONS)
|
||||
@echo OSSSHELL_SRC = $(OSSSHELL_SRC)
|
||||
@echo OSTRACE = $(OSTRACE)
|
||||
@echo RBU = $(RBU)
|
||||
@echo RCC = $(RCC)
|
||||
@echo RC = $(RC)
|
||||
@echo READLINE_FLAGS = $(READLINE_FLAGS)
|
||||
@echo REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS)
|
||||
@echo RSYNC_OPT = $(RSYNC_OPT)
|
||||
@echo RSYNC_SRC = $(RSYNC_SRC)
|
||||
@echo SESSION = $(SESSION)
|
||||
@echo SETLK_TIMEOUT = $(SETLK_TIMEOUT)
|
||||
@echo SHELL_CCONV_OPTS = $(SHELL_CCONV_OPTS)
|
||||
@echo SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS)
|
||||
@echo SHELL_CORE_DEP = $(SHELL_CORE_DEP)
|
||||
@echo SHELL_CORE_LIB = $(SHELL_CORE_LIB)
|
||||
@echo SHELL_CORE_SRC = $(SHELL_CORE_SRC)
|
||||
@echo SHELL_DEP = $(SHELL_DEP)
|
||||
@echo SHELL_LINK_OPTS = $(SHELL_LINK_OPTS)
|
||||
@echo SPLIT_AMALGAMATION = $(SPLIT_AMALGAMATION)
|
||||
@echo SQLITETCLDECLSH = $(SQLITETCLDECLSH)
|
||||
@echo SQLITE_TCL_DEP = $(SQLITE_TCL_DEP)
|
||||
@echo SQLITETCLH = $(SQLITETCLH)
|
||||
@echo SRC = $(SRC)
|
||||
@echo STATICALLY_LINK_TCL = $(STATICALLY_LINK_TCL)
|
||||
@echo ST_COMPILE_OPTS = $(ST_COMPILE_OPTS)
|
||||
@echo STORELIBPATH = $(STORELIBPATH)
|
||||
@echo SYMBOLS = $(SYMBOLS)
|
||||
@echo TCC = $(TCC)
|
||||
@echo TCLDIR = $(TCLDIR)
|
||||
@echo TCLINCDIR = $(TCLINCDIR)
|
||||
@echo TCLLIBDIR = $(TCLLIBDIR)
|
||||
@echo TCLLIBPATHS = $(TCLLIBPATHS)
|
||||
@echo TCLLIBS = $(TCLLIBS)
|
||||
@echo TCLSH_CMD = $(TCLSH_CMD)
|
||||
@echo TCLSQLITEEX = $(TCLSQLITEEX)
|
||||
@echo TCLSUFFIX = $(TCLSUFFIX)
|
||||
@echo TCLVERSION = $(TCLVERSION)
|
||||
@echo TEST_CCONV_OPTS = $(TEST_CCONV_OPTS)
|
||||
@echo TESTEXT = $(TESTEXT)
|
||||
@echo TESTFIXTURE_DEP = $(TESTFIXTURE_DEP)
|
||||
@echo TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS)
|
||||
@echo TESTFIXTURE_SRC = $(TESTFIXTURE_SRC)
|
||||
@echo TESTOPTS = $(TESTOPTS)
|
||||
@echo TESTPROGS = $(TESTPROGS)
|
||||
@echo TESTSRC = $(TESTSRC)
|
||||
@echo TLIBS = $(TLIBS)
|
||||
@echo TOP = $(TOP)
|
||||
@echo UCRTLIBPATH = $(UCRTLIBPATH)
|
||||
@echo USE_AMALGAMATION = $(USE_AMALGAMATION)
|
||||
@echo USE_CRT_DLL = $(USE_CRT_DLL)
|
||||
@echo USE_FATAL_WARN = $(USE_FATAL_WARN)
|
||||
@echo USE_FULLWARN = $(USE_FULLWARN)
|
||||
@echo USE_ICU = $(USE_ICU)
|
||||
@echo USE_LISTINGS = $(USE_LISTINGS)
|
||||
@echo USE_NATIVE_LIBPATHS = $(USE_NATIVE_LIBPATHS)
|
||||
@echo USE_RC = $(USE_RC)
|
||||
@echo USE_RUNTIME_CHECKS = $(USE_RUNTIME_CHECKS)
|
||||
@echo USE_SEH = $(USE_SEH)
|
||||
@echo USE_STDCALL = $(USE_STDCALL)
|
||||
@echo USE_ZLIB = $(USE_ZLIB)
|
||||
@echo XCOMPILE = $(XCOMPILE)
|
||||
@echo ZLIBDIR = $(ZLIBDIR)
|
||||
@echo ZLIBINCDIR = $(ZLIBINCDIR)
|
||||
@echo ZLIBLIBDIR = $(ZLIBLIBDIR)
|
||||
@echo ZLIBLIB = $(ZLIBLIB)
|
||||
LSMDIR=$(TOP)\ext\lsm1
|
||||
!INCLUDE $(LSMDIR)\Makefile.msc
|
||||
|
||||
moreclean: clean
|
||||
del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
|
||||
@@ -2950,7 +2812,7 @@ moreclean: clean
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def ctime.c pragma.h 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
# <<mark>>
|
||||
del /Q $(SQLITE3TCLDLL) pkgIndex.tcl 2>NUL
|
||||
@@ -2966,9 +2828,7 @@ clean:
|
||||
del /Q lsm.dll lsmtest.exe 2>NUL
|
||||
del /Q atrc.exe changesetfuzz.exe dbtotxt.exe index_usage.exe 2>NUL
|
||||
del /Q testloadext.dll 2>NUL
|
||||
del /Q testfixture.exe test.db tf.bat 2>NUL
|
||||
del /Q /S testdir 2>/NUL
|
||||
-rmdir /Q /S testdir 2>NUL
|
||||
del /Q testfixture.exe test.db 2>NUL
|
||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
|
||||
del /Q changeset.exe 2>NUL
|
||||
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
|
||||
@@ -2984,6 +2844,6 @@ clean:
|
||||
del /Q kvtest.exe ossshell.exe scrub.exe 2>NUL
|
||||
del /Q showshm.exe sqlite3_checker.* sqlite3_expert.exe 2>NUL
|
||||
del /Q fts5.* fts5parse.* 2>NUL
|
||||
del /Q lsm.h lsm1.c 2>NUL
|
||||
del /q src-verify.exe 2>NUL
|
||||
del /q jimsh.exe jimsh0.exe 2>NUL
|
||||
# <</mark>>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
This repository contains the complete source code for the
|
||||
[SQLite database engine](https://sqlite.org/), including
|
||||
many tests. Additional tests and most documentation
|
||||
are managed separately.
|
||||
many test scripts. However, other test scripts
|
||||
and most of the documentation are managed separately.
|
||||
|
||||
See the [on-line documentation](https://sqlite.org/) for more information
|
||||
about what SQLite is and how it works from a user's perspective. This
|
||||
@@ -53,32 +53,39 @@ then no longer be fully in the public domain.
|
||||
|
||||
## Obtaining The SQLite Source Code
|
||||
|
||||
Source code tarballs or ZIP archives are available at:
|
||||
If you do not want to use Fossil, you can download tarballs or ZIP
|
||||
archives or [SQLite archives](https://sqlite.org/cli.html#sqlar) as follows:
|
||||
|
||||
* [Latest trunk check-in](https://sqlite.org/src/rchvdwnld/trunk).
|
||||
* Latest trunk check-in as
|
||||
[Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz),
|
||||
[ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip), or
|
||||
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar).
|
||||
|
||||
* [Latest release](https://sqlite.org/src/rchvdwnld/release)
|
||||
* Latest release as
|
||||
[Tarball](https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release),
|
||||
[ZIP-archive](https://www.sqlite.org/src/zip/sqlite.zip?r=release), or
|
||||
[SQLite-archive](https://www.sqlite.org/src/sqlar/sqlite.sqlar?r=release).
|
||||
|
||||
* For other check-ins, browse the
|
||||
[project timeline](https://sqlite.org/src/timeline?y=ci) and
|
||||
click on the check-in hash of the check-in you want to download.
|
||||
On the resulting "info" page, click one of the options to the
|
||||
right of the "**Downloads:**" label in the "**Overview**" section
|
||||
near the top.
|
||||
* For other check-ins, substitute an appropriate branch name or
|
||||
tag or hash prefix in place of "release" in the URLs of the previous
|
||||
bullet. Or browse the [timeline](https://www.sqlite.org/src/timeline)
|
||||
to locate the check-in desired, click on its information page link,
|
||||
then click on the "Tarball" or "ZIP Archive" links on the information
|
||||
page.
|
||||
|
||||
To access sources directly using [Fossil](https://fossil-scm.org/home),
|
||||
first install Fossil version 2.0 or later.
|
||||
Source tarballs and precompiled binaries for Fossil are available at
|
||||
Source tarballs and precompiled binaries available at
|
||||
<https://fossil-scm.org/home/uv/download.html>. Fossil is
|
||||
a stand-alone program. To install, simply download or build the single
|
||||
executable file and put that file someplace on your $PATH or %PATH%.
|
||||
executable file and put that file someplace on your $PATH.
|
||||
Then run commands like this:
|
||||
|
||||
mkdir -p ~/sqlite
|
||||
cd ~/sqlite
|
||||
fossil open https://sqlite.org/src
|
||||
|
||||
The initial "fossil open" command will take two or three minutes. Afterwards,
|
||||
The "fossil open" command will take two or three minutes. Afterwards,
|
||||
you can do fast, bandwidth-efficient updates to the whatever versions
|
||||
of SQLite you like. Some examples:
|
||||
|
||||
@@ -127,7 +134,7 @@ later. The "tclextension-install" target and the test targets that follow
|
||||
all require TCL development libraries too. ("apt install tcl-dev"). It is
|
||||
helpful, but is not required, to install the SQLite TCL extension (the
|
||||
"tclextension-install" target) prior to running tests. The "releasetest"
|
||||
target has additional requirements, such as "valgrind".
|
||||
target has additional requiremenst, such as "valgrind".
|
||||
|
||||
On "make" command-lines, one can add "OPTIONS=..." to specify additional
|
||||
compile-time options over and above those set by ./configure. For example,
|
||||
@@ -145,8 +152,7 @@ show what changes are needed.
|
||||
## Compiling for Windows Using MSVC
|
||||
|
||||
On Windows, everything can be compiled with MSVC.
|
||||
You will also need a working installation of TCL if you want to run tests.
|
||||
TCL is not required if you just want to build SQLite itself.
|
||||
You will also need a working installation of TCL.
|
||||
See the [compile-for-windows.md](doc/compile-for-windows.md) document for
|
||||
additional information about how to install MSVC and TCL and configure your
|
||||
build environment.
|
||||
@@ -158,8 +164,8 @@ TCL library, using a command like this:
|
||||
|
||||
SQLite uses "tclsh.exe" as part of the build process, and so that
|
||||
program will need to be somewhere on your %PATH%. SQLite itself
|
||||
does not contain any TCL code, but it does use TCL to run tests.
|
||||
You may need to install TCL development
|
||||
does not contain any TCL code, but it does use TCL to help with the
|
||||
build process and to run tests. You may need to install TCL development
|
||||
libraries in order to successfully complete some makefile targets.
|
||||
It is helpful, but is not required, to install the SQLite TCL extension
|
||||
(the "tclextension-install" target) prior to running tests.
|
||||
@@ -302,14 +308,14 @@ individual source file exceeds 32K lines in length.
|
||||
## How It All Fits Together
|
||||
|
||||
SQLite is modular in design.
|
||||
See the [architectural description](https://sqlite.org/arch.html)
|
||||
See the [architectural description](https://www.sqlite.org/arch.html)
|
||||
for details. Other documents that are useful in
|
||||
helping to understand how SQLite works include the
|
||||
[file format](https://sqlite.org/fileformat2.html) description,
|
||||
the [virtual machine](https://sqlite.org/opcode.html) that runs
|
||||
[file format](https://www.sqlite.org/fileformat2.html) description,
|
||||
the [virtual machine](https://www.sqlite.org/opcode.html) that runs
|
||||
prepared statements, the description of
|
||||
[how transactions work](https://sqlite.org/atomiccommit.html), and
|
||||
the [overview of the query planner](https://sqlite.org/optoverview.html).
|
||||
[how transactions work](https://www.sqlite.org/atomiccommit.html), and
|
||||
the [overview of the query planner](https://www.sqlite.org/optoverview.html).
|
||||
|
||||
Decades of effort have gone into optimizing SQLite, both
|
||||
for small size and high performance. And optimizations tend to result in
|
||||
|
||||
@@ -4,66 +4,70 @@
|
||||
# This is the main autosetup-compatible configure script for the
|
||||
# SQLite project.
|
||||
#
|
||||
# This script and all of its dependencies must be kept compatible with
|
||||
# JimTCL, a copy of which is included in this source tree as
|
||||
# ./autosetup/jimsh0.c. The number of incompatibilities between
|
||||
# canonical TCL and JimTCL is very low and alternative formulations of
|
||||
# incompatible constructs have, so far, been easy to find.
|
||||
# This script should be kept compatible with JimTCL, a copy of which
|
||||
# is included in this source tree as ./autosetup/jimsh0.c. The number
|
||||
# of incompatibilities between canonical TCL and JimTCL is very low
|
||||
# and alternative formulations of incompatible constructs have, so
|
||||
# far, been easy to find.
|
||||
#
|
||||
# JimTCL: https://jim.tcl.tk
|
||||
#
|
||||
# Code-diver notes: APIs names starting with "sqlite-" are specific to
|
||||
# this project and can be found in autosetup/sqlite-config.tcl. Names
|
||||
# starting with "proj-" are project-agnostic and found in
|
||||
# autosetup/proj.tcl.
|
||||
#
|
||||
|
||||
use sqlite-config
|
||||
sqlite-configure canonical {
|
||||
proj-if-opt-truthy dev {
|
||||
# --enable-dev needs to come early so that the downstream tests
|
||||
# which check for the following flags use their updated state.
|
||||
proj-opt-set all 1
|
||||
proj-opt-set debug 1
|
||||
proj-opt-set amalgamation 0
|
||||
define CFLAGS [get-env CFLAGS {-O0 -g}]
|
||||
# -------------^^^^^^^ intentionally using [get-env] instead of
|
||||
# [proj-get-env] here because [sqlite-setup-default-cflags] uses
|
||||
# [proj-get-env] and we want this to supercede that.
|
||||
sqlite-munge-cflags; # straighten out -DSQLITE_ENABLE/OMIT flags
|
||||
}
|
||||
sqlite-handle-debug ;# must come after --dev flag check
|
||||
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
|
||||
sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
|
||||
sqlite-check-common-system-deps
|
||||
sqlite-config-bootstrap canonical
|
||||
sqlite-setup-default-cflags
|
||||
proj-if-opt-truthy dev {
|
||||
# --enable-dev needs to come early so that the downstream tests
|
||||
# which check for the following flags use their updated state.
|
||||
proj-opt-set all 1
|
||||
proj-opt-set debug 1
|
||||
proj-opt-set amalgamation 0
|
||||
define CFLAGS [get-env CFLAGS {-O0 -g}]
|
||||
# -------------^^^^^^^ intentionally using [get-env] instead of
|
||||
# [proj-get-env] here because [sqlite-setup-default-cflags] uses
|
||||
# [proj-get-env] and we want this to supercede that.
|
||||
}
|
||||
|
||||
proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?"
|
||||
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
|
||||
sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
|
||||
sqlite-check-common-system-deps
|
||||
|
||||
proj-define-for-opt gcov USE_GCOV "Use gcov?"
|
||||
#
|
||||
# Enable large file support (if special flags are necessary)
|
||||
#
|
||||
define HAVE_LFS 0
|
||||
if {[opt-bool largefile]} {
|
||||
cc-check-lfs
|
||||
}
|
||||
|
||||
proj-define-for-opt test-status TSTRNNR_OPTS \
|
||||
"test-runner flags:" {--status} {}
|
||||
proj-define-for-opt shared ENABLE_SHARED "Build shared library?"
|
||||
|
||||
proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
|
||||
"Use #line macros in the amalgamation:"
|
||||
if {![proj-define-for-opt static ENABLE_STATIC \
|
||||
"Build static library?"]} {
|
||||
proj-warn "Static lib build may be implicitly re-activated by other components, e.g. some test apps."
|
||||
}
|
||||
|
||||
define AMALGAMATION_EXTRA_SRC \
|
||||
[join [opt-val amalgamation-extra-src ""] " "]
|
||||
proj-define-for-opt amalgamation USE_AMALGAMATION "Use amalgamation for builds?"
|
||||
|
||||
define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
|
||||
proj-define-for-opt gcov USE_GCOV "Use gcov?"
|
||||
|
||||
if {[set fsan [join [opt-val asan-fsanitize] ","]] in {auto ""}} {
|
||||
set fsan address,bounds-strict
|
||||
}
|
||||
define CFLAGS_ASAN_FSANITIZE [proj-check-fsanitize [split $fsan ", "]]
|
||||
proj-define-for-opt test-status TSTRNNR_OPTS \
|
||||
"test-runner flags:" {--status} {}
|
||||
|
||||
sqlite-handle-tcl
|
||||
sqlite-handle-emsdk
|
||||
proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
|
||||
"Use #line macros in the amalgamation:"
|
||||
|
||||
proj-if-opt-truthy static-shells {
|
||||
proj-opt-set static-tclsqlite3 1
|
||||
proj-opt-set static-cli-shell 1
|
||||
}
|
||||
proj-define-for-opt static-tclsqlite3 STATIC_TCLSQLITE3 "Statically link tclsqlite3?"
|
||||
proj-define-for-opt static-cli-shell STATIC_CLI_SHELL "Statically link CLI shell?"
|
||||
define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
|
||||
|
||||
}; # sqlite-configure
|
||||
proj-check-rpath
|
||||
sqlite-handle-soname
|
||||
sqlite-handle-debug
|
||||
sqlite-handle-tcl
|
||||
sqlite-handle-threadsafe
|
||||
sqlite-handle-tempstore
|
||||
sqlite-handle-line-editing
|
||||
sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
sqlite-handle-emsdk
|
||||
sqlite-config-finalize
|
||||
|
||||
+61
-111
@@ -50,7 +50,6 @@ CC = @CC@
|
||||
|
||||
ENABLE_LIB_SHARED = @ENABLE_LIB_SHARED@
|
||||
ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@
|
||||
HAVE_WASI_SDK = @HAVE_WASI_SDK@
|
||||
|
||||
CFLAGS = @CFLAGS@ @CPPFLAGS@
|
||||
#
|
||||
@@ -72,8 +71,11 @@ LDFLAGS.rt = @LDFLAGS_RT@
|
||||
LDFLAGS.icu = @LDFLAGS_ICU@
|
||||
CFLAGS.icu = @CFLAGS_ICU@
|
||||
|
||||
# INSTALL reminder: we specifically do not strip binaries,
|
||||
# as discussed in https://sqlite.org/forum/forumpost/9a67df63eda9925c.
|
||||
# When cross-compiling, we need to avoid the -s flag because it only
|
||||
# works on the build host's platform.
|
||||
INSTALL.strip.1 = $(INSTALL)
|
||||
INSTALL.strip.0 = $(INSTALL) -s
|
||||
INSTALL.strip = $(INSTALL.strip.@IS_CROSS_COMPILING@)
|
||||
INSTALL.noexec = $(INSTALL) -m 0644
|
||||
|
||||
install-dir.bin = $(DESTDIR)$(bindir)
|
||||
@@ -117,19 +119,6 @@ sqlite_cfg.h: $(AS_AUTO_DEF)
|
||||
# CFLAGS for sqlite3$(T.exe)
|
||||
#
|
||||
SHELL_OPT ?= @OPT_SHELL@
|
||||
SHELL_OPT += -DSQLITE_DQS=0
|
||||
SHELL_OPT += -DSQLITE_ENABLE_FTS4
|
||||
#SHELL_OPT += -DSQLITE_ENABLE_FTS5
|
||||
SHELL_OPT += -DSQLITE_ENABLE_RTREE
|
||||
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
|
||||
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
SHELL_OPT += -DSQLITE_ENABLE_PERCENTILE
|
||||
SHELL_OPT += -DSQLITE_STRICT_SUBTYPE=1
|
||||
|
||||
#
|
||||
# Library-level feature flags
|
||||
@@ -138,8 +127,10 @@ OPT_FEATURE_FLAGS = @OPT_FEATURE_FLAGS@
|
||||
|
||||
LDFLAGS.libsqlite3.soname = @LDFLAGS_LIBSQLITE3_SONAME@
|
||||
# soname: see https://sqlite.org/src/forumpost/5a3b44f510df8ded
|
||||
LDFLAGS.libsqlite3.os-specific = \
|
||||
@LDFLAGS_MAC_CVERSION@ @LDFLAGS_MAC_INSTALL_NAME@ @LDFLAGS_OUT_IMPLIB@
|
||||
LDFLAGS.libsqlite3.os-specific = @LDFLAGS_MAC_CVERSION@ @LDFLAGS_OUT_IMPLIB@
|
||||
# os-specific: see
|
||||
# - https://sqlite.org/forum/forumpost/9dfd5b8fd525a5d7
|
||||
# - https://sqlite.org/forum/forumpost/0c7fc097b2
|
||||
|
||||
LDFLAGS.libsqlite3 = \
|
||||
$(LDFLAGS.rpath) $(LDFLAGS.pthread) \
|
||||
@@ -152,78 +143,57 @@ sqlite3.o: $(TOP)/sqlite3.h $(TOP)/sqlite3.c
|
||||
$(CC) -c $(TOP)/sqlite3.c -o $@ $(CFLAGS) $(CFLAGS.libsqlite3)
|
||||
|
||||
libsqlite3.LIB = libsqlite3$(T.lib)
|
||||
libsqlite3.DLL.basename = @SQLITE_DLL_BASENAME@
|
||||
libsqlite3.out.implib = @SQLITE_OUT_IMPLIB@
|
||||
libsqlite3.DLL = $(libsqlite3.DLL.basename)$(T.dll)
|
||||
libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@
|
||||
libsqlite3.SO = libsqlite3$(T.dll)
|
||||
|
||||
$(libsqlite3.DLL): sqlite3.o
|
||||
$(libsqlite3.SO): sqlite3.o
|
||||
$(CC) -o $@ sqlite3.o $(LDFLAGS.shlib) \
|
||||
$(LDFLAGS) $(LDFLAGS.libsqlite3) \
|
||||
$(LDFLAGS.libsqlite3.os-specific) $(LDFLAGS.libsqlite3.soname)
|
||||
$(libsqlite3.DLL)-1: $(libsqlite3.DLL)
|
||||
$(libsqlite3.DLL)-0:
|
||||
all: $(libsqlite3.DLL)-$(ENABLE_LIB_SHARED)
|
||||
all: $(libsqlite3.SO)
|
||||
|
||||
$(libsqlite3.LIB): sqlite3.o
|
||||
$(AR) $(AR.flags) $@ sqlite3.o
|
||||
$(libsqlite3.LIB)-1: $(libsqlite3.LIB)
|
||||
$(libsqlite3.LIB)-0:
|
||||
all: $(libsqlite3.LIB)-$(ENABLE_LIB_STATIC)
|
||||
all: $(libsqlite3.LIB)
|
||||
|
||||
#
|
||||
# Maintenance reminder: the install-dll-... rules must be kept in sync
|
||||
# with the main copies rom /main.mk.
|
||||
#
|
||||
install-dll-out-implib: $(install-dir.lib) $(libsqlite3.DLL)
|
||||
if [ x != "x$(libsqlite3.out.implib)" ] && [ -f "$(libsqlite3.out.implib)" ]; then \
|
||||
$(INSTALL) $(libsqlite3.out.implib) "$(install-dir.lib)"; \
|
||||
install-so-1: $(install-dir.lib) $(libsqlite3.SO)
|
||||
$(INSTALL) $(libsqlite3.SO) "$(install-dir.lib)"
|
||||
@if [ -f $(libsqlite3.SO).a ]; then \
|
||||
$(INSTALL) $(libsqlite3.SO).a "$(install-dir.lib)"; \
|
||||
fi
|
||||
@echo "Setting up $(libsqlite3.SO) version symlinks..."; \
|
||||
if [ x.dll = x$(T.dll) ]; then \
|
||||
echo "No library symlinks needed on this platform"; \
|
||||
elif [ x.dylib = x$(T.dll) ]; then \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
|
||||
dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
|
||||
mv $(libsqlite3.SO) $$dllname || exit $$?; \
|
||||
ln -s $$dllname $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
|
||||
ls -la $$dllname $(libsqlite3.SO) libsqlite3.0$(T.dll); \
|
||||
else \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
rm -f $(libsqlite3.SO).0 $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
|
||||
mv $(libsqlite3.SO) $(libsqlite3.SO).$(PACKAGE_VERSION) || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO) || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO) $(libsqlite3.SO).[a03]*; \
|
||||
if [ -e $(libsqlite3.SO).0.8.6 ]; then \
|
||||
echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
|
||||
rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO).0.8.6; \
|
||||
elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
|
||||
echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
|
||||
rm -f libsqlite3.la $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.SO).$(PACKAGE_VERSION) $(libsqlite3.SO).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.SO).0.8.6; \
|
||||
fi; \
|
||||
fi
|
||||
|
||||
install-dll-unix-generic: install-dll-out-implib
|
||||
$(INSTALL) $(libsqlite3.DLL) "$(install-dir.lib)"
|
||||
@echo "Setting up $(libsqlite3.DLL) version symlinks..."; \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
rm -f $(libsqlite3.DLL).0 $(libsqlite3.DLL).$(PACKAGE_VERSION) || exit $$?; \
|
||||
mv $(libsqlite3.DLL) $(libsqlite3.DLL).$(PACKAGE_VERSION) || exit $$?; \
|
||||
ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL) || exit $$?; \
|
||||
ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0 || exit $$?; \
|
||||
ls -la $(libsqlite3.DLL) $(libsqlite3.DLL).[a03]*; \
|
||||
if [ -e $(libsqlite3.DLL).0.8.6 ]; then \
|
||||
echo "ACHTUNG: legacy libtool-compatible install found. Re-linking it..."; \
|
||||
rm -f libsqlite3.la $(libsqlite3.DLL).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.DLL).0.8.6; \
|
||||
elif [ x1 = "x$(INSTALL_SO_086_LINK)" ]; then \
|
||||
echo "ACHTUNG: installing legacy libtool-style links because INSTALL_SO_086_LINK=1"; \
|
||||
rm -f libsqlite3.la $(libsqlite3.DLL).0.8.6 || exit $$?; \
|
||||
ln -s $(libsqlite3.DLL).$(PACKAGE_VERSION) $(libsqlite3.DLL).0.8.6 || exit $$?; \
|
||||
ls -la $(libsqlite3.DLL).0.8.6; \
|
||||
fi
|
||||
|
||||
install-dll-msys: install-dll-out-implib $(install-dir.bin)
|
||||
$(INSTALL) $(libsqlite3.DLL) "$(install-dir.bin)"
|
||||
# ----------------------------------------------^^^ yes, bin
|
||||
# Each of {msys,mingw,cygwin} uses a different name for the DLL, but
|
||||
# that is already accounted for via $(libsqlite3.DLL).
|
||||
install-dll-mingw: install-dll-msys
|
||||
install-dll-cygwin: install-dll-msys
|
||||
|
||||
install-dll-darwin: $(install-dir.lib) $(libsqlite3.DLL)
|
||||
$(INSTALL) $(libsqlite3.DLL) "$(install-dir.lib)"
|
||||
@echo "Setting up $(libsqlite3.DLL) version symlinks..."; \
|
||||
cd "$(install-dir.lib)" || exit $$?; \
|
||||
rm -f libsqlite3.0$(T.dll) libsqlite3.$(PACKAGE_VERSION)$(T.dll) || exit $$?; \
|
||||
dllname=libsqlite3.$(PACKAGE_VERSION)$(T.dll); \
|
||||
mv $(libsqlite3.DLL) $$dllname || exit $$?; \
|
||||
ln -s $$dllname $(libsqlite3.DLL) || exit $$?; \
|
||||
ln -s $$dllname libsqlite3.0$(T.dll) || exit $$?; \
|
||||
ls -la $$dllname $(libsqlite3.DLL) libsqlite3.0$(T.dll)
|
||||
|
||||
install-dll-1: install-dll-$(libsqlite3.DLL.install-rules)
|
||||
install-dll-0 install-dll-:
|
||||
install-dll: install-dll-$(ENABLE_LIB_SHARED)
|
||||
install: install-dll
|
||||
install-so-0 install-so-:
|
||||
install-so: install-so-$(ENABLE_LIB_SHARED)
|
||||
install: install-so
|
||||
|
||||
install-lib-1: $(install-dir.lib) $(libsqlite3.LIB)
|
||||
$(INSTALL.noexec) $(libsqlite3.LIB) "$(install-dir.lib)"
|
||||
@@ -231,46 +201,27 @@ install-lib-0 install-lib-:
|
||||
install-lib: install-lib-$(ENABLE_LIB_STATIC)
|
||||
install: install-lib
|
||||
|
||||
#
|
||||
|
||||
# Flags to link the shell app either directly against sqlite3.c
|
||||
# (ENABLE_STATIC_SHELL==1) or libsqlite3.so (ENABLE_STATIC_SHELL==0).
|
||||
#
|
||||
# Maintenance reminder: placement of $(LDFLAGS) is more relevant for
|
||||
# some platforms than others:
|
||||
# https://sqlite.org/forum/forumpost/d80ecdaddd
|
||||
ENABLE_STATIC_SHELL = @ENABLE_STATIC_SHELL@
|
||||
sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS) $(LDFLAGS.libsqlite3)
|
||||
sqlite3-shell-link-flags.0 = $(LDFLAGS) -L. -lsqlite3 $(LDFLAGS.zlib) $(LDFLAGS.math)
|
||||
sqlite3-shell-link-flags.1 = $(TOP)/sqlite3.c $(LDFLAGS.libsqlite3)
|
||||
sqlite3-shell-link-flags.0 = -L. -lsqlite3 $(LDFLAGS.zlib)
|
||||
sqlite3-shell-deps.1 = $(TOP)/sqlite3.c
|
||||
sqlite3-shell-deps.0 = $(libsqlite3.DLL)
|
||||
#
|
||||
# STATIC_CLI_SHELL = 1 to statically link sqlite3$(T.exe), else
|
||||
# 0. Requires static versions of all requisite libraries. Primarily
|
||||
# intended for use with static-friendly environments like Alpine
|
||||
# Linux.
|
||||
#
|
||||
STATIC_CLI_SHELL = @STATIC_CLI_SHELL@
|
||||
#
|
||||
# sqlite3-shell-static.flags.N = N is $(STATIC_CLI_SHELL)
|
||||
#
|
||||
sqlite3-shell-static.flags.1 = -static
|
||||
sqlite3-shell-static.flags.0 =
|
||||
sqlite3-shell-deps.0 = $(libsqlite3.SO)
|
||||
sqlite3$(T.exe): $(TOP)/shell.c $(sqlite3-shell-deps.$(ENABLE_STATIC_SHELL))
|
||||
$(CC) -o $@ \
|
||||
$(TOP)/shell.c $(sqlite3-shell-link-flags.$(ENABLE_STATIC_SHELL)) \
|
||||
$(sqlite3-shell-static.flags.$(STATIC_CLI_SHELL)) \
|
||||
-I. $(OPT_FEATURE_FLAGS) $(SHELL_OPT) \
|
||||
$(CFLAGS) $(CFLAGS.readline) $(CFLAGS.icu) \
|
||||
$(LDFLAGS.readline)
|
||||
$(LDFLAGS) $(LDFLAGS.readline)
|
||||
|
||||
sqlite3$(T.exe)-1:
|
||||
sqlite3$(T.exe)-0: sqlite3$(T.exe)
|
||||
all: sqlite3$(T.exe)-$(HAVE_WASI_SDK)
|
||||
all: sqlite3$(T.exe)
|
||||
|
||||
install-shell-0: sqlite3$(T.exe) $(install-dir.bin)
|
||||
$(INSTALL) sqlite3$(T.exe) "$(install-dir.bin)"
|
||||
install-shell-1:
|
||||
install: install-shell-$(HAVE_WASI_SDK)
|
||||
install-shell: sqlite3$(T.exe) $(install-dir.bin)
|
||||
$(INSTALL.strip) sqlite3$(T.exe) "$(install-dir.bin)"
|
||||
install: install-shell
|
||||
|
||||
install-headers: $(TOP)/sqlite3.h $(install-dir.include)
|
||||
$(INSTALL.noexec) $(TOP)/sqlite3.h $(TOP)/sqlite3ext.h "$(install-dir.include)"
|
||||
@@ -286,7 +237,7 @@ install: install-man1
|
||||
|
||||
clean:
|
||||
rm -f *.o sqlite3$(T.exe)
|
||||
rm -f $(libsqlite3.LIB) $(libsqlite3.DLL) libsqlite3$(T.dll).a
|
||||
rm -f $(libsqlite3.LIB) $(libsqlite3.SO) $(libsqlite3.SO).a
|
||||
|
||||
distclean: clean
|
||||
rm -f jimsh0$(T.exe) config.* sqlite3.pc sqlite_cfg.h Makefile
|
||||
@@ -299,16 +250,15 @@ DIST_FILES := \
|
||||
sqlite3.rc sqlite3rc.h Replace.cs \
|
||||
sqlite3.pc.in sqlite3.1
|
||||
|
||||
#
|
||||
# Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so
|
||||
# that tool/mkautoconfamal.sh knows how to find it.
|
||||
#
|
||||
dist_name = sqlite-$(PACKAGE_VERSION)
|
||||
dist_tarball = $(dist_name).tar.gz
|
||||
dist:
|
||||
rm -fr $(dist_name)
|
||||
mkdir -p $(dist_name)
|
||||
cp -rp $(DIST_FILES) $(dist_name)/.
|
||||
rm -f $(dist_name)/tea/configure.ac.in
|
||||
tar czf $(dist_tarball) $(dist_name)
|
||||
rm -fr $(dist_name)
|
||||
ls -l $(dist_tarball)
|
||||
|
||||
+2
-19
@@ -247,12 +247,6 @@ SESSION = 0
|
||||
RBU = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this to non-0 to enable support for blocking locks.
|
||||
#
|
||||
!IFNDEF SETLK_TIMEOUT
|
||||
SETLK_TIMEOUT = 0
|
||||
!ENDIF
|
||||
|
||||
# Set the source code file to be used by executables and libraries when
|
||||
# they need the amalgamation.
|
||||
#
|
||||
@@ -327,7 +321,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_CARRAY=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
@@ -350,7 +343,6 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
|
||||
|
||||
# Always enable math functions on Windows
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PERCENTILE
|
||||
|
||||
# Should the rbu extension be enabled? If so, add compilation options
|
||||
# to enable it.
|
||||
@@ -380,10 +372,6 @@ EXT_FEATURE_FLAGS =
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IF $(SETLK_TIMEOUT)!=0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SETLK_TIMEOUT
|
||||
!ENDIF
|
||||
|
||||
###############################################################################
|
||||
############################### END OF OPTIONS ################################
|
||||
###############################################################################
|
||||
@@ -695,21 +683,17 @@ BCC = $(BCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
|
||||
!IF $(DEBUG)>1
|
||||
TCC = $(TCC) -MDd
|
||||
BCC = $(BCC) -MDd
|
||||
ZLIBCFLAGS = -nologo -MDd -W3 -O2 -Oy- -Zi
|
||||
!ELSE
|
||||
TCC = $(TCC) -MD
|
||||
BCC = $(BCC) -MD
|
||||
ZLIBCFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi
|
||||
!ENDIF
|
||||
!ELSE
|
||||
!IF $(DEBUG)>1
|
||||
TCC = $(TCC) -MTd
|
||||
BCC = $(BCC) -MTd
|
||||
ZLIBCFLAGS = -nologo -MTd -W3 -O2 -Oy- -Zi
|
||||
!ELSE
|
||||
TCC = $(TCC) -MT
|
||||
BCC = $(BCC) -MT
|
||||
ZLIBCFLAGS = -nologo -MT -W3 -O2 -Oy- -Zi
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@@ -730,7 +714,7 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
|
||||
!ENDIF
|
||||
|
||||
!IF $(DEBUG)>2
|
||||
TCC = $(TCC) -DSQLITE_DEBUG=1 -DSQLITE_USE_W32_FOR_CONSOLE_IO
|
||||
TCC = $(TCC) -DSQLITE_DEBUG=1
|
||||
RCC = $(RCC) -DSQLITE_DEBUG=1
|
||||
!IF $(DYNAMIC_SHELL)==0
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
|
||||
@@ -1021,7 +1005,6 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_DQS=0
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_PERCENTILE=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_STMT_SCANSTATUS=1
|
||||
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_STRICT_SUBTYPE=1
|
||||
@@ -1105,5 +1088,5 @@ $(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H)
|
||||
clean:
|
||||
del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
|
||||
del /Q *.bsc *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def ctime.c pragma.h 2>NUL
|
||||
del /Q sqlite3.def tclsqlite3.def 2>NUL
|
||||
del /Q $(SQLITE3EXE) $(SQLITE3DLL) Replace.exe 2>NUL
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ the embedded copy of JimTCL).
|
||||
REASONS TO USE THE CANONICAL BUILD SYSTEM RATHER THAN THIS PACKAGE
|
||||
==================================================================
|
||||
|
||||
* the canonical build system allows you to run tests to verify that
|
||||
* the cononical build system allows you to run tests to verify that
|
||||
the build worked
|
||||
* the canonical build system supports more compile-time options
|
||||
* the canonical build system works for any arbitrary check-in to
|
||||
@@ -90,7 +90,7 @@ Other preprocessor defines
|
||||
Additionally, preprocessor defines may be specified by using the OPTS macro
|
||||
on the NMAKE command line. However, not all possible preprocessor defines
|
||||
may be specified in this manner as some require the amalgamation to be built
|
||||
with them enabled (see http://sqlite.org/compile.html). For example, the
|
||||
with them enabled (see http://www.sqlite.org/compile.html). For example, the
|
||||
following will work:
|
||||
|
||||
"OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_OMIT_JSON=1"
|
||||
|
||||
+23
-19
@@ -3,23 +3,27 @@
|
||||
#
|
||||
# This is the main autosetup-compatible configure script for the
|
||||
# "autoconf" bundle of the SQLite project.
|
||||
#
|
||||
# This script must be kept compatible with JimTCL, a copy of which is
|
||||
# included in this source tree as ./autosetup/jimsh0.c.
|
||||
#
|
||||
use sqlite-config
|
||||
sqlite-configure autoconf {
|
||||
sqlite-handle-debug
|
||||
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
|
||||
sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
|
||||
sqlite-check-common-system-deps
|
||||
proj-define-for-opt static-shell ENABLE_STATIC_SHELL \
|
||||
"Link library statically into the CLI shell?"
|
||||
proj-define-for-opt static-cli-shell STATIC_CLI_SHELL "Statically link CLI shell?"
|
||||
if {![opt-bool static-shell] && [opt-bool static-cli-shell]} {
|
||||
proj-fatal "--disable-static-shell and --static-cli-shell are mutualy exclusive"
|
||||
}
|
||||
if {![opt-bool shared] && ![opt-bool static-shell]} {
|
||||
proj-opt-set shared 1
|
||||
proj-indented-notice {
|
||||
NOTICE: ignoring --disable-shared because --disable-static-shell
|
||||
was specified.
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite-config-bootstrap autoconf
|
||||
sqlite-check-common-bins
|
||||
sqlite-check-common-system-deps
|
||||
proj-check-rpath
|
||||
sqlite-handle-soname
|
||||
sqlite-setup-default-cflags
|
||||
sqlite-handle-debug
|
||||
sqlite-handle-threadsafe
|
||||
sqlite-handle-tempstore
|
||||
sqlite-handle-line-editing
|
||||
sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
|
||||
define ENABLE_STATIC_SHELL [opt-bool static-shell]
|
||||
define ENABLE_LIB_SHARED [opt-bool shared]
|
||||
define ENABLE_LIB_STATIC [opt-bool static]
|
||||
|
||||
sqlite-config-finalize
|
||||
|
||||
+428
-524
@@ -1,559 +1,463 @@
|
||||
all:
|
||||
# Makefile.in --
|
||||
#
|
||||
# Unless this file is named Makefile.in, you are probably looking
|
||||
# at an automatically generated/filtered copy and should probably not
|
||||
# edit it.
|
||||
# This file is a Makefile for Sample TEA Extension. If it has the name
|
||||
# "Makefile.in" then it is a template for a Makefile; to generate the
|
||||
# actual Makefile, run "./configure", which is a configuration script
|
||||
# generated by the "autoconf" program (constructs like "@foo@" will get
|
||||
# replaced in the actual Makefile.
|
||||
#
|
||||
# This makefile is part of the teaish framework, a tool for building
|
||||
# Tcl extensions, conceptually related to TEA/tclconfig but using the
|
||||
# Autosetup configuration system instead of the GNU Autotools.
|
||||
#
|
||||
# A copy of this makefile gets processed for each extension separately
|
||||
# and populated with info about how to build, test, and install the
|
||||
# extension.
|
||||
#
|
||||
# Maintenance reminder: this file needs to stay portable with POSIX
|
||||
# Make, not just GNU Make. Yes, that's unfortunate because it makes
|
||||
# some things impossible (like skipping over swathes of rules when
|
||||
# 'make distclean' is invoked).
|
||||
# Copyright (c) 1999 Scriptics Corporation.
|
||||
# Copyright (c) 2002-2005 ActiveState Corporation.
|
||||
#
|
||||
# See the file "license.terms" for information on usage and redistribution
|
||||
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @BIN_INSTALL@
|
||||
INSTALL.noexec = $(INSTALL) -m 0644
|
||||
#========================================================================
|
||||
# Add additional lines to handle any additional AC_SUBST cases that
|
||||
# have been added in a customized configure script.
|
||||
#========================================================================
|
||||
|
||||
#
|
||||
# Var name prefixes:
|
||||
#
|
||||
# teaish. => teaish core
|
||||
# tx. => teaish extension
|
||||
#
|
||||
# Vars with a "tx." or "teaish." prefix are all "public" for purposes
|
||||
# of the extension makefile, but the extension must not any "teaish."
|
||||
# vars and must only modify "tx." vars where that allowance is
|
||||
# specifically noted.
|
||||
#
|
||||
# Vars with a "teaish__" prefix are "private" and must not be used by
|
||||
# the extension makefile. They may change semantics or be removed in
|
||||
# any given teaish build.
|
||||
#
|
||||
tx.name = @TEAISH_NAME@
|
||||
tx.version = @TEAISH_VERSION@
|
||||
tx.name.pkg = @TEAISH_PKGNAME@
|
||||
tx.libdir = @TEAISH_LIBDIR_NAME@
|
||||
tx.loadPrefix = @TEAISH_LOAD_PREFIX@
|
||||
tx.tcl = @TEAISH_TCL@
|
||||
tx.makefile = @TEAISH_MAKEFILE@
|
||||
tx.makefile.in = @TEAISH_MAKEFILE_IN@
|
||||
tx.dll8.basename = @TEAISH_DLL8_BASENAME@
|
||||
tx.dll9.basename = @TEAISH_DLL9_BASENAME@
|
||||
tx.dll8 = @TEAISH_DLL8@
|
||||
tx.dll9 = @TEAISH_DLL9@
|
||||
tx.dll = $(tx.dll$(TCL_MAJOR_VERSION))
|
||||
tx.dir = @TEAISH_EXT_DIR@
|
||||
@if TEAISH_TM_TCL
|
||||
# Input filename for tcl::tm-style module
|
||||
tx.tm = @TEAISH_TM_TCL@
|
||||
# Target filename for tcl::tm-style installation
|
||||
tx.tm.tgt = $(tx.name.pkg)-$(tx.version).tm
|
||||
@endif
|
||||
#SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@
|
||||
|
||||
@if TEAISH_DIST_NAME
|
||||
tx.name.dist = @TEAISH_DIST_NAME@
|
||||
@else
|
||||
tx.name.dist = $(teaish.name)
|
||||
@endif
|
||||
#========================================================================
|
||||
# Nothing of the variables below this line should need to be changed.
|
||||
# Please check the TARGETS section below to make sure the make targets
|
||||
# are correct.
|
||||
#========================================================================
|
||||
|
||||
teaish.dir = @abs_top_srcdir@
|
||||
#teaish.dir.autosetup = @TEAISH_AUTOSETUP_DIR@
|
||||
teaish.makefile = Makefile
|
||||
teaish.makefile.in = $(teaish.dir)/Makefile.in
|
||||
teaish__auto.def = $(teaish.dir)/auto.def
|
||||
#========================================================================
|
||||
# The names of the source files is defined in the configure script.
|
||||
# The object files are used for linking into the final library.
|
||||
# This will be used when a dist target is added to the Makefile.
|
||||
# It is not important to specify the directory, as long as it is the
|
||||
# $(srcdir) or in the generic, win or unix subdirectory.
|
||||
#========================================================================
|
||||
|
||||
PKG_SOURCES = @PKG_SOURCES@
|
||||
PKG_OBJECTS = @PKG_OBJECTS@
|
||||
|
||||
PKG_STUB_SOURCES = @PKG_STUB_SOURCES@
|
||||
PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@
|
||||
|
||||
#========================================================================
|
||||
# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with
|
||||
# this package that need to be installed, if any.
|
||||
#========================================================================
|
||||
|
||||
PKG_TCL_SOURCES = @PKG_TCL_SOURCES@
|
||||
|
||||
#========================================================================
|
||||
# This is a list of public header files to be installed, if any.
|
||||
#========================================================================
|
||||
|
||||
PKG_HEADERS = @PKG_HEADERS@
|
||||
|
||||
#========================================================================
|
||||
# "PKG_LIB_FILE" refers to the library (dynamic or static as per
|
||||
# configuration options) composed of the named objects.
|
||||
#========================================================================
|
||||
|
||||
PKG_LIB_FILE = @PKG_LIB_FILE@
|
||||
PKG_LIB_FILE8 = @PKG_LIB_FILE8@
|
||||
PKG_LIB_FILE9 = @PKG_LIB_FILE9@
|
||||
PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@
|
||||
|
||||
lib_BINARIES = $(PKG_LIB_FILE)
|
||||
BINARIES = $(lib_BINARIES)
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = @includedir@
|
||||
datarootdir = @datarootdir@
|
||||
runstatedir = @runstatedir@
|
||||
datadir = @datadir@
|
||||
mandir = @mandir@
|
||||
|
||||
DESTDIR =
|
||||
|
||||
PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION)
|
||||
pkgdatadir = $(datadir)/$(PKG_DIR)
|
||||
pkglibdir = $(libdir)/$(PKG_DIR)
|
||||
pkgincludedir = $(includedir)/$(PKG_DIR)
|
||||
|
||||
top_builddir = @abs_top_builddir@
|
||||
|
||||
INSTALL_OPTIONS =
|
||||
INSTALL = @INSTALL@ $(INSTALL_OPTIONS)
|
||||
INSTALL_DATA_DIR = @INSTALL_DATA_DIR@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_LIBRARY = @INSTALL_LIBRARY@
|
||||
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
CC = @CC@
|
||||
CFLAGS_DEFAULT = @CFLAGS_DEFAULT@
|
||||
CFLAGS_WARNING = @CFLAGS_WARNING@
|
||||
EXEEXT = @EXEEXT@
|
||||
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
|
||||
MAKE_LIB = @MAKE_LIB@
|
||||
MAKE_STUB_LIB = @MAKE_STUB_LIB@
|
||||
OBJEXT = @OBJEXT@
|
||||
RANLIB = @RANLIB@
|
||||
RANLIB_STUB = @RANLIB_STUB@
|
||||
SHLIB_CFLAGS = @SHLIB_CFLAGS@
|
||||
SHLIB_LD = @SHLIB_LD@
|
||||
SHLIB_LD_LIBS = @SHLIB_LD_LIBS@
|
||||
STLIB_LD = @STLIB_LD@
|
||||
#TCL_DEFS = @TCL_DEFS@
|
||||
TCL_BIN_DIR = @TCL_BIN_DIR@
|
||||
TCL_SRC_DIR = @TCL_SRC_DIR@
|
||||
#TK_BIN_DIR = @TK_BIN_DIR@
|
||||
#TK_SRC_DIR = @TK_SRC_DIR@
|
||||
|
||||
# Not used, but retained for reference of what libs Tcl required
|
||||
#TCL_LIBS = @TCL_LIBS@
|
||||
|
||||
#========================================================================
|
||||
# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
|
||||
# package without installing. The other environment variables allow us
|
||||
# to test against an uninstalled Tcl. Add special env vars that you
|
||||
# require for testing here (like TCLX_LIBRARY).
|
||||
#========================================================================
|
||||
|
||||
EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR)
|
||||
#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
|
||||
TCLLIBPATH = $(top_builddir)
|
||||
TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library`
|
||||
PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
|
||||
PATH="$(EXTRA_PATH):$(PATH)" \
|
||||
TCLLIBPATH="$(TCLLIBPATH)"
|
||||
|
||||
TCLSH_PROG = @TCLSH_PROG@
|
||||
TCLSH = $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG)
|
||||
|
||||
#WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
|
||||
#WISH_PROG = @WISH_PROG@
|
||||
#WISH = $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG)
|
||||
|
||||
SHARED_BUILD = @SHARED_BUILD@
|
||||
|
||||
INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I. -I$(srcdir)/..
|
||||
#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@
|
||||
|
||||
PKG_CFLAGS = @PKG_CFLAGS@
|
||||
|
||||
# TCL_DEFS is not strictly need here, but if you remove it, then you
|
||||
# must make sure that configure.ac checks for the necessary components
|
||||
# that your library may use. TCL_DEFS can actually be a problem if
|
||||
# you do not compile with a similar machine setup as the Tcl core was
|
||||
# compiled with.
|
||||
#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
|
||||
DEFS = @DEFS@ $(PKG_CFLAGS)
|
||||
|
||||
# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
|
||||
CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
|
||||
CLEANFILES = @CLEANFILES@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LIBS = @PKG_LIBS@ @LIBS@
|
||||
AR = @AR@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \
|
||||
$(CFLAGS_DEFAULT) $(CFLAGS_WARNING) $(SHLIB_CFLAGS) $(CFLAGS)
|
||||
|
||||
GDB = gdb
|
||||
VALGRIND = valgrind
|
||||
VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \
|
||||
--leak-check=yes --show-reachable=yes -v
|
||||
|
||||
.SUFFIXES: .c .$(OBJEXT)
|
||||
|
||||
#========================================================================
|
||||
# Start of user-definable TARGETS section
|
||||
#========================================================================
|
||||
|
||||
#========================================================================
|
||||
# TEA TARGETS. Please note that the "libraries:" target refers to platform
|
||||
# independent files, and the "binaries:" target includes executable programs and
|
||||
# platform-dependent libraries. Modify these targets so that they install
|
||||
# the various pieces of your package. The make and install rules
|
||||
# for the BINARIES that you specified above have already been done.
|
||||
#========================================================================
|
||||
|
||||
all: binaries libraries doc
|
||||
|
||||
#========================================================================
|
||||
# The binaries target builds executable programs, Windows .dll's, unix
|
||||
# shared/static libraries, and any other platform-dependent files.
|
||||
# The list of targets to build for "binaries:" is specified at the top
|
||||
# of the Makefile, in the "BINARIES" variable.
|
||||
#========================================================================
|
||||
|
||||
binaries: $(BINARIES)
|
||||
|
||||
libraries:
|
||||
|
||||
#========================================================================
|
||||
# Your doc target should differentiate from doc builds (by the developer)
|
||||
# and doc installs (see install-doc), which just install the docs on the
|
||||
# end user machine when building from source.
|
||||
#========================================================================
|
||||
|
||||
doc:
|
||||
@echo "If you have documentation to create, place the commands to"
|
||||
@echo "build the docs in the 'doc:' target. For example:"
|
||||
@echo " xml2nroff sample.xml > sample.n"
|
||||
@echo " xml2html sample.xml > sample.html"
|
||||
|
||||
install: all install-binaries install-libraries install-doc
|
||||
|
||||
install-binaries: binaries install-lib-binaries install-bin-binaries
|
||||
|
||||
#========================================================================
|
||||
# This rule installs platform-independent files, such as header files.
|
||||
# The list=...; for p in $$list handles the empty list case x-platform.
|
||||
#========================================================================
|
||||
|
||||
install-libraries: libraries
|
||||
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(includedir)"
|
||||
@echo "Installing header files in $(DESTDIR)$(includedir)"
|
||||
@list='$(PKG_HEADERS)'; for i in $$list; do \
|
||||
echo "Installing $(srcdir)/$$i" ; \
|
||||
$(INSTALL_DATA) $(srcdir)/$$i "$(DESTDIR)$(includedir)" ; \
|
||||
done;
|
||||
|
||||
#========================================================================
|
||||
# Install documentation. Unix manpages should go in the $(mandir)
|
||||
# directory.
|
||||
#========================================================================
|
||||
|
||||
install-doc: doc
|
||||
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(mandir)/mann"
|
||||
@echo "Installing documentation in $(DESTDIR)$(mandir)"
|
||||
@list='$(srcdir)/doc/*.n'; for i in $$list; do \
|
||||
echo "Installing $$i"; \
|
||||
$(INSTALL_DATA) $$i "$(DESTDIR)$(mandir)/mann" ; \
|
||||
done
|
||||
|
||||
test: binaries libraries
|
||||
@echo "SQLite TEA distribution does not include tests"
|
||||
|
||||
shell: binaries libraries
|
||||
@$(TCLSH) $(SCRIPT)
|
||||
|
||||
gdb:
|
||||
$(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT)
|
||||
|
||||
gdb-test: binaries libraries
|
||||
$(TCLSH_ENV) $(PKG_ENV) $(GDB) \
|
||||
--args $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` \
|
||||
$(TESTFLAGS) -singleproc 1 \
|
||||
-load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \
|
||||
[list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]"
|
||||
|
||||
valgrind: binaries libraries
|
||||
$(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) \
|
||||
`@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)
|
||||
|
||||
valgrindshell: binaries libraries
|
||||
$(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)
|
||||
|
||||
depend:
|
||||
|
||||
#========================================================================
|
||||
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
|
||||
# mentioned above. That will ensure that this target is built when you
|
||||
# run "make binaries".
|
||||
#
|
||||
# Autotools-conventional vars. We don't actually use these in this
|
||||
# makefile but some may be referenced by vars imported via
|
||||
# tclConfig.sh. They are part of the public API and may be reliably
|
||||
# depended on from teaish.make.in.
|
||||
# The $(PKG_OBJECTS) objects are created and linked into the final
|
||||
# library. In most cases these object files will correspond to the
|
||||
# source files above.
|
||||
#========================================================================
|
||||
|
||||
$(PKG_LIB_FILE): $(PKG_OBJECTS)
|
||||
-rm -f $(PKG_LIB_FILE)
|
||||
${MAKE_LIB}
|
||||
$(RANLIB) $(PKG_LIB_FILE)
|
||||
|
||||
$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
|
||||
-rm -f $(PKG_STUB_LIB_FILE)
|
||||
${MAKE_STUB_LIB}
|
||||
$(RANLIB_STUB) $(PKG_STUB_LIB_FILE)
|
||||
|
||||
#========================================================================
|
||||
# We need to enumerate the list of .c to .o lines here.
|
||||
#
|
||||
bindir = @bindir@
|
||||
datadir = @datadir@
|
||||
exec_prefix = @exec_prefix@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
prefix = @prefix@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
# In the following lines, $(srcdir) refers to the toplevel directory
|
||||
# containing your extension. If your sources are in a subdirectory,
|
||||
# you will have to modify the paths to reflect this:
|
||||
#
|
||||
# sample.$(OBJEXT): $(srcdir)/generic/sample.c
|
||||
# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
|
||||
#
|
||||
# Setting the VPATH variable to a list of paths will cause the makefile
|
||||
# to look into these paths when resolving .c to .obj dependencies.
|
||||
# As necessary, add $(srcdir):$(srcdir)/compat:....
|
||||
#========================================================================
|
||||
|
||||
VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx
|
||||
|
||||
.c.@OBJEXT@:
|
||||
$(COMPILE) -c `@CYGPATH@ $<` -o $@
|
||||
|
||||
|
||||
#
|
||||
# Vars derived (mostly) from tclConfig.sh. These may be reliably
|
||||
# used from the extension makefile.
|
||||
#
|
||||
TCLSH = @TCLSH_CMD@
|
||||
TCL_CONFIG_SH = @TCL_CONFIG_SH@
|
||||
TCL_EXEC_PREFIX = @TCL_EXEC_PREFIX@
|
||||
TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@
|
||||
TCL_LIBS = @TCL_LIBS@
|
||||
TCL_LIB_SPEC = @TCL_LIB_SPEC@
|
||||
TCL_MAJOR_VERSION = @TCL_MAJOR_VERSION@
|
||||
TCL_MINOR_VERSION = @TCL_MINOR_VERSION@
|
||||
TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@
|
||||
TCL_PREFIX = @TCL_PREFIX@
|
||||
TCL_SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
|
||||
TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@
|
||||
TCL_VERSION = @TCL_VERSION@
|
||||
TCLLIBDIR = @TCLLIBDIR@
|
||||
#========================================================================
|
||||
# Distribution creation
|
||||
# You may need to tweak this target to make it work correctly.
|
||||
#========================================================================
|
||||
|
||||
#
|
||||
# CFLAGS.configure = CFLAGS as known at configure-time.
|
||||
#
|
||||
# This ordering is deliberate: flags populated via tcl's
|
||||
# [teaish-cflags-add] should preceed CFLAGS and CPPFLAGS (which
|
||||
# typically come from the ./configure command-line invocation).
|
||||
#
|
||||
CFLAGS.configure = @SH_CFLAGS@ @TEAISH_CFLAGS@ @CFLAGS@ @CPPFLAGS@ $(TCL_INCLUDE_SPEC)
|
||||
CFLAGS.configure += -DUSE_TCL_STUBS=@TEAISH_USE_STUBS@
|
||||
#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
|
||||
COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
|
||||
DIST_ROOT = /tmp/dist
|
||||
DIST_DIR = $(DIST_ROOT)/$(PKG_DIR)
|
||||
|
||||
#
|
||||
# LDFLAGS.configure = LDFLAGS as known at configure-time.
|
||||
#
|
||||
# This ordering is deliberate: flags populated via tcl's
|
||||
# [teaish-ldflags-add] should precede LDFLAGS (which typically
|
||||
# comes from the ./configure command-line invocation).
|
||||
#
|
||||
LDFLAGS.configure = @TEAISH_LDFLAGS@ @LDFLAGS@
|
||||
DIST_INSTALL_DATA = CPPROG='cp -p' $(INSTALL) -m 644
|
||||
DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755
|
||||
|
||||
#
|
||||
# Linker flags for linkhing a shared library.
|
||||
#
|
||||
LDFLAGS.shlib = @SH_LDFLAGS@
|
||||
dist-clean:
|
||||
rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*
|
||||
|
||||
#
|
||||
# The following tx.XYZ vars may be populated/modified by teaish.tcl
|
||||
# and/or teaish.make.
|
||||
#
|
||||
dist: dist-clean $(srcdir)/manifest.uuid
|
||||
$(INSTALL_DATA_DIR) $(DIST_DIR)
|
||||
|
||||
#
|
||||
# tx.src is the list of source or object files to include in the
|
||||
# (single) compiler/linker invocation. This will initially contain any
|
||||
# sources passed to [teaish-src-add], but may also be appended to by
|
||||
# teaish.make.
|
||||
#
|
||||
tx.src = @TEAISH_EXT_SRC@
|
||||
# TEA files
|
||||
$(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \
|
||||
$(srcdir)/aclocal.m4 $(srcdir)/configure.ac \
|
||||
$(DIST_DIR)/
|
||||
$(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/
|
||||
|
||||
#
|
||||
# tx.CFLAGS is typically set by teaish.make, whereas TEAISH_CFLAGS
|
||||
# gets set up via the configure script.
|
||||
#
|
||||
tx.CFLAGS =
|
||||
tx.CPPFLAGS =
|
||||
$(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig
|
||||
$(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \
|
||||
$(srcdir)/manifest.uuid \
|
||||
$(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \
|
||||
$(DIST_DIR)/tclconfig/
|
||||
|
||||
#
|
||||
# tx.LDFLAGS is typically set by teaish.make, whereas TEAISH_LDFLAGS
|
||||
# gets set up via the configure script.
|
||||
#
|
||||
tx.LDFLAGS =
|
||||
# Extension files
|
||||
$(DIST_INSTALL_DATA) \
|
||||
$(srcdir)/ChangeLog \
|
||||
$(srcdir)/README.sha \
|
||||
$(srcdir)/license.terms \
|
||||
$(srcdir)/README \
|
||||
$(srcdir)/pkgIndex.tcl.in \
|
||||
$(DIST_DIR)/
|
||||
|
||||
#
|
||||
# The list of 'dist' files may be appended to from teaish.make.in.
|
||||
# It can also be set up from teaish.tcl using [teaish-dist-add]
|
||||
# and/or [teaish-src-add -dist ...].
|
||||
#
|
||||
tx.dist.files = @TEAISH_DIST_FILES@
|
||||
list='demos doc generic library macosx tests unix win'; \
|
||||
for p in $$list; do \
|
||||
if test -d $(srcdir)/$$p ; then \
|
||||
$(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \
|
||||
$(DIST_INSTALL_DATA) $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
#
|
||||
# The base name for a distribution tar/zip file.
|
||||
#
|
||||
tx.dist.basename = $(tx.name.dist)-$(tx.version)
|
||||
(cd $(DIST_ROOT); $(COMPRESS);)
|
||||
|
||||
# List of deps which may trigger an auto-reconfigure.
|
||||
#
|
||||
teaish__autogen.deps = \
|
||||
$(tx.makefile.in) $(teaish.makefile.in) \
|
||||
$(tx.tcl) \
|
||||
@TEAISH_PKGINDEX_TCL_IN@ @TEAISH_TM_TCL_IN@ \
|
||||
@AUTODEPS@
|
||||
#========================================================================
|
||||
# End of user-definable section
|
||||
#========================================================================
|
||||
|
||||
@if TEAISH_MAKEFILE_IN
|
||||
$(tx.makefile): $(tx.makefile.in)
|
||||
@endif
|
||||
#========================================================================
|
||||
# Don't modify the file to clean here. Instead, set the "CLEANFILES"
|
||||
# variable in configure.ac
|
||||
#========================================================================
|
||||
|
||||
teaish.autoreconfig = \
|
||||
@TEAISH_AUTORECONFIG@
|
||||
clean:
|
||||
-test -z "$(BINARIES)" || rm -f $(BINARIES)
|
||||
-rm -f *.$(OBJEXT) core *.core
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
#
|
||||
# Problem: when more than one target can invoke TEAISH_AUTORECONFIG,
|
||||
# we can get parallel reconfigures running. Thus, targets which
|
||||
# may require reconfigure should depend on...
|
||||
#
|
||||
config.log: $(teaish__autogen.deps)
|
||||
$(teaish.autoreconfig)
|
||||
# ^^^ We would love to skip this when running [dist]clean, but there's
|
||||
# no POSIX Make-portable way to do that. GNU Make can.
|
||||
.PHONY: reconfigure
|
||||
reconfigure:
|
||||
$(teaish.autoreconfig)
|
||||
distclean: clean
|
||||
-rm -f *.tab.c
|
||||
-rm -f $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log config.status
|
||||
|
||||
$(teaish.makefile): $(teaish__auto.def) $(teaish.makefile.in) \
|
||||
@AUTODEPS@
|
||||
#========================================================================
|
||||
# Install binary object libraries. On Windows this includes both .dll and
|
||||
# .lib files. Because the .lib files are not explicitly listed anywhere,
|
||||
# we need to deduce their existence from the .dll file of the same name.
|
||||
# Library files go into the lib directory.
|
||||
# In addition, this will generate the pkgIndex.tcl
|
||||
# file in the install location (assuming it can find a usable tclsh shell)
|
||||
#
|
||||
# You should not have to modify this target.
|
||||
#========================================================================
|
||||
|
||||
@if TEAISH_TESTER_TCL_IN
|
||||
@TEAISH_TESTER_TCL_IN@: $(teaish__autogen.deps)
|
||||
config.log: @TEAISH_TESTER_TCL_IN@
|
||||
@TEAISH_TESTER_TCL@: @TEAISH_TESTER_TCL_IN@
|
||||
@endif
|
||||
@if TEAISH_TEST_TCL_IN
|
||||
@TEAISH_TEST_TCL_IN@: $(teaish__autogen.deps)
|
||||
config.log: @TEAISH_TEST_TCL_IN@
|
||||
@TEAISH_TEST_TCL@: @TEAISH_TEST_TCL_IN@
|
||||
@endif
|
||||
|
||||
#
|
||||
# CC variant for compiling Tcl-using sources.
|
||||
#
|
||||
CC.tcl = \
|
||||
$(CC) -o $@ $(CFLAGS.configure) $(CFLAGS) $(tx.CFLAGS) $(tx.CPPFLAGS)
|
||||
|
||||
#
|
||||
# CC variant for linking $(tx.src) into an extension DLL. Note that
|
||||
# $(tx.src) must come before $(LDFLAGS...) for linking to third-party
|
||||
# libs to work.
|
||||
#
|
||||
CC.dll = \
|
||||
$(CC.tcl) $(tx.src) $(LDFLAGS.shlib) \
|
||||
$(tx.LDFLAGS) $(LDFLAGS.configure) $(LDFLAGS) $(TCL_STUB_LIB_SPEC)
|
||||
|
||||
@if TEAISH_ENABLE_DLL
|
||||
#
|
||||
# The rest of this makefile exists solely to support this brief
|
||||
# target: the extension shared lib.
|
||||
#
|
||||
$(tx.dll): $(tx.src) config.log
|
||||
@if [ "x" = "x$(tx.src)" ]; then \
|
||||
echo "Makefile var tx.src (source/object files) is empty" 1>&2; \
|
||||
exit 1; \
|
||||
install-lib-binaries: binaries
|
||||
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(pkglibdir)"
|
||||
@list='$(lib_BINARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
$(INSTALL_LIBRARY) $$p "$(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
ext=`echo $$p|sed -e "s/.*\.//"`; \
|
||||
if test "x$$ext" = "xdll"; then \
|
||||
lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
|
||||
if test -f $$lib; then \
|
||||
echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
|
||||
$(INSTALL_DATA) $$lib "$(DESTDIR)$(pkglibdir)/$$lib"; \
|
||||
fi; \
|
||||
fi; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
|
||||
if test -f $(srcdir)/$$p; then \
|
||||
destp=`basename $$p`; \
|
||||
echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
|
||||
$(INSTALL_DATA) $(srcdir)/$$p "$(DESTDIR)$(pkglibdir)/$$destp"; \
|
||||
fi; \
|
||||
done
|
||||
@if test "x$(SHARED_BUILD)" = "x1"; then \
|
||||
echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
|
||||
$(INSTALL_DATA) pkgIndex.tcl "$(DESTDIR)$(pkglibdir)"; \
|
||||
fi
|
||||
$(CC.dll)
|
||||
|
||||
all: $(tx.dll)
|
||||
@endif # TEAISH_ENABLE_DLL
|
||||
#========================================================================
|
||||
# Install binary executables (e.g. .exe files and dependent .dll files)
|
||||
# This is for files that must go in the bin directory (located next to
|
||||
# wish and tclsh), like dependent .dll files on Windows.
|
||||
#
|
||||
# You should not have to modify this target, except to define bin_BINARIES
|
||||
# above if necessary.
|
||||
#========================================================================
|
||||
|
||||
tclsh: $(teaish.makefile) config.log
|
||||
@{ echo "#!/bin/sh"; echo 'exec $(TCLSH) "$$@"'; } > $@
|
||||
@chmod +x $@
|
||||
@echo "Created $@"
|
||||
install-bin-binaries: binaries
|
||||
@$(INSTALL_DATA_DIR) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_BINARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
|
||||
$(INSTALL_PROGRAM) $$p "$(DESTDIR)$(bindir)/$$p"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
#
|
||||
# Run the generated test script.
|
||||
#
|
||||
.PHONY: test-pre test-prepre test-core test test-post test-extension
|
||||
test-extension: # this name is reserved for use by teaish.make[.in]
|
||||
@if TEAISH_ENABLE_DLL
|
||||
test-prepre: $(tx.dll)
|
||||
@endif
|
||||
@if TEAISH_TESTER_TCL
|
||||
teaish.tester.tcl = @TEAISH_TESTER_TCL@
|
||||
test-core.args = $(teaish.tester.tcl)
|
||||
@if TEAISH_ENABLE_DLL
|
||||
test-core.args += '$(tx.dll)' '$(tx.loadPrefix)'
|
||||
@else
|
||||
test-core.args += '' ''
|
||||
@endif
|
||||
test-core.args += @TEAISH_TESTUTIL_TCL@
|
||||
# Clients may pass additional args via test.args=...
|
||||
# and ::argv will be rewritten before the test script loads, to
|
||||
# remove $(test-core.args)
|
||||
test.args ?=
|
||||
test-core: test-pre
|
||||
$(TCLSH) $(test-core.args) $(test.args)
|
||||
test-gdb: $(teaish.tester.tcl)
|
||||
gdb --args $(TCLSH) $(test-core.args) $(test.args)
|
||||
test-vg.flags ?= --leak-check=full -v --show-reachable=yes --track-origins=yes
|
||||
test-vg: $(teaish.tester.tcl)
|
||||
valgrind $(test-vg.flags) $(TCLSH) $(test-core.args) $(test.args)
|
||||
@else # !TEAISH_TESTER_TCL
|
||||
test-prepre:
|
||||
@endif # TEAISH_TESTER_TCL
|
||||
test-pre: test-prepre
|
||||
test-core: test-pre
|
||||
test-post: test-core
|
||||
test: test-post
|
||||
.SUFFIXES: .c .$(OBJEXT)
|
||||
|
||||
#
|
||||
# Cleanup rules...
|
||||
#
|
||||
#.PHONY: clean-pre clean-core clean-post clean-extension
|
||||
#
|
||||
clean-pre:
|
||||
clean-core: clean-pre
|
||||
rm -f $(tx.dll8) $(tx.dll9) tclsh
|
||||
clean-post: clean-core
|
||||
clean: clean-post
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
.PHONY: distclean-pre distclean-core distclean-post clean-extension
|
||||
distclean-pre: clean
|
||||
distclean-core: distclean-pre
|
||||
rm -f Makefile
|
||||
rm -f config.log config.defines.txt
|
||||
@if TEAISH_MAKEFILE_IN
|
||||
@if TEAISH_MAKEFILE
|
||||
rm -f @TEAISH_MAKEFILE@
|
||||
@endif
|
||||
@endif
|
||||
@if TEAISH_TESTER_TCL_IN
|
||||
rm -f $(teaish.tester.tcl)
|
||||
@endif
|
||||
@if TEAISH_PKGINDEX_TCL_IN
|
||||
rm -f @TEAISH_PKGINDEX_TCL@
|
||||
@endif
|
||||
@if TEAISH_PKGINIT_TCL_IN
|
||||
rm -f @TEAISH_PKGINIT_TCL@
|
||||
@endif
|
||||
@if TEAISH_TEST_TCL_IN
|
||||
rm -f @TEAISH_TEST_TCL@
|
||||
@endif
|
||||
distclean-post: distclean-core
|
||||
distclean: distclean-post
|
||||
#
|
||||
# The (dist)clean-extension targets are reserved for use by
|
||||
# client-side teaish.make.
|
||||
#
|
||||
# Client code which wants to clean up extra stuff should do so by
|
||||
# adding their cleanup target (e.g. clean-extension) as a dependency
|
||||
# to the 'clean' target, like so:
|
||||
#
|
||||
# clean: distclean-extension
|
||||
# distclean: distclean-extension
|
||||
#
|
||||
distclean-extension:
|
||||
clean-extension:
|
||||
uninstall-binaries:
|
||||
list='$(lib_BINARIES)'; for p in $$list; do \
|
||||
rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
done
|
||||
list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
|
||||
p=`basename $$p`; \
|
||||
rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \
|
||||
done
|
||||
list='$(bin_BINARIES)'; for p in $$list; do \
|
||||
rm -f "$(DESTDIR)$(bindir)/$$p"; \
|
||||
done
|
||||
|
||||
#
|
||||
# Installation rules...
|
||||
#
|
||||
@if TEAISH_ENABLE_INSTALL
|
||||
.PHONY: install-pre install-core install-post install-test install-prepre install-extension
|
||||
install-extension: # this name is reserved for use by teaish.make
|
||||
.PHONY: all binaries clean depend distclean doc install libraries test
|
||||
.PHONY: gdb gdb-test valgrind valgrindshell
|
||||
|
||||
@if TEAISH_ENABLE_DLL
|
||||
install-prepre: $(tx.dll)
|
||||
@else
|
||||
install-prepre:
|
||||
@endif
|
||||
|
||||
@if TEAISH_TM_TCL
|
||||
install-core.tmdir = $(DESTDIR)@TEAISH_TCL_TM_DIR@
|
||||
@endif
|
||||
|
||||
install-pre: install-prepre
|
||||
install-core: install-pre
|
||||
@if [ ! -d "$(DESTDIR)$(TCLLIBDIR)" ]; then \
|
||||
set -x; $(INSTALL) -d "$(DESTDIR)$(TCLLIBDIR)"; \
|
||||
fi
|
||||
# ^^^^ on some platforms, install -d fails if the target already exists.
|
||||
@if TEAISH_ENABLE_DLL
|
||||
$(INSTALL) $(tx.dll) "$(DESTDIR)$(TCLLIBDIR)"
|
||||
@endif
|
||||
@if TEAISH_PKGINDEX_TCL
|
||||
$(INSTALL.noexec) "@TEAISH_PKGINDEX_TCL@" "$(DESTDIR)$(TCLLIBDIR)"
|
||||
@endif
|
||||
@if TEAISH_PKGINIT_TCL
|
||||
$(INSTALL.noexec) "@TEAISH_PKGINIT_TCL@" "$(DESTDIR)$(TCLLIBDIR)"
|
||||
@endif
|
||||
@if TEAISH_TM_TCL
|
||||
@if [ ! -d "$(install-core.tmdir)" ]; then \
|
||||
set -x; $(INSTALL) -d "$(install-core.tmdir)"; \
|
||||
fi
|
||||
$(INSTALL.noexec) "@TEAISH_TM_TCL@" "$(install-core.tmdir)/$(tx.tm.tgt)"
|
||||
@endif
|
||||
install-test: install-core
|
||||
@echo "Post-install test of [package require $(tx.name.pkg) $(tx.version)]..."; \
|
||||
set xtra=""; \
|
||||
if [ x != "x$(DESTDIR)" ]; then \
|
||||
xtra='set ::auto_path [linsert $$::auto_path 0 [file normalize $(DESTDIR)$(TCLLIBDIR)/..]];'; \
|
||||
fi; \
|
||||
if echo \
|
||||
'set c 0; ' $$xtra \
|
||||
'@TEAISH_POSTINST_PREREQUIRE@' \
|
||||
'if {[catch {package require $(tx.name.pkg) $(tx.version)} xc]} {incr c};' \
|
||||
'if {$$c && "" ne $$xc} {puts $$xc; puts "auto_path=$$::auto_path"};' \
|
||||
'exit $$c' \
|
||||
| $(TCLSH) ; then \
|
||||
echo "passed"; \
|
||||
else \
|
||||
echo "FAILED"; \
|
||||
exit 1; \
|
||||
fi
|
||||
install-post: install-test
|
||||
install: install-post
|
||||
|
||||
#
|
||||
# Uninstall rules...
|
||||
#
|
||||
.PHONY: uninstall uninstall-pre uninstall-core uninstall-post uninstall-extension
|
||||
uninstall-extension: # this name is reserved for use by teaish.make
|
||||
uninstall-pre:
|
||||
uninstall-core: uninstall-pre
|
||||
@if TEAISH_ENABLE_DLL
|
||||
rm -fr "$(DESTDIR)$(TCLLIBDIR)"
|
||||
@endif
|
||||
@if TEAISH_TM_TCL
|
||||
rm -f "$(DESTDIR)$(install-core.tmdir)/$(tx.tm.tgt)"
|
||||
@endif
|
||||
|
||||
uninstall-post: uninstall-core
|
||||
@echo "Uninstalled Tcl extension $(tx.name) $(tx.version)"
|
||||
uninstall: uninstall-post
|
||||
@endif # TEAISH_ENABLE_INSTALL
|
||||
|
||||
@if TEAISH_MAKEFILE_IN
|
||||
Makefile: $(tx.makefile.in)
|
||||
config.log: $(teaish.makefile.in)
|
||||
@endif
|
||||
|
||||
#
|
||||
# Package archive generation ("dist") rules...
|
||||
#
|
||||
@if TEAISH_ENABLE_DIST
|
||||
@if BIN_TAR
|
||||
@if BIN_ZIP
|
||||
|
||||
# When installing teaish as part of "make dist", we need to run
|
||||
# configure with similar flags to what we last configured with but we
|
||||
# must not pass on any extension-specific flags, as those won't be
|
||||
# recognized when running in --teaish-install mode, causing
|
||||
# the sub-configure to fail.
|
||||
dist.flags = --with-tclsh=$(TCLSH)
|
||||
dist.reconfig = $(teaish.dir)/configure $(tx.dist.reconfig-flags) $(dist.flags)
|
||||
|
||||
# Temp dir for dist.zip. Must be different than dist.tgz or else
|
||||
# parallel builds may hose the dist.
|
||||
teaish__dist.tmp.zip = teaish__dist_zip
|
||||
#
|
||||
# Make a distribution zip file...
|
||||
#
|
||||
dist.zip = $(tx.dist.basename).zip
|
||||
.PHONY: dist.zip dist.zip-core dist.zip-post
|
||||
#dist.zip-pre:
|
||||
# We apparently can't add a pre-hook here, else "make dist" rebuilds
|
||||
# the archive each time it's run.
|
||||
$(dist.zip): $(tx.dist.files)
|
||||
@rm -fr $(teaish__dist.tmp.zip)
|
||||
@mkdir -p $(teaish__dist.tmp.zip)/$(tx.dist.basename)
|
||||
@tar cf $(teaish__dist.tmp.zip)/tmp.tar $(tx.dist.files)
|
||||
@tar xf $(teaish__dist.tmp.zip)/tmp.tar -C $(teaish__dist.tmp.zip)/$(tx.dist.basename)
|
||||
@if TEAISH_DIST_FULL
|
||||
@$(dist.reconfig) \
|
||||
--teaish-install=$(teaish__dist.tmp.zip)/$(tx.dist.basename) \
|
||||
--t-e-d=$(teaish__dist.tmp.zip)/$(tx.dist.basename) >/dev/null
|
||||
@endif
|
||||
@rm -f $(tx.dist.basename)/tmp.tar $(dist.zip)
|
||||
@cd $(teaish__dist.tmp.zip) && zip -q -r ../$(dist.zip) $(tx.dist.basename)
|
||||
@rm -fr $(teaish__dist.tmp.zip)
|
||||
@ls -la $(dist.zip)
|
||||
dist.zip-core: $(dist.zip)
|
||||
dist.zip-post: dist.zip-core
|
||||
dist.zip: dist.zip-post
|
||||
dist: dist.zip
|
||||
undist-zip:
|
||||
rm -f $(dist.zip)
|
||||
undist: undist-zip
|
||||
@endif #BIN_ZIP
|
||||
|
||||
#
|
||||
# Make a distribution tarball...
|
||||
#
|
||||
teaish__dist.tmp.tgz = teaish__dist_tgz
|
||||
dist.tgz = $(tx.dist.basename).tar.gz
|
||||
.PHONY: dist.tgz dist.tgz-core dist.tgz-post
|
||||
# dist.tgz-pre:
|
||||
# see notes in dist.zip
|
||||
$(dist.tgz): $(tx.dist.files)
|
||||
@rm -fr $(teaish__dist.tmp.tgz)
|
||||
@mkdir -p $(teaish__dist.tmp.tgz)/$(tx.dist.basename)
|
||||
@tar cf $(teaish__dist.tmp.tgz)/tmp.tar $(tx.dist.files)
|
||||
@tar xf $(teaish__dist.tmp.tgz)/tmp.tar -C $(teaish__dist.tmp.tgz)/$(tx.dist.basename)
|
||||
@if TEAISH_DIST_FULL
|
||||
@rm -f $(teaish__dist.tmp.tgz)/$(tx.dist.basename)/pkgIndex.tcl.in; # kludge
|
||||
@$(dist.reconfig) \
|
||||
--teaish-install=$(teaish__dist.tmp.tgz)/$(tx.dist.basename) \
|
||||
--t-e-d=$(teaish__dist.tmp.zip)/$(tx.dist.basename) >/dev/null
|
||||
@endif
|
||||
@rm -f $(tx.dist.basename)/tmp.tar $(dist.tgz)
|
||||
@cd $(teaish__dist.tmp.tgz) && tar czf ../$(dist.tgz) $(tx.dist.basename)
|
||||
@rm -fr $(teaish__dist.tmp.tgz)
|
||||
@ls -la $(dist.tgz)
|
||||
dist.tgz-core: $(dist.tgz)
|
||||
dist.tgz-post: dist.tgz-core
|
||||
dist.tgz: dist.tgz-post
|
||||
dist: dist.tgz
|
||||
undist-tgz:
|
||||
rm -f $(dist.tgz)
|
||||
undist: undist-tgz
|
||||
@else #!BIN_TAR
|
||||
dist:
|
||||
@echo "The dist rules require tar, which configure did not find." 1>&2; exit 1
|
||||
@endif #BIN_TAR
|
||||
@else #!TEAISH_ENABLE_DIST
|
||||
undist:
|
||||
dist:
|
||||
@if TEAISH_OUT_OF_EXT_TREE
|
||||
@echo "'dist' can only be used from an extension's home dir" 1>&2; \
|
||||
echo "In this case: @TEAISH_EXT_DIR@" 1>&2; exit 1
|
||||
@endif
|
||||
@endif #TEAISH_ENABLE_DIST
|
||||
|
||||
Makefile: @TEAISH_TCL@
|
||||
|
||||
@if TEAISH_MAKEFILE_CODE
|
||||
#
|
||||
# TEAISH_MAKEFILE_CODE may contain literal makefile code, which
|
||||
# gets pasted verbatim here. Either [define TEAISH_MAKEFILE_CODE
|
||||
# ...] or use [teaish-make-add] to incrementally build up this
|
||||
# content.
|
||||
#
|
||||
# <TEAISH_MAKEFILE_CODE>
|
||||
@TEAISH_MAKEFILE_CODE@
|
||||
# </TEAISH_MAKEFILE_CODE>
|
||||
@endif
|
||||
|
||||
@if TEAISH_MAKEFILE
|
||||
#
|
||||
# TEAISH_MAKEFILE[_IN] defines any extension-specific state this file
|
||||
# needs.
|
||||
#
|
||||
# It must set the following vars if they're not already accounted for
|
||||
# via teaish.tcl.
|
||||
#
|
||||
# - tx.src = list of the extension's source files, being sure to
|
||||
# prefix each with $(tx.dir) (if it's in the same dir as the
|
||||
# extension) so that out-of-tree builds can find them. Optionally,
|
||||
# [define] TEAISH_EXT_SRC or pass them to [teaish-src-add].
|
||||
#
|
||||
# It may optionally set the following vars:
|
||||
#
|
||||
# - tx.CFLAGS = CFLAGS/CPPFLAGS. Optionally, [define] TEAISH_CFLAGS
|
||||
# or pass them to [teaish-cflags-add].
|
||||
#
|
||||
# - tx.LDFLAGS = LDFLAGS. Optionally, [define] TEAISH_LDFLAGS or
|
||||
# pass them to [teaish-ldflags-add].
|
||||
#
|
||||
# It may optionally hook into various targets as documented in
|
||||
# /doc/extensions.md in the canonical teaish source tree.
|
||||
#
|
||||
# Interestingly, we don't have to pre-filter teaish.makefile.in - we
|
||||
# can just @include it here. That skips its teaish-specific validation
|
||||
# though. Hmm.
|
||||
#
|
||||
# <TEAISH_MAKEFILE>
|
||||
Makefile: @TEAISH_MAKEFILE@
|
||||
@include @TEAISH_MAKEFILE@
|
||||
# </TEAISH_MAKEFILE>
|
||||
@endif
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
|
||||
+36
-52
@@ -1,30 +1,9 @@
|
||||
This is the SQLite extension for Tcl using something akin to
|
||||
the Tcl Extension Architecture (TEA). To build it:
|
||||
This is the SQLite extension for Tcl using the Tcl Extension
|
||||
Architecture (TEA).
|
||||
|
||||
./configure ...flags...
|
||||
----------------------- A BETTER WAY ---------------------------
|
||||
|
||||
e.g.:
|
||||
|
||||
./configure --with-tcl=/path/to/tcl/install/root
|
||||
|
||||
or:
|
||||
|
||||
./configure --with-tclsh=/path/to/tcl/install/root
|
||||
|
||||
Run ./configure --help for the full list of flags.
|
||||
|
||||
The configuration process will fail if tclConfig.sh cannot be found.
|
||||
|
||||
The makefile will only honor CFLAGS and CPPFLAGS passed to the
|
||||
configure script, not those directly passed to the makefile.
|
||||
|
||||
Then:
|
||||
|
||||
make test install
|
||||
|
||||
----------------------- THE PREFERRED WAY ---------------------------
|
||||
|
||||
The preferred way to build the TCL extension for SQLite is to use the
|
||||
A better way to build the TCL extension for SQLite is to use the
|
||||
canonical source code tarball. For Unix:
|
||||
|
||||
./configure --with-tclsh=$(TCLSH)
|
||||
@@ -41,32 +20,24 @@ step-by-step instructions at the links below for more information:
|
||||
https://sqlite.org/src/doc/trunk/doc/compile-for-unix.md
|
||||
https://sqlite.org/src/doc/trunk/doc/compile-for-windows.md
|
||||
|
||||
And info about the extension's Tcl interface can be found at:
|
||||
|
||||
https://sqlite.org/tclsqlite.html
|
||||
|
||||
The whole point of the amalgamation-autoconf tarball (in which this
|
||||
README.txt file is embedded) is to provide a means of compiling SQLite
|
||||
that does not require first installing TCL and/or "tclsh". The
|
||||
canonical Makefile in the SQLite source tree provides more
|
||||
capabilities (such as the the ability to run test cases to ensure that
|
||||
the build worked) and is better maintained. The only downside of the
|
||||
canonical Makefile is that it requires a TCL installation. But if you
|
||||
are wanting to build the TCL extension for SQLite, then presumably you
|
||||
already have a TCL installation. So why not just use the more-capable
|
||||
and better-maintained canoncal Makefile?
|
||||
README.txt file is embedded) is to provide a means of compiling
|
||||
SQLite that does not require first installing TCL and/or "tclsh".
|
||||
The canonical Makefile in the SQLite source tree provides more
|
||||
capabilities (such as the the ability to run test cases to ensure
|
||||
that the build worked) and is better maintained. The only
|
||||
downside of the canonical Makfile is that it requires a TCL
|
||||
installation. But if you are wanting to build the TCL extension for
|
||||
SQLite, then presumably you already have a TCL installation. So why
|
||||
not just use the more-capable and better-maintained canoncal Makefile?
|
||||
|
||||
As of version 3.50.0, this build process uses "teaish":
|
||||
|
||||
https://fossil.wanderinghorse.net/r/teaish
|
||||
|
||||
which is conceptually derived from the pre-3.50 toolchain, TEA:
|
||||
This TEA builder is derived from code found at
|
||||
|
||||
http://core.tcl-lang.org/tclconfig
|
||||
http://core.tcl-lang.org/sampleextension
|
||||
|
||||
It to works for us. It might also work for you. But we cannot
|
||||
promise that.
|
||||
The SQLite developers do not understand how it works. It seems to
|
||||
work for us. It might also work for you. But we cannot promise that.
|
||||
|
||||
If you want to use this TEA builder and it works for you, that's fine.
|
||||
But if you have trouble, the first thing you should do is go back
|
||||
@@ -78,17 +49,30 @@ to using the canonical Makefile in the SQLite source tree.
|
||||
UNIX BUILD
|
||||
==========
|
||||
|
||||
Building under most UNIX systems is easy, just run the configure
|
||||
script and then run make. For example:
|
||||
Building under most UNIX systems is easy, just run the configure script
|
||||
and then run make. For more information about the build process, see
|
||||
the tcl/unix/README file in the Tcl src dist. The following minimal
|
||||
example will install the extension in the /opt/tcl directory.
|
||||
|
||||
$ cd sqlite-*-tea
|
||||
$ ./configure --with-tcl=/path/to/tcl/install/root
|
||||
$ make test
|
||||
$ ./configure --prefix=/opt/tcl
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
WINDOWS BUILD
|
||||
=============
|
||||
|
||||
On Windows this build is known to work on Cygwin and some Msys2
|
||||
environments. We do not currently support Microsoft makefiles for
|
||||
native Windows builds.
|
||||
The recommended method to build extensions under windows is to use the
|
||||
Msys + Mingw build process. This provides a Unix-style build while
|
||||
generating native Windows binaries. Using the Msys + Mingw build tools
|
||||
means that you can use the same configure script as per the Unix build
|
||||
to create a Makefile. See the tcl/win/README file for the URL of
|
||||
the Msys + Mingw download.
|
||||
|
||||
If you have VC++ then you may wish to use the files in the win
|
||||
subdirectory and build the extension using just VC++. These files have
|
||||
been designed to be as generic as possible but will require some
|
||||
additional maintenance by the project developer to synchronise with
|
||||
the TEA configure.in and Makefile.in files. Instructions for using the
|
||||
VC++ makefile are written in the first part of the Makefile.vc
|
||||
file.
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
# -*- tcl -*-
|
||||
#
|
||||
# Unless this file is named _teaish.tester.tcl.in, you are probably
|
||||
# looking at an automatically generated/filtered copy and should
|
||||
# probably not edit it.
|
||||
#
|
||||
# This is the wrapper script invoked by teaish's "make test" recipe.
|
||||
# It gets passed 3 args:
|
||||
#
|
||||
# $1 = the DLL name, or "" if the extension has no DLL
|
||||
#
|
||||
# $2 = the "load prefix" for Tcl's [load] or empty if $1 is empty
|
||||
#
|
||||
# $3 = the /path/to/teaish/tester.tcl (test utility code)
|
||||
#
|
||||
@if TEAISH_VSATISFIES_CODE
|
||||
@TEAISH_VSATISFIES_CODE@
|
||||
@endif
|
||||
if {[llength [lindex $::argv 0]] > 0} {
|
||||
load [file normalize [lindex $::argv 0]] [lindex $::argv 1];
|
||||
# ----^^^^^^^ needed on Haiku when argv 0 is just a filename, else
|
||||
# load cannot find the file.
|
||||
}
|
||||
set ::argv [lassign $argv - -]
|
||||
source -encoding utf-8 [lindex $::argv 0]; # teaish/tester.tcl
|
||||
@if TEAISH_PKGINIT_TCL
|
||||
apply {{file} {
|
||||
set dir [file dirname $::argv0]
|
||||
source -encoding utf-8 $file
|
||||
}} [join {@TEAISH_PKGINIT_TCL@}]
|
||||
@endif
|
||||
@if TEAISH_TM_TCL
|
||||
apply {{file} {
|
||||
set dir [file dirname $::argv0]
|
||||
source -encoding utf-8 $file
|
||||
}} [join {@TEAISH_TM_TCL@}]
|
||||
@endif
|
||||
@if TEAISH_TEST_TCL
|
||||
apply {{file} {
|
||||
# Populate state for [tester.tcl::teaish-build-flag*]
|
||||
array set ::teaish__BuildFlags @TEAISH__DEFINES_MAP@
|
||||
set dir [file normalize [file dirname $file]]
|
||||
#test-fail "Just testing"
|
||||
source -encoding utf-8 $file
|
||||
}} [join {@TEAISH_TEST_TCL@}]
|
||||
@else # TEAISH_TEST_TCL
|
||||
# No $TEAISH_TEST_TCL provided, so here's a default test which simply
|
||||
# loads the extension.
|
||||
puts {Extension @TEAISH_NAME@ @TEAISH_VERSION@ successfully loaded from @TEAISH_TESTER_TCL@}
|
||||
@endif
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# Include the TEA standard macro set
|
||||
#
|
||||
|
||||
builtin(include,tclconfig/tcl.m4)
|
||||
|
||||
#
|
||||
# Add here whatever m4 macros you want to define for your package
|
||||
#
|
||||
@@ -1,8 +0,0 @@
|
||||
#/do/not/tclsh
|
||||
# ^^^ help out editors which guess this file's content type.
|
||||
#
|
||||
# Main configure script entry point for the TEA(ish) framework. All
|
||||
# extension-specific customization goes in teaish.tcl.in or
|
||||
# teaish.tcl.
|
||||
use teaish/core
|
||||
teaish-configure-core
|
||||
Vendored
-20
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Look for and run autosetup...
|
||||
dir0="`dirname "$0"`"
|
||||
dirA="$dir0"
|
||||
if [ -d $dirA/autosetup ]; then
|
||||
# A local copy of autosetup
|
||||
dirA=$dirA/autosetup
|
||||
elif [ -d $dirA/../autosetup ]; then
|
||||
# SQLite "autoconf" bundle
|
||||
dirA=$dirA/../autosetup
|
||||
elif [ -d $dirA/../../autosetup ]; then
|
||||
# SQLite canonical source tree
|
||||
dirA=$dirA/../../autosetup
|
||||
else
|
||||
echo "$0: Cannot find autosetup" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
WRAPPER="$0"; export WRAPPER; exec "`"$dirA/autosetup-find-tclsh"`" \
|
||||
"$dirA/autosetup" --teaish-extension-dir="$dir0" \
|
||||
"$@"
|
||||
@@ -0,0 +1,227 @@
|
||||
#!/bin/bash -norc
|
||||
dnl This file is an input file used by the GNU "autoconf" program to
|
||||
dnl generate the file "configure", which is run during Tcl installation
|
||||
dnl to configure the system for the local environment.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Sample configure.ac for Tcl Extensions. The only places you should
|
||||
# need to modify this file are marked by the string __CHANGE__
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# __CHANGE__
|
||||
# Set your package name and version numbers here.
|
||||
#
|
||||
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
|
||||
# set as provided. These will also be added as -D defs in your Makefile
|
||||
# so you can encode the package version directly into the source files.
|
||||
# This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME>
|
||||
# so that we create the export library with the dll.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
AC_INIT([sqlite],[@VERSION@])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
||||
# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
|
||||
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_INIT()
|
||||
|
||||
AC_CONFIG_AUX_DIR(tclconfig)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Load the tclConfig.sh file
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_PATH_TCLCONFIG
|
||||
TEA_LOAD_TCLCONFIG
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Load the tkConfig.sh file if necessary (Tk extension)
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
#TEA_PATH_TKCONFIG
|
||||
#TEA_LOAD_TKCONFIG
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Handle the --prefix=... option by defaulting to what Tcl gave.
|
||||
# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
TEA_PREFIX
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Standard compiler checks.
|
||||
# This sets up CC by using the CC env var, or looks for gcc otherwise.
|
||||
# This also calls AC_PROG_CC and a few others to create the basic setup
|
||||
# necessary to compile executables.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
TEA_SETUP_COMPILER
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# __CHANGE__
|
||||
# Specify the C source files to compile in TEA_ADD_SOURCES,
|
||||
# public headers that need to be installed in TEA_ADD_HEADERS,
|
||||
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
|
||||
# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
|
||||
# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
|
||||
# and PKG_TCL_SOURCES.
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
TEA_ADD_SOURCES([tclsqlite3.c])
|
||||
TEA_ADD_HEADERS([])
|
||||
TEA_ADD_INCLUDES([])
|
||||
TEA_ADD_LIBS([])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS3=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS4=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_FTS5=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_3_SUFFIX_ONLY=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_RTREE=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_GEOPOLY=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_MATH_FUNCTIONS=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DESERIALIZE=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DBPAGE_VTAB=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_BYTECODE_VTAB=1])
|
||||
TEA_ADD_CFLAGS([-DSQLITE_ENABLE_DBSTAT_VTAB=1])
|
||||
TEA_ADD_STUB_SOURCES([])
|
||||
TEA_ADD_TCL_SOURCES([])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# The --with-system-sqlite causes the TCL bindings to SQLite to use
|
||||
# the system shared library for SQLite rather than statically linking
|
||||
# against its own private copy. This is dangerous and leads to
|
||||
# undersirable dependences and is not recommended.
|
||||
# Patchs from rmax.
|
||||
#--------------------------------------------------------------------
|
||||
AC_ARG_WITH([system-sqlite],
|
||||
[AS_HELP_STRING([--with-system-sqlite],
|
||||
[use a system-supplied libsqlite3 instead of the bundled one])],
|
||||
[], [with_system_sqlite=no])
|
||||
if test x$with_system_sqlite != xno; then
|
||||
AC_CHECK_HEADER([sqlite3.h],
|
||||
[AC_CHECK_LIB([sqlite3],[sqlite3_initialize],
|
||||
[AC_DEFINE(USE_SYSTEM_SQLITE)
|
||||
LIBS="$LIBS -lsqlite3"])])
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# __CHANGE__
|
||||
#
|
||||
# You can add more files to clean if your extension creates any extra
|
||||
# files by extending CLEANFILES.
|
||||
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
|
||||
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
|
||||
#
|
||||
# A few miscellaneous platform-specific items:
|
||||
# TEA_ADD_* any platform specific compiler/build info here.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
#CLEANFILES="$CLEANFILES pkgIndex.tcl"
|
||||
if test "${TEA_PLATFORM}" = "windows" ; then
|
||||
# Ensure no empty if clauses
|
||||
:
|
||||
#TEA_ADD_SOURCES([win/winFile.c])
|
||||
#TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
|
||||
else
|
||||
# Ensure no empty else clauses
|
||||
:
|
||||
#TEA_ADD_SOURCES([unix/unixFile.c])
|
||||
#TEA_ADD_LIBS([-lsuperfly])
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# __CHANGE__
|
||||
# Choose which headers you need. Extension authors should try very
|
||||
# hard to only rely on the Tcl public header files. Internal headers
|
||||
# contain private data structures and are subject to change without
|
||||
# notice.
|
||||
# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_PUBLIC_TCL_HEADERS
|
||||
#TEA_PRIVATE_TCL_HEADERS
|
||||
|
||||
#TEA_PUBLIC_TK_HEADERS
|
||||
#TEA_PRIVATE_TK_HEADERS
|
||||
#TEA_PATH_X
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Check whether --enable-threads or --disable-threads was given.
|
||||
# This auto-enables if Tcl was compiled threaded.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_ENABLE_THREADS
|
||||
if test "${TCL_THREADS}" = "1" ; then
|
||||
AC_DEFINE(SQLITE_THREADSAFE, 1, [Trigger sqlite threadsafe build])
|
||||
# Not automatically added by Tcl because its assumed Tcl links to them,
|
||||
# but it may not if it isn't really a threaded build.
|
||||
TEA_ADD_LIBS([$THREADS_LIBS])
|
||||
else
|
||||
AC_DEFINE(SQLITE_THREADSAFE, 0, [Trigger sqlite non-threadsafe build])
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# The statement below defines a collection of symbols related to
|
||||
# building as a shared library instead of a static library.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_ENABLE_SHARED
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# This macro figures out what flags to use with the compiler/linker
|
||||
# when building shared/static debug/optimized objects. This information
|
||||
# can be taken from the tclConfig.sh file, but this figures it all out.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_CONFIG_CFLAGS
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Set the default compiler switches based on the --enable-symbols option.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_ENABLE_SYMBOLS
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# This macro generates a line to use when building a library. It
|
||||
# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
|
||||
# and TEA_LOAD_TCLCONFIG macros above.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_MAKE_LIB
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Determine the name of the tclsh and/or wish executables in the
|
||||
# Tcl and Tk build directories or the location they were installed
|
||||
# into. These paths are used to support running test cases only,
|
||||
# the Makefile should not be making use of these paths to generate
|
||||
# a pkgIndex.tcl file or anything else at extension build time.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
TEA_PROG_TCLSH
|
||||
#TEA_PROG_WISH
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Setup a *Config.sh.in configuration file.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
#TEA_EXPORT_CONFIG([sample])
|
||||
#AC_SUBST(SAMPLE_VAR)
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Specify files to substitute AC variables in. You may alternatively
|
||||
# have a special pkgIndex.tcl.in or other files which require
|
||||
# substituting the AC variables in. Include these here.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
AC_CONFIG_FILES([Makefile pkgIndex.tcl])
|
||||
#AC_CONFIG_FILES([sampleConfig.sh])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Finally, substitute all of the various values into the files
|
||||
# specified with AC_CONFIG_FILES.
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
AC_OUTPUT
|
||||
@@ -0,0 +1,15 @@
|
||||
.TH sqlite3 n 4.1 "Tcl-Extensions"
|
||||
.HS sqlite3 tcl
|
||||
.BS
|
||||
.SH NAME
|
||||
sqlite3 \- an interface to the SQLite3 database engine
|
||||
.SH SYNOPSIS
|
||||
\fBsqlite3\fI command_name ?filename?\fR
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
SQLite3 is a self-contains, zero-configuration, transactional SQL database
|
||||
engine. This extension provides an easy to use interface for accessing
|
||||
SQLite database files from Tcl.
|
||||
.PP
|
||||
For full documentation see \fIhttp://www.sqlite.org/\fR and
|
||||
in particular \fIhttp://www.sqlite.org/tclsqlite.html\fR.
|
||||
@@ -1,40 +1,10 @@
|
||||
# -*- tcl -*-
|
||||
# Tcl package index file
|
||||
# Tcl package index file, version 1.1
|
||||
#
|
||||
# Unless this file is named pkgIndex.tcl.in, you are probably looking
|
||||
# at an automatically generated/filtered copy and should probably not
|
||||
# edit it.
|
||||
#
|
||||
# Adapted from https://core.tcl-lang.org/tcltls
|
||||
@if TEAISH_VSATISFIES_CODE
|
||||
@TEAISH_VSATISFIES_CODE@
|
||||
@endif
|
||||
if {[package vsatisfies [package provide Tcl] 9.0-]} {
|
||||
package ifneeded {@TEAISH_PKGNAME@} {@TEAISH_VERSION@} [list apply {{dir} {
|
||||
@if TEAISH_ENABLE_DLL
|
||||
load [file join $dir {@TEAISH_DLL9@}] @TEAISH_LOAD_PREFIX@
|
||||
@endif
|
||||
@if TEAISH_PKGINIT_TCL_TAIL
|
||||
set initScript [file join $dir {@TEAISH_PKGINIT_TCL_TAIL@}]
|
||||
if {[file exists $initScript]} {
|
||||
source -encoding utf-8 $initScript
|
||||
}
|
||||
@endif
|
||||
}} $dir]
|
||||
package ifneeded sqlite3 @PACKAGE_VERSION@ \
|
||||
[list load [file join $dir @PKG_LIB_FILE9@] Sqlite3]
|
||||
} else {
|
||||
package ifneeded {@TEAISH_PKGNAME@} {@TEAISH_VERSION@} [list apply {{dir} {
|
||||
@if TEAISH_ENABLE_DLL
|
||||
if {[string tolower [file extension {@TEAISH_DLL8@}]] in [list .dll .dylib .so]} {
|
||||
load [file join $dir {@TEAISH_DLL8@}] @TEAISH_LOAD_PREFIX@
|
||||
} else {
|
||||
load {} @TEAISH_LOAD_PREFIX@
|
||||
}
|
||||
@endif
|
||||
@if TEAISH_PKGINIT_TCL_TAIL
|
||||
set initScript [file join $dir {@TEAISH_PKGINIT_TCL_TAIL@}]
|
||||
if {[file exists $initScript]} {
|
||||
source -encoding utf-8 $initScript
|
||||
}
|
||||
@endif
|
||||
}} $dir]
|
||||
package ifneeded sqlite3 @PACKAGE_VERSION@ \
|
||||
[list load [file join $dir @PKG_LIB_FILE8@] Sqlite3]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2020-11-14.01; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# 'make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
tab=' '
|
||||
nl='
|
||||
'
|
||||
IFS=" $tab$nl"
|
||||
|
||||
# Set DOITPROG to "echo" to test this script.
|
||||
|
||||
doit=${DOITPROG-}
|
||||
doit_exec=${doit:-exec}
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
# Create dirs (including intermediate dirs) using mode 755.
|
||||
# This is like GNU 'install' as of coreutils 8.32 (2020).
|
||||
mkdir_umask=22
|
||||
|
||||
backupsuffix=
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
is_target_a_directory=possibly
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-p pass -p to $cpprog.
|
||||
-s $stripprog installed files.
|
||||
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
|
||||
By default, rm is invoked with -f; when overridden with RMPROG,
|
||||
it's up to you to specify -f if you want it.
|
||||
|
||||
If -S is not specified, no backups are attempted.
|
||||
|
||||
Email bug reports to bug-automake@gnu.org.
|
||||
Automake home page: https://www.gnu.org/software/automake/
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-p) cpprog="$cpprog -p";;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-S) backupsuffix="$2"
|
||||
shift;;
|
||||
|
||||
-t)
|
||||
is_target_a_directory=always
|
||||
dst_arg=$2
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) is_target_a_directory=never;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# We allow the use of options -d and -T together, by making -d
|
||||
# take the precedence; this is for compatibility with GNU install.
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
if test -n "$dst_arg"; then
|
||||
echo "$0: target directory not allowed when installing a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call 'install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||
if test ! -d "$dst_arg"; then
|
||||
echo "$0: $dst_arg: Is not a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
# Don't chown directories that already exist.
|
||||
if test $dstdir_status = 0; then
|
||||
chowncmd=""
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename.
|
||||
if test -d "$dst"; then
|
||||
if test "$is_target_a_directory" = never; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dstbase=`basename "$src"`
|
||||
case $dst in
|
||||
*/) dst=$dst$dstbase;;
|
||||
*) dst=$dst/$dstbase;;
|
||||
esac
|
||||
dstdir_status=0
|
||||
else
|
||||
dstdir=`dirname "$dst"`
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
case $dstdir in
|
||||
*/) dstdirslash=$dstdir;;
|
||||
*) dstdirslash=$dstdir/;;
|
||||
esac
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
# The $RANDOM variable is not portable (e.g., dash). Use it
|
||||
# here however when possible just to lower collision chance.
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
|
||||
trap '
|
||||
ret=$?
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
|
||||
exit $ret
|
||||
' 0
|
||||
|
||||
# Because "mkdir -p" follows existing symlinks and we likely work
|
||||
# directly in world-writeable /tmp, make sure that the '$tmpdir'
|
||||
# directory is successfully created first before we actually test
|
||||
# 'mkdir -p'.
|
||||
if (umask $mkdir_umask &&
|
||||
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
test_tmpdir="$tmpdir/a"
|
||||
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=${dstdirslash}_inst.$$_
|
||||
rmtmp=${dstdirslash}_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask &&
|
||||
{ test -z "$stripcmd" || {
|
||||
# Create $dsttmp read-write so that cp doesn't create it read-only,
|
||||
# which would cause strip to fail.
|
||||
if test -z "$doit"; then
|
||||
: >"$dsttmp" # No need to fork-exec 'touch'.
|
||||
else
|
||||
$doit touch "$dsttmp"
|
||||
fi
|
||||
}
|
||||
} &&
|
||||
$doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
set +f &&
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# If $backupsuffix is set, and the file being installed
|
||||
# already exists, attempt a backup. Don't worry if it fails,
|
||||
# e.g., if mv doesn't support -f.
|
||||
if test -n "$backupsuffix" && test -f "$dst"; then
|
||||
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
|
||||
fi
|
||||
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,569 +0,0 @@
|
||||
# Teaish configure script for the SQLite Tcl extension
|
||||
|
||||
#
|
||||
# State for disparate config-time pieces.
|
||||
#
|
||||
array set sqlite__Config [proj-strip-hash-comments {
|
||||
#
|
||||
# The list of feature --flags which the --all flag implies. This
|
||||
# requires special handling in a few places.
|
||||
#
|
||||
all-flag-enables {fts3 fts4 fts5 rtree geopoly}
|
||||
|
||||
# >0 if building in the canonical tree. -1=undetermined
|
||||
is-canonical -1
|
||||
}]
|
||||
|
||||
#
|
||||
# Set up the package info for teaish...
|
||||
#
|
||||
apply {{dir} {
|
||||
# Figure out the version number...
|
||||
set version ""
|
||||
if {[file exists $dir/../VERSION]} {
|
||||
# The canonical SQLite TEA(ish) build
|
||||
set version [proj-file-content -trim $dir/../VERSION]
|
||||
set ::sqlite__Config(is-canonical) 1
|
||||
set distname sqlite-tcl
|
||||
} elseif {[file exists $dir/generic/tclsqlite3.c]} {
|
||||
# The copy from the teaish tree, used as a dev/test bed before
|
||||
# updating SQLite's tree.
|
||||
set ::sqlite__Config(is-canonical) 0
|
||||
set fd [open $dir/generic/tclsqlite3.c rb]
|
||||
while {[gets $fd line] >=0} {
|
||||
if {[regexp {^#define[ ]+SQLITE_VERSION[ ]+"(3.+)"} \
|
||||
$line - version]} {
|
||||
set distname sqlite-teaish
|
||||
break
|
||||
}
|
||||
}
|
||||
close $fd
|
||||
}
|
||||
|
||||
if {"" eq $version} {
|
||||
proj-fatal "Cannot determine the SQLite version number"
|
||||
}
|
||||
|
||||
proj-assert {$::sqlite__Config(is-canonical) > -1}
|
||||
proj-assert {[string match 3.*.* $version]} \
|
||||
"Unexpected SQLite version: $version"
|
||||
|
||||
set pragmas {}
|
||||
if {$::sqlite__Config(is-canonical)} {
|
||||
# Disable "make dist" in the canonical tree. That tree is
|
||||
# generated from several pieces and creating/testing working
|
||||
# "dist" rules for that sub-build currently feels unnecessary. The
|
||||
# copy in the teaish tree, though, should be able to "make dist".
|
||||
lappend pragmas no-dist
|
||||
} else {
|
||||
lappend pragmas full-dist
|
||||
}
|
||||
|
||||
teaish-pkginfo-set -vars {
|
||||
-name sqlite
|
||||
-name.pkg sqlite3
|
||||
-version $version
|
||||
-name.dist $distname
|
||||
-libDir sqlite$version
|
||||
-pragmas $pragmas
|
||||
-src generic/tclsqlite3.c
|
||||
}
|
||||
# We should also have:
|
||||
# -vsatisfies 8.6-
|
||||
# But at least one platform is failing this vsatisfies check
|
||||
# for no apparent reason:
|
||||
# https://sqlite.org/forum/forumpost/fde857fb8101a4be
|
||||
}} [teaish-get -dir]
|
||||
|
||||
|
||||
#
|
||||
# Must return either an empty string or a list in the form accepted by
|
||||
# autosetup's [options] function.
|
||||
#
|
||||
proc teaish-options {} {
|
||||
# These flags and defaults mostly derive from the historical TEA
|
||||
# build. Some, like ICU, are taken from the canonical SQLite tree.
|
||||
return [subst -nocommands -nobackslashes {
|
||||
with-system-sqlite=0
|
||||
=> {Use the system-level SQLite instead of the copy in this tree.
|
||||
Also requires use of --override-sqlite-version so that the build
|
||||
knows what version number to associate with the system-level SQLite.}
|
||||
override-sqlite-version:VERSION
|
||||
=> {For use with --with-system-sqlite to set the version number.}
|
||||
threadsafe=1 => {Disable mutexing}
|
||||
with-tempstore:=no => {Use an in-RAM database for temporary tables: never,no,yes,always}
|
||||
load-extension=0 => {Enable loading of external extensions}
|
||||
math=1 => {Disable math functions}
|
||||
json=1 => {Disable JSON functions}
|
||||
fts3 => {Enable the FTS3 extension}
|
||||
fts4 => {Enable the FTS4 extension}
|
||||
fts5 => {Enable the FTS5 extension}
|
||||
update-limit => {Enable the UPDATE/DELETE LIMIT clause}
|
||||
geopoly => {Enable the GEOPOLY extension}
|
||||
rtree => {Enable the RTREE extension}
|
||||
session => {Enable the SESSION extension}
|
||||
all=1 => {Disable $::sqlite__Config(all-flag-enables)}
|
||||
with-icu-ldflags:LDFLAGS
|
||||
=> {Enable SQLITE_ENABLE_ICU and add the given linker flags for the
|
||||
ICU libraries. e.g. on Ubuntu systems, try '-licui18n -licuuc -licudata'.}
|
||||
with-icu-cflags:CFLAGS
|
||||
=> {Apply extra CFLAGS/CPPFLAGS necessary for building with ICU.
|
||||
e.g. -I/usr/local/include}
|
||||
with-icu-config:=auto
|
||||
=> {Enable SQLITE_ENABLE_ICU. Value must be one of: auto, pkg-config,
|
||||
/path/to/icu-config}
|
||||
icu-collations=0
|
||||
=> {Enable SQLITE_ENABLE_ICU_COLLATIONS. Requires --with-icu-ldflags=...
|
||||
or --with-icu-config}
|
||||
}]
|
||||
}
|
||||
|
||||
#
|
||||
# Gets called by tea-configure-core. Must perform any configuration
|
||||
# work needed for this extension.
|
||||
#
|
||||
proc teaish-configure {} {
|
||||
use teaish/feature
|
||||
|
||||
if {[proj-opt-was-provided override-sqlite-version]} {
|
||||
teaish-pkginfo-set -version [opt-val override-sqlite-version]
|
||||
proj-warn "overriding sqlite version number:" [teaish-pkginfo-get -version]
|
||||
} elseif {[proj-opt-was-provided with-system-sqlite]
|
||||
&& [opt-val with-system-sqlite] ne "0"} {
|
||||
proj-fatal "when using --with-system-sqlite also use" \
|
||||
"--override-sqlite-version to specify a library version number."
|
||||
}
|
||||
|
||||
define CFLAGS [proj-get-env CFLAGS {-O2}]
|
||||
sqlite-munge-cflags
|
||||
|
||||
#
|
||||
# Add feature flags from legacy configure.ac which are not covered by
|
||||
# --flags.
|
||||
#
|
||||
sqlite-add-feature-flag {
|
||||
-DSQLITE_3_SUFFIX_ONLY=1
|
||||
-DSQLITE_ENABLE_DESERIALIZE=1
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB=1
|
||||
-DSQLITE_ENABLE_BYTECODE_VTAB=1
|
||||
-DSQLITE_ENABLE_DBSTAT_VTAB=1
|
||||
}
|
||||
|
||||
if {[opt-bool with-system-sqlite]} {
|
||||
msg-result "Using system-level sqlite3."
|
||||
teaish-cflags-add -DUSE_SYSTEM_SQLITE
|
||||
teaish-ldflags-add -lsqlite3
|
||||
} elseif {$::sqlite__Config(is-canonical)} {
|
||||
teaish-cflags-add -I[teaish-get -dir]/..
|
||||
}
|
||||
|
||||
teaish-check-librt
|
||||
teaish-check-libz
|
||||
sqlite-handle-threadsafe
|
||||
sqlite-handle-tempstore
|
||||
sqlite-handle-load-extension
|
||||
sqlite-handle-math
|
||||
sqlite-handle-icu
|
||||
|
||||
sqlite-handle-common-feature-flags; # must be late in the process
|
||||
}; # teaish-configure
|
||||
|
||||
define OPT_FEATURE_FLAGS {} ; # -DSQLITE_OMIT/ENABLE flags.
|
||||
#
|
||||
# Adds $args, if not empty, to OPT_FEATURE_FLAGS. This is intended only for holding
|
||||
# -DSQLITE_ENABLE/OMIT/... flags, but that is not enforced here.
|
||||
proc sqlite-add-feature-flag {args} {
|
||||
if {"" ne $args} {
|
||||
define-append OPT_FEATURE_FLAGS {*}$args
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Check for log(3) in libm and die with an error if it is not
|
||||
# found. $featureName should be the feature name which requires that
|
||||
# function (it's used only in error messages). defines LDFLAGS_MATH to
|
||||
# the required linker flags (which may be empty even if the math APIs
|
||||
# are found, depending on the OS).
|
||||
proc sqlite-affirm-have-math {featureName} {
|
||||
if {"" eq [get-define LDFLAGS_MATH ""]} {
|
||||
if {![msg-quiet proj-check-function-in-lib log m]} {
|
||||
user-error "Missing math APIs for $featureName"
|
||||
}
|
||||
set lfl [get-define lib_log ""]
|
||||
undefine lib_log
|
||||
if {"" ne $lfl} {
|
||||
user-notice "Forcing requirement of $lfl for $featureName"
|
||||
}
|
||||
define LDFLAGS_MATH $lfl
|
||||
teaish-ldflags-prepend $lfl
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Handle various SQLITE_ENABLE/OMIT_... feature flags.
|
||||
proc sqlite-handle-common-feature-flags {} {
|
||||
msg-result "Feature flags..."
|
||||
if {![opt-bool all]} {
|
||||
# Special handling for --disable-all
|
||||
foreach flag $::sqlite__Config(all-flag-enables) {
|
||||
if {![proj-opt-was-provided $flag]} {
|
||||
proj-opt-set $flag 0
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach {boolFlag featureFlag ifSetEvalThis} [proj-strip-hash-comments {
|
||||
all {} {
|
||||
# The 'all' option must be first in this list. This impl makes
|
||||
# an effort to only apply flags which the user did not already
|
||||
# apply, so that combinations like (--all --disable-geopoly)
|
||||
# will indeed disable geopoly. There are corner cases where
|
||||
# flags which depend on each other will behave in non-intuitive
|
||||
# ways:
|
||||
#
|
||||
# --all --disable-rtree
|
||||
#
|
||||
# Will NOT disable geopoly, though geopoly depends on rtree.
|
||||
# The --geopoly flag, though, will automatically re-enable
|
||||
# --rtree, so --disable-rtree won't actually disable anything in
|
||||
# that case.
|
||||
foreach k $::sqlite__Config(all-flag-enables) {
|
||||
if {![proj-opt-was-provided $k]} {
|
||||
proj-opt-set $k 1
|
||||
}
|
||||
}
|
||||
}
|
||||
fts3 -DSQLITE_ENABLE_FTS3 {sqlite-affirm-have-math fts3}
|
||||
fts4 -DSQLITE_ENABLE_FTS4 {sqlite-affirm-have-math fts4}
|
||||
fts5 -DSQLITE_ENABLE_FTS5 {sqlite-affirm-have-math fts5}
|
||||
geopoly -DSQLITE_ENABLE_GEOPOLY {proj-opt-set rtree}
|
||||
rtree -DSQLITE_ENABLE_RTREE {}
|
||||
session {-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK} {}
|
||||
update-limit -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT {}
|
||||
scanstatus -DSQLITE_ENABLE_STMT_SCANSTATUS {}
|
||||
}] {
|
||||
if {$boolFlag ni $::autosetup(options)} {
|
||||
# Skip flags which are in the canonical build but not
|
||||
# the autoconf bundle.
|
||||
continue
|
||||
}
|
||||
proj-if-opt-truthy $boolFlag {
|
||||
sqlite-add-feature-flag $featureFlag
|
||||
if {0 != [eval $ifSetEvalThis] && "all" ne $boolFlag} {
|
||||
msg-result " + $boolFlag"
|
||||
}
|
||||
} {
|
||||
if {"all" ne $boolFlag} {
|
||||
msg-result " - $boolFlag"
|
||||
}
|
||||
}
|
||||
}
|
||||
#
|
||||
# Invert the above loop's logic for some SQLITE_OMIT_... cases. If
|
||||
# config option $boolFlag is false, [sqlite-add-feature-flag
|
||||
# $featureFlag], where $featureFlag is intended to be
|
||||
# -DSQLITE_OMIT_...
|
||||
foreach {boolFlag featureFlag} {
|
||||
json -DSQLITE_OMIT_JSON
|
||||
} {
|
||||
if {[proj-opt-truthy $boolFlag]} {
|
||||
msg-result " + $boolFlag"
|
||||
} else {
|
||||
sqlite-add-feature-flag $featureFlag
|
||||
msg-result " - $boolFlag"
|
||||
}
|
||||
}
|
||||
|
||||
##
|
||||
# Remove duplicates from the final feature flag sets and show them
|
||||
# to the user.
|
||||
set oFF [get-define OPT_FEATURE_FLAGS]
|
||||
if {"" ne $oFF} {
|
||||
define OPT_FEATURE_FLAGS [lsort -unique $oFF]
|
||||
msg-result "Library feature flags: [get-define OPT_FEATURE_FLAGS]"
|
||||
}
|
||||
if {[lsearch [get-define TARGET_DEBUG ""] -DSQLITE_DEBUG=1] > -1} {
|
||||
msg-result "Note: this is a debug build, so performance will suffer."
|
||||
}
|
||||
teaish-cflags-add -define OPT_FEATURE_FLAGS
|
||||
}; # sqlite-handle-common-feature-flags
|
||||
|
||||
#
|
||||
# If --enable-threadsafe is set, this adds -DSQLITE_THREADSAFE=1 to
|
||||
# OPT_FEATURE_FLAGS and sets LDFLAGS_PTHREAD to the linker flags
|
||||
# needed for linking pthread (possibly an empty string). If
|
||||
# --enable-threadsafe is not set, adds -DSQLITE_THREADSAFE=0 to
|
||||
# OPT_FEATURE_FLAGS and sets LDFLAGS_PTHREAD to an empty string.
|
||||
#
|
||||
# It prepends the flags to the global LDFLAGS.
|
||||
proc sqlite-handle-threadsafe {} {
|
||||
msg-checking "Support threadsafe operation? "
|
||||
define LDFLAGS_PTHREAD ""
|
||||
set enable 0
|
||||
if {[proj-opt-was-provided threadsafe]} {
|
||||
proj-if-opt-truthy threadsafe {
|
||||
if {[proj-check-function-in-lib pthread_create pthread]
|
||||
&& [proj-check-function-in-lib pthread_mutexattr_init pthread]} {
|
||||
incr enable
|
||||
set ldf [get-define lib_pthread_create]
|
||||
define LDFLAGS_PTHREAD $ldf
|
||||
teaish-ldflags-prepend $ldf
|
||||
undefine lib_pthread_create
|
||||
undefine lib_pthread_mutexattr_init
|
||||
} else {
|
||||
user-error "Missing required pthread libraries. Use --disable-threadsafe to disable this check."
|
||||
}
|
||||
# Recall that LDFLAGS_PTHREAD might be empty even if pthreads if
|
||||
# found because it's in -lc on some platforms.
|
||||
} {
|
||||
msg-result "Disabled using --disable-threadsafe"
|
||||
}
|
||||
} else {
|
||||
#
|
||||
# If user does not specify --[disable-]threadsafe then select a
|
||||
# default based on whether it looks like Tcl has threading
|
||||
# support.
|
||||
#
|
||||
catch {
|
||||
scan [exec echo {puts [tcl::pkgconfig get threaded]} | [get-define TCLSH_CMD]] \
|
||||
%d enable
|
||||
}
|
||||
if {$enable} {
|
||||
set flagName "--threadsafe"
|
||||
set lblAbled "enabled"
|
||||
msg-result yes
|
||||
} else {
|
||||
set flagName "--disable-threadsafe"
|
||||
set lblAbled "disabled"
|
||||
msg-result no
|
||||
}
|
||||
msg-result "Defaulting to ${flagName} because Tcl has threading ${lblAbled}."
|
||||
# ^^^ We (probably) don't need to link against -lpthread in the
|
||||
# is-enabled case. We might in the case of static linking. Unsure.
|
||||
}
|
||||
sqlite-add-feature-flag -DSQLITE_THREADSAFE=${enable}
|
||||
return $enable
|
||||
}
|
||||
|
||||
#
|
||||
# Handles the --enable-load-extension flag. Returns 1 if the support
|
||||
# is enabled, else 0. If support for that feature is not found, a
|
||||
# fatal error is triggered if --enable-load-extension is explicitly
|
||||
# provided, else a loud warning is instead emitted. If
|
||||
# --disable-load-extension is used, no check is performed.
|
||||
#
|
||||
# Makes the following environment changes:
|
||||
#
|
||||
# - defines LDFLAGS_DLOPEN to any linker flags needed for this
|
||||
# feature. It may legally be empty on some systems where dlopen()
|
||||
# is in libc.
|
||||
#
|
||||
# - If the feature is not available, adds
|
||||
# -DSQLITE_OMIT_LOAD_EXTENSION=1 to the feature flags list.
|
||||
proc sqlite-handle-load-extension {} {
|
||||
define LDFLAGS_DLOPEN ""
|
||||
set found 0
|
||||
proj-if-opt-truthy load-extension {
|
||||
set found [proj-check-function-in-lib dlopen dl]
|
||||
if {$found} {
|
||||
set ldf [get-define lib_dlopen]
|
||||
define LDFLAGS_DLOPEN $ldf
|
||||
teaish-ldflags-prepend $ldf
|
||||
undefine lib_dlopen
|
||||
} else {
|
||||
if {[proj-opt-was-provided load-extension]} {
|
||||
# Explicit --enable-load-extension: fail if not found
|
||||
proj-indented-notice -error {
|
||||
--enable-load-extension was provided but dlopen()
|
||||
not found. Use --disable-load-extension to bypass this
|
||||
check.
|
||||
}
|
||||
} else {
|
||||
# It was implicitly enabled: warn if not found
|
||||
proj-indented-notice {
|
||||
WARNING: dlopen() not found, so loadable module support will
|
||||
be disabled. Use --disable-load-extension to bypass this
|
||||
check.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$found} {
|
||||
msg-result "Loadable extension support enabled."
|
||||
} else {
|
||||
msg-result "Disabling loadable extension support. Use --enable-load-extension to enable them."
|
||||
sqlite-add-feature-flag -DSQLITE_OMIT_LOAD_EXTENSION=1
|
||||
}
|
||||
return $found
|
||||
}
|
||||
|
||||
#
|
||||
# ICU - International Components for Unicode
|
||||
#
|
||||
# Handles these flags:
|
||||
#
|
||||
# --with-icu-ldflags=LDFLAGS
|
||||
# --with-icu-cflags=CFLAGS
|
||||
# --with-icu-config[=auto | pkg-config | /path/to/icu-config]
|
||||
# --enable-icu-collations
|
||||
#
|
||||
# --with-icu-config values:
|
||||
#
|
||||
# - auto: use the first one of (pkg-config, icu-config) found on the
|
||||
# system.
|
||||
# - pkg-config: use only pkg-config to determine flags
|
||||
# - /path/to/icu-config: use that to determine flags
|
||||
#
|
||||
# If --with-icu-config is used as neither pkg-config nor icu-config
|
||||
# are found, fail fatally.
|
||||
#
|
||||
# If both --with-icu-ldflags and --with-icu-config are provided, they
|
||||
# are cumulative. If neither are provided, icu-collations is not
|
||||
# honored and a warning is emitted if it is provided.
|
||||
#
|
||||
# Design note: though we could automatically enable ICU if the
|
||||
# icu-config binary or (pkg-config icu-io) are found, we specifically
|
||||
# do not. ICU is always an opt-in feature.
|
||||
proc sqlite-handle-icu {} {
|
||||
define LDFLAGS_LIBICU [join [opt-val with-icu-ldflags ""]]
|
||||
define CFLAGS_LIBICU [join [opt-val with-icu-cflags ""]]
|
||||
if {[proj-opt-was-provided with-icu-config]} {
|
||||
msg-result "Checking for ICU support..."
|
||||
set icuConfigBin [opt-val with-icu-config]
|
||||
set tryIcuConfigBin 1; # set to 0 if we end up using pkg-config
|
||||
if {$icuConfigBin in {auto pkg-config}} {
|
||||
uplevel 3 { use pkg-config }
|
||||
if {[pkg-config-init 0] && [pkg-config icu-io]} {
|
||||
# Maintenance reminder: historical docs say to use both of
|
||||
# (icu-io, icu-uc). icu-uc lacks a required lib and icu-io has
|
||||
# all of them on tested OSes.
|
||||
set tryIcuConfigBin 0
|
||||
define LDFLAGS_LIBICU [get-define PKG_ICU_IO_LDFLAGS]
|
||||
define-append LDFLAGS_LIBICU [get-define PKG_ICU_IO_LIBS]
|
||||
define CFLAGS_LIBICU [get-define PKG_ICU_IO_CFLAGS]
|
||||
} elseif {"pkg-config" eq $icuConfigBin} {
|
||||
proj-fatal "pkg-config cannot find package icu-io"
|
||||
} else {
|
||||
proj-assert {"auto" eq $icuConfigBin}
|
||||
}
|
||||
}
|
||||
if {$tryIcuConfigBin} {
|
||||
if {"auto" eq $icuConfigBin} {
|
||||
set icuConfigBin [proj-first-bin-of \
|
||||
/usr/local/bin/icu-config \
|
||||
/usr/bin/icu-config]
|
||||
if {"" eq $icuConfigBin} {
|
||||
proj-indented-notice -error {
|
||||
--with-icu-config=auto cannot find (pkg-config icu-io) or icu-config binary.
|
||||
On Ubuntu-like systems try:
|
||||
--with-icu-ldflags='-licui18n -licuuc -licudata'
|
||||
}
|
||||
}
|
||||
}
|
||||
if {[file-isexec $icuConfigBin]} {
|
||||
set x [exec $icuConfigBin --ldflags]
|
||||
if {"" eq $x} {
|
||||
proj-indented-notice -error \
|
||||
[subst {
|
||||
$icuConfigBin --ldflags returned no data.
|
||||
On Ubuntu-like systems try:
|
||||
--with-icu-ldflags='-licui18n -licuuc -licudata'
|
||||
}]
|
||||
}
|
||||
define-append LDFLAGS_LIBICU $x
|
||||
set x [exec $icuConfigBin --cppflags]
|
||||
define-append CFLAGS_LIBICU $x
|
||||
} else {
|
||||
proj-fatal "--with-icu-config=$icuConfigBin does not refer to an executable"
|
||||
}
|
||||
}
|
||||
}
|
||||
set ldflags [define LDFLAGS_LIBICU [string trim [get-define LDFLAGS_LIBICU]]]
|
||||
set cflags [define CFLAGS_LIBICU [string trim [get-define CFLAGS_LIBICU]]]
|
||||
if {"" ne $ldflags} {
|
||||
sqlite-add-feature-flag -DSQLITE_ENABLE_ICU
|
||||
msg-result "Enabling ICU support with flags: $ldflags $cflags"
|
||||
if {[opt-bool icu-collations]} {
|
||||
msg-result "Enabling ICU collations."
|
||||
sqlite-add-feature-flag -DSQLITE_ENABLE_ICU_COLLATIONS
|
||||
}
|
||||
teaish-ldflags-prepend $ldflags
|
||||
teaish-cflags-add $cflags
|
||||
} elseif {[opt-bool icu-collations]} {
|
||||
proj-warn "ignoring --enable-icu-collations because neither --with-icu-ldflags nor --with-icu-config provided any linker flags"
|
||||
} else {
|
||||
msg-result "ICU support is disabled."
|
||||
}
|
||||
}; # sqlite-handle-icu
|
||||
|
||||
|
||||
#
|
||||
# Handles the --with-tempstore flag.
|
||||
#
|
||||
# The test fixture likes to set SQLITE_TEMP_STORE on its own, so do
|
||||
# not set that feature flag unless it was explicitly provided to the
|
||||
# configure script.
|
||||
proc sqlite-handle-tempstore {} {
|
||||
if {[proj-opt-was-provided with-tempstore]} {
|
||||
set ts [opt-val with-tempstore no]
|
||||
set tsn 1
|
||||
msg-checking "Use an in-RAM database for temporary tables? "
|
||||
switch -exact -- $ts {
|
||||
never { set tsn 0 }
|
||||
no { set tsn 1 }
|
||||
yes { set tsn 2 }
|
||||
always { set tsn 3 }
|
||||
default {
|
||||
user-error "Invalid --with-tempstore value '$ts'. Use one of: never, no, yes, always"
|
||||
}
|
||||
}
|
||||
msg-result $ts
|
||||
sqlite-add-feature-flag -DSQLITE_TEMP_STORE=$tsn
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Handles the --enable-math flag.
|
||||
proc sqlite-handle-math {} {
|
||||
proj-if-opt-truthy math {
|
||||
if {![proj-check-function-in-lib ceil m]} {
|
||||
user-error "Cannot find libm functions. Use --disable-math to bypass this."
|
||||
}
|
||||
set lfl [get-define lib_ceil]
|
||||
undefine lib_ceil
|
||||
define LDFLAGS_MATH $lfl
|
||||
teaish-ldflags-prepend $lfl
|
||||
sqlite-add-feature-flag -DSQLITE_ENABLE_MATH_FUNCTIONS
|
||||
msg-result "Enabling math SQL functions"
|
||||
} {
|
||||
define LDFLAGS_MATH ""
|
||||
msg-result "Disabling math SQL functions"
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Move -DSQLITE_OMIT... and -DSQLITE_ENABLE... flags from CFLAGS and
|
||||
# CPPFLAGS to OPT_FEATURE_FLAGS and remove them from BUILD_CFLAGS.
|
||||
proc sqlite-munge-cflags {} {
|
||||
# Move CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and
|
||||
# -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived
|
||||
# from the pre-3.48 build.
|
||||
#
|
||||
# If any configure flags for features are in conflict with
|
||||
# CFLAGS/CPPFLAGS-specified feature flags, all bets are off. There
|
||||
# are no guarantees about which one will take precedence.
|
||||
foreach flagDef {CFLAGS CPPFLAGS} {
|
||||
set tmp ""
|
||||
foreach cf [get-define $flagDef ""] {
|
||||
switch -glob -- $cf {
|
||||
-DSQLITE_OMIT* -
|
||||
-DSQLITE_ENABLE* {
|
||||
sqlite-add-feature-flag $cf
|
||||
}
|
||||
default {
|
||||
lappend tmp $cf
|
||||
}
|
||||
}
|
||||
}
|
||||
define $flagDef $tmp
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
test-expect 1.0-open {
|
||||
sqlite3 db :memory:
|
||||
} {}
|
||||
|
||||
test-assert 1.1-version-3.x {
|
||||
[string match 3.* [db eval {select sqlite_version()}]]
|
||||
}
|
||||
|
||||
test-expect 1.2-select {
|
||||
db eval {select 'hi, world',1,2,3}
|
||||
} {{hi, world} 1 2 3}
|
||||
|
||||
|
||||
test-expect 99.0-db-close {db close} {}
|
||||
@@ -0,0 +1,61 @@
|
||||
#------------------------------------------------------------- -*- makefile -*-
|
||||
#
|
||||
# Sample makefile for building Tcl extensions.
|
||||
#
|
||||
# Basic build, test and install
|
||||
# nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\tcl
|
||||
# nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\tcl test
|
||||
# nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\tcl install
|
||||
#
|
||||
# For other build options (debug, static etc.)
|
||||
# See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for
|
||||
# detailed documentation.
|
||||
#
|
||||
# See the file "license.terms" for information on usage and redistribution
|
||||
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# PROJECT is sqlite, not sqlite3 to match TEA AC_INIT definition.
|
||||
# This makes the generated DLL name also consistent between the two
|
||||
# except for the "t" suffix which is the convention for nmake builds.
|
||||
PROJECT = sqlite
|
||||
PRJ_PACKAGE_TCLNAME = sqlite3
|
||||
|
||||
!include "rules-ext.vc"
|
||||
|
||||
PRJ_OBJS = $(TMP_DIR)\tclsqlite3.obj
|
||||
|
||||
# Preprocessor macros specific to sqlite3.
|
||||
PRJ_DEFINES = -I"$(ROOT)\.." -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB=1 -DSQLITE_ENABLE_DBSTAT_VTAB=1 \
|
||||
-DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS4=1 \
|
||||
-DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 \
|
||||
-DSQLITE_ENABLE_JSON1=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 \
|
||||
-DSQLITE_3_SUFFIX_ONLY=1 -DSQLITE_ENABLE_RTREE=1 \
|
||||
-DSQLITE_UNTESTABLE=1 -DSQLITE_OMIT_LOOKASIDE=1 \
|
||||
-DSQLITE_SECURE_DELETE=1 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_GEOPOLY=1 \
|
||||
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 \
|
||||
-DSQLITE_ENABLE_MATH_FUNCTIONS=1 -DDSQLITE_USE_ALLOCA=1 \
|
||||
-DSQLITE_ENABLE_STAT4=1 -DSQLITE_OMIT_DEPRECATED=1 \
|
||||
-DSQLITE_WIN32_GETVERSIONEX=0 -DSQLITE_WIN32_NO_ANSI=1
|
||||
PRJ_DEFINES = $(PRJ_DEFINES) -I$(TMP_DIR)
|
||||
|
||||
# Standard targets to build, install, test etc.
|
||||
!include "$(_RULESDIR)\targets.vc"
|
||||
|
||||
# The built-in pkgindex does no suffice for our extension as
|
||||
# the PROJECT name (sqlite) is not same as init function name (Sqlite3)
|
||||
pkgindex:
|
||||
@echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl
|
||||
@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
|
||||
[list load [file join $$dir $(PRJLIBNAME9)] [string totitle $(PRJ_PACKAGE_TCLNAME)]] >> $(OUT_DIR)\pkgIndex.tcl
|
||||
@echo } else { >> $(OUT_DIR)\pkgIndex.tcl
|
||||
@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
|
||||
[list load [file join $$dir $(PRJLIBNAME8)] [string totitle $(PRJ_PACKAGE_TCLNAME)]] >> $(OUT_DIR)\pkgIndex.tcl
|
||||
@echo } >> $(OUT_DIR)\pkgIndex.tcl
|
||||
|
||||
# Install the manpage though on Windows, doubt it does much good
|
||||
install: default-install-docs-n
|
||||
|
||||
# Explicit dependency rules
|
||||
@@ -0,0 +1,815 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* nmakehlp.c --
|
||||
*
|
||||
* This is used to fix limitations within nmake and the environment.
|
||||
*
|
||||
* Copyright (c) 2002 by David Gravereaux.
|
||||
* Copyright (c) 2006 by Pat Thoyts
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#include <windows.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "user32.lib")
|
||||
#pragma comment (lib, "kernel32.lib")
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
* This library is required for x64 builds with _some_ versions of MSVC
|
||||
*/
|
||||
#if defined(_M_IA64) || defined(_M_AMD64)
|
||||
#if _MSC_VER >= 1400 && _MSC_VER < 1500
|
||||
#pragma comment(lib, "bufferoverflowU")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ISO hack for dumb VC++ */
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
|
||||
/* protos */
|
||||
|
||||
static int CheckForCompilerFeature(const char *option);
|
||||
static int CheckForLinkerFeature(char **options, int count);
|
||||
static int IsIn(const char *string, const char *substring);
|
||||
static int SubstituteFile(const char *substs, const char *filename);
|
||||
static int QualifyPath(const char *path);
|
||||
static int LocateDependency(const char *keyfile);
|
||||
static const char *GetVersionFromFile(const char *filename, const char *match, int numdots);
|
||||
static DWORD WINAPI ReadFromPipe(LPVOID args);
|
||||
|
||||
/* globals */
|
||||
|
||||
#define CHUNK 25
|
||||
#define STATICBUFFERSIZE 1000
|
||||
typedef struct {
|
||||
HANDLE pipe;
|
||||
char buffer[STATICBUFFERSIZE];
|
||||
} pipeinfo;
|
||||
|
||||
pipeinfo Out = {INVALID_HANDLE_VALUE, ""};
|
||||
pipeinfo Err = {INVALID_HANDLE_VALUE, ""};
|
||||
|
||||
/*
|
||||
* exitcodes: 0 == no, 1 == yes, 2 == error
|
||||
*/
|
||||
|
||||
int
|
||||
main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
{
|
||||
char msg[300];
|
||||
DWORD dwWritten;
|
||||
int chars;
|
||||
const char *s;
|
||||
|
||||
/*
|
||||
* Make sure children (cl.exe and link.exe) are kept quiet.
|
||||
*/
|
||||
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
||||
|
||||
/*
|
||||
* Make sure the compiler and linker aren't effected by the outside world.
|
||||
*/
|
||||
|
||||
SetEnvironmentVariable("CL", "");
|
||||
SetEnvironmentVariable("LINK", "");
|
||||
|
||||
if (argc > 1 && *argv[1] == '-') {
|
||||
switch (*(argv[1]+1)) {
|
||||
case 'c':
|
||||
if (argc != 3) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -c <compiler option>\n"
|
||||
"Tests for whether cl.exe supports an option\n"
|
||||
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 2;
|
||||
}
|
||||
return CheckForCompilerFeature(argv[2]);
|
||||
case 'l':
|
||||
if (argc < 3) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -l <linker option> ?<mandatory option> ...?\n"
|
||||
"Tests for whether link.exe supports an option\n"
|
||||
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 2;
|
||||
}
|
||||
return CheckForLinkerFeature(&argv[2], argc-2);
|
||||
case 'f':
|
||||
if (argc == 2) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -f <string> <substring>\n"
|
||||
"Find a substring within another\n"
|
||||
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 2;
|
||||
} else if (argc == 3) {
|
||||
/*
|
||||
* If the string is blank, there is no match.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return IsIn(argv[2], argv[3]);
|
||||
}
|
||||
case 's':
|
||||
if (argc == 2) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -s <substitutions file> <file>\n"
|
||||
"Perform a set of string map type substutitions on a file\n"
|
||||
"exitcodes: 0\n",
|
||||
argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 2;
|
||||
}
|
||||
return SubstituteFile(argv[2], argv[3]);
|
||||
case 'V':
|
||||
if (argc != 4) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -V filename matchstring\n"
|
||||
"Extract a version from a file:\n"
|
||||
"eg: pkgIndex.tcl \"package ifneeded http\"",
|
||||
argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 0;
|
||||
}
|
||||
s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0');
|
||||
if (s && *s) {
|
||||
printf("%s\n", s);
|
||||
return 0;
|
||||
} else
|
||||
return 1; /* Version not found. Return non-0 exit code */
|
||||
|
||||
case 'Q':
|
||||
if (argc != 3) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -Q path\n"
|
||||
"Emit the fully qualified path\n"
|
||||
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 2;
|
||||
}
|
||||
return QualifyPath(argv[2]);
|
||||
|
||||
case 'L':
|
||||
if (argc != 3) {
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -L keypath\n"
|
||||
"Emit the fully qualified path of directory containing keypath\n"
|
||||
"exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
|
||||
&dwWritten, NULL);
|
||||
return 2;
|
||||
}
|
||||
return LocateDependency(argv[2]);
|
||||
}
|
||||
}
|
||||
chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"usage: %s -c|-f|-l|-Q|-s|-V ...\n"
|
||||
"This is a little helper app to equalize shell differences between WinNT and\n"
|
||||
"Win9x and get nmake.exe to accomplish its job.\n",
|
||||
argv[0]);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int
|
||||
CheckForCompilerFeature(
|
||||
const char *option)
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
DWORD threadID;
|
||||
char msg[300];
|
||||
BOOL ok;
|
||||
HANDLE hProcess, h, pipeThreads[2];
|
||||
char cmdline[100];
|
||||
|
||||
hProcess = GetCurrentProcess();
|
||||
|
||||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdInput = INVALID_HANDLE_VALUE;
|
||||
|
||||
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = FALSE;
|
||||
|
||||
/*
|
||||
* Create a non-inheritible pipe.
|
||||
*/
|
||||
|
||||
CreatePipe(&Out.pipe, &h, &sa, 0);
|
||||
|
||||
/*
|
||||
* Dupe the write side, make it inheritible, and close the original.
|
||||
*/
|
||||
|
||||
DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
|
||||
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
||||
|
||||
/*
|
||||
* Same as above, but for the error side.
|
||||
*/
|
||||
|
||||
CreatePipe(&Err.pipe, &h, &sa, 0);
|
||||
DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
|
||||
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
||||
|
||||
/*
|
||||
* Base command line.
|
||||
*/
|
||||
|
||||
lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch ");
|
||||
|
||||
/*
|
||||
* Append our option for testing
|
||||
*/
|
||||
|
||||
lstrcat(cmdline, option);
|
||||
|
||||
/*
|
||||
* Filename to compile, which exists, but is nothing and empty.
|
||||
*/
|
||||
|
||||
lstrcat(cmdline, " .\\nul");
|
||||
|
||||
ok = CreateProcess(
|
||||
NULL, /* Module name. */
|
||||
cmdline, /* Command line. */
|
||||
NULL, /* Process handle not inheritable. */
|
||||
NULL, /* Thread handle not inheritable. */
|
||||
TRUE, /* yes, inherit handles. */
|
||||
DETACHED_PROCESS, /* No console for you. */
|
||||
NULL, /* Use parent's environment block. */
|
||||
NULL, /* Use parent's starting directory. */
|
||||
&si, /* Pointer to STARTUPINFO structure. */
|
||||
&pi); /* Pointer to PROCESS_INFORMATION structure. */
|
||||
|
||||
if (!ok) {
|
||||
DWORD err = GetLastError();
|
||||
int chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
|
||||
(300-chars), 0);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close our references to the write handles that have now been inherited.
|
||||
*/
|
||||
|
||||
CloseHandle(si.hStdOutput);
|
||||
CloseHandle(si.hStdError);
|
||||
|
||||
WaitForInputIdle(pi.hProcess, 5000);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
/*
|
||||
* Start the pipe reader threads.
|
||||
*/
|
||||
|
||||
pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
|
||||
pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
|
||||
|
||||
/*
|
||||
* Block waiting for the process to end.
|
||||
*/
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
/*
|
||||
* Wait for our pipe to get done reading, should it be a little slow.
|
||||
*/
|
||||
|
||||
WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
|
||||
CloseHandle(pipeThreads[0]);
|
||||
CloseHandle(pipeThreads[1]);
|
||||
|
||||
/*
|
||||
* Look for the commandline warning code in both streams.
|
||||
* - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
|
||||
*/
|
||||
|
||||
return !(strstr(Out.buffer, "D4002") != NULL
|
||||
|| strstr(Err.buffer, "D4002") != NULL
|
||||
|| strstr(Out.buffer, "D9002") != NULL
|
||||
|| strstr(Err.buffer, "D9002") != NULL
|
||||
|| strstr(Out.buffer, "D2021") != NULL
|
||||
|| strstr(Err.buffer, "D2021") != NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
CheckForLinkerFeature(
|
||||
char **options,
|
||||
int count)
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
DWORD threadID;
|
||||
char msg[300];
|
||||
BOOL ok;
|
||||
HANDLE hProcess, h, pipeThreads[2];
|
||||
int i;
|
||||
char cmdline[255];
|
||||
|
||||
hProcess = GetCurrentProcess();
|
||||
|
||||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdInput = INVALID_HANDLE_VALUE;
|
||||
|
||||
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = TRUE;
|
||||
|
||||
/*
|
||||
* Create a non-inheritible pipe.
|
||||
*/
|
||||
|
||||
CreatePipe(&Out.pipe, &h, &sa, 0);
|
||||
|
||||
/*
|
||||
* Dupe the write side, make it inheritible, and close the original.
|
||||
*/
|
||||
|
||||
DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
|
||||
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
||||
|
||||
/*
|
||||
* Same as above, but for the error side.
|
||||
*/
|
||||
|
||||
CreatePipe(&Err.pipe, &h, &sa, 0);
|
||||
DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE,
|
||||
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
||||
|
||||
/*
|
||||
* Base command line.
|
||||
*/
|
||||
|
||||
lstrcpy(cmdline, "link.exe -nologo ");
|
||||
|
||||
/*
|
||||
* Append our option for testing.
|
||||
*/
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
lstrcat(cmdline, " \"");
|
||||
lstrcat(cmdline, options[i]);
|
||||
lstrcat(cmdline, "\"");
|
||||
}
|
||||
|
||||
ok = CreateProcess(
|
||||
NULL, /* Module name. */
|
||||
cmdline, /* Command line. */
|
||||
NULL, /* Process handle not inheritable. */
|
||||
NULL, /* Thread handle not inheritable. */
|
||||
TRUE, /* yes, inherit handles. */
|
||||
DETACHED_PROCESS, /* No console for you. */
|
||||
NULL, /* Use parent's environment block. */
|
||||
NULL, /* Use parent's starting directory. */
|
||||
&si, /* Pointer to STARTUPINFO structure. */
|
||||
&pi); /* Pointer to PROCESS_INFORMATION structure. */
|
||||
|
||||
if (!ok) {
|
||||
DWORD err = GetLastError();
|
||||
int chars = snprintf(msg, sizeof(msg) - 1,
|
||||
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
|
||||
(300-chars), 0);
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close our references to the write handles that have now been inherited.
|
||||
*/
|
||||
|
||||
CloseHandle(si.hStdOutput);
|
||||
CloseHandle(si.hStdError);
|
||||
|
||||
WaitForInputIdle(pi.hProcess, 5000);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
/*
|
||||
* Start the pipe reader threads.
|
||||
*/
|
||||
|
||||
pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID);
|
||||
pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID);
|
||||
|
||||
/*
|
||||
* Block waiting for the process to end.
|
||||
*/
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
/*
|
||||
* Wait for our pipe to get done reading, should it be a little slow.
|
||||
*/
|
||||
|
||||
WaitForMultipleObjects(2, pipeThreads, TRUE, 500);
|
||||
CloseHandle(pipeThreads[0]);
|
||||
CloseHandle(pipeThreads[1]);
|
||||
|
||||
/*
|
||||
* Look for the commandline warning code in the stderr stream.
|
||||
*/
|
||||
|
||||
return !(strstr(Out.buffer, "LNK1117") != NULL ||
|
||||
strstr(Err.buffer, "LNK1117") != NULL ||
|
||||
strstr(Out.buffer, "LNK4044") != NULL ||
|
||||
strstr(Err.buffer, "LNK4044") != NULL ||
|
||||
strstr(Out.buffer, "LNK4224") != NULL ||
|
||||
strstr(Err.buffer, "LNK4224") != NULL);
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
ReadFromPipe(
|
||||
LPVOID args)
|
||||
{
|
||||
pipeinfo *pi = (pipeinfo *) args;
|
||||
char *lastBuf = pi->buffer;
|
||||
DWORD dwRead;
|
||||
BOOL ok;
|
||||
|
||||
again:
|
||||
if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) {
|
||||
CloseHandle(pi->pipe);
|
||||
return (DWORD)-1;
|
||||
}
|
||||
ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L);
|
||||
if (!ok || dwRead == 0) {
|
||||
CloseHandle(pi->pipe);
|
||||
return 0;
|
||||
}
|
||||
lastBuf += dwRead;
|
||||
goto again;
|
||||
|
||||
return 0; /* makes the compiler happy */
|
||||
}
|
||||
|
||||
static int
|
||||
IsIn(
|
||||
const char *string,
|
||||
const char *substring)
|
||||
{
|
||||
return (strstr(string, substring) != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* GetVersionFromFile --
|
||||
* Looks for a match string in a file and then returns the version
|
||||
* following the match where a version is anything acceptable to
|
||||
* package provide or package ifneeded.
|
||||
*/
|
||||
|
||||
static const char *
|
||||
GetVersionFromFile(
|
||||
const char *filename,
|
||||
const char *match,
|
||||
int numdots)
|
||||
{
|
||||
static char szBuffer[100];
|
||||
char *szResult = NULL;
|
||||
FILE *fp = fopen(filename, "rt");
|
||||
|
||||
if (fp != NULL) {
|
||||
/*
|
||||
* Read data until we see our match string.
|
||||
*/
|
||||
|
||||
while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
|
||||
LPSTR p, q;
|
||||
|
||||
p = strstr(szBuffer, match);
|
||||
if (p != NULL) {
|
||||
/*
|
||||
* Skip to first digit after the match.
|
||||
*/
|
||||
|
||||
p += strlen(match);
|
||||
while (*p && !isdigit((unsigned char)*p)) {
|
||||
++p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find ending whitespace.
|
||||
*/
|
||||
|
||||
q = p;
|
||||
while (*q && (strchr("0123456789.ab", *q)) && (((!strchr(".ab", *q)
|
||||
&& !strchr("ab", q[-1])) || --numdots))) {
|
||||
++q;
|
||||
}
|
||||
|
||||
*q = 0;
|
||||
szResult = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
return szResult;
|
||||
}
|
||||
|
||||
/*
|
||||
* List helpers for the SubstituteFile function
|
||||
*/
|
||||
|
||||
typedef struct list_item_t {
|
||||
struct list_item_t *nextPtr;
|
||||
char * key;
|
||||
char * value;
|
||||
} list_item_t;
|
||||
|
||||
/* insert a list item into the list (list may be null) */
|
||||
static list_item_t *
|
||||
list_insert(list_item_t **listPtrPtr, const char *key, const char *value)
|
||||
{
|
||||
list_item_t *itemPtr = (list_item_t *)malloc(sizeof(list_item_t));
|
||||
if (itemPtr) {
|
||||
itemPtr->key = strdup(key);
|
||||
itemPtr->value = strdup(value);
|
||||
itemPtr->nextPtr = NULL;
|
||||
|
||||
while(*listPtrPtr) {
|
||||
listPtrPtr = &(*listPtrPtr)->nextPtr;
|
||||
}
|
||||
*listPtrPtr = itemPtr;
|
||||
}
|
||||
return itemPtr;
|
||||
}
|
||||
|
||||
static void
|
||||
list_free(list_item_t **listPtrPtr)
|
||||
{
|
||||
list_item_t *tmpPtr, *listPtr = *listPtrPtr;
|
||||
while (listPtr) {
|
||||
tmpPtr = listPtr;
|
||||
listPtr = listPtr->nextPtr;
|
||||
free(tmpPtr->key);
|
||||
free(tmpPtr->value);
|
||||
free(tmpPtr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SubstituteFile --
|
||||
* As windows doesn't provide anything useful like sed and it's unreliable
|
||||
* to use the tclsh you are building against (consider x-platform builds -
|
||||
* eg compiling AMD64 target from IX86) we provide a simple substitution
|
||||
* option here to handle autoconf style substitutions.
|
||||
* The substitution file is whitespace and line delimited. The file should
|
||||
* consist of lines matching the regular expression:
|
||||
* \s*\S+\s+\S*$
|
||||
*
|
||||
* Usage is something like:
|
||||
* nmakehlp -S << $** > $@
|
||||
* @PACKAGE_NAME@ $(PACKAGE_NAME)
|
||||
* @PACKAGE_VERSION@ $(PACKAGE_VERSION)
|
||||
* <<
|
||||
*/
|
||||
|
||||
static int
|
||||
SubstituteFile(
|
||||
const char *substitutions,
|
||||
const char *filename)
|
||||
{
|
||||
static char szBuffer[1024], szCopy[1024];
|
||||
list_item_t *substPtr = NULL;
|
||||
FILE *fp, *sp;
|
||||
|
||||
fp = fopen(filename, "rt");
|
||||
if (fp != NULL) {
|
||||
|
||||
/*
|
||||
* Build a list of substutitions from the first filename
|
||||
*/
|
||||
|
||||
sp = fopen(substitutions, "rt");
|
||||
if (sp != NULL) {
|
||||
while (fgets(szBuffer, sizeof(szBuffer), sp) != NULL) {
|
||||
unsigned char *ks, *ke, *vs, *ve;
|
||||
ks = (unsigned char*)szBuffer;
|
||||
while (ks && *ks && isspace(*ks)) ++ks;
|
||||
ke = ks;
|
||||
while (ke && *ke && !isspace(*ke)) ++ke;
|
||||
vs = ke;
|
||||
while (vs && *vs && isspace(*vs)) ++vs;
|
||||
ve = vs;
|
||||
while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve;
|
||||
*ke = 0, *ve = 0;
|
||||
list_insert(&substPtr, (char*)ks, (char*)vs);
|
||||
}
|
||||
fclose(sp);
|
||||
}
|
||||
|
||||
/* debug: dump the list */
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
int n = 0;
|
||||
list_item_t *p = NULL;
|
||||
for (p = substPtr; p != NULL; p = p->nextPtr, ++n) {
|
||||
fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Run the substitutions over each line of the input
|
||||
*/
|
||||
|
||||
while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {
|
||||
list_item_t *p = NULL;
|
||||
for (p = substPtr; p != NULL; p = p->nextPtr) {
|
||||
char *m = strstr(szBuffer, p->key);
|
||||
if (m) {
|
||||
char *cp, *op, *sp;
|
||||
cp = szCopy;
|
||||
op = szBuffer;
|
||||
while (op != m) *cp++ = *op++;
|
||||
sp = p->value;
|
||||
while (sp && *sp) *cp++ = *sp++;
|
||||
op += strlen(p->key);
|
||||
while (*op) *cp++ = *op++;
|
||||
*cp = 0;
|
||||
memcpy(szBuffer, szCopy, sizeof(szCopy));
|
||||
}
|
||||
}
|
||||
printf("%s", szBuffer);
|
||||
}
|
||||
|
||||
list_free(&substPtr);
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL FileExists(LPCTSTR szPath)
|
||||
{
|
||||
#ifndef INVALID_FILE_ATTRIBUTES
|
||||
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||
#endif
|
||||
DWORD pathAttr = GetFileAttributes(szPath);
|
||||
return (pathAttr != INVALID_FILE_ATTRIBUTES &&
|
||||
!(pathAttr & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* QualifyPath --
|
||||
*
|
||||
* This composes the current working directory with a provided path
|
||||
* and returns the fully qualified and normalized path.
|
||||
* Mostly needed to setup paths for testing.
|
||||
*/
|
||||
|
||||
static int
|
||||
QualifyPath(
|
||||
const char *szPath)
|
||||
{
|
||||
char szCwd[MAX_PATH + 1];
|
||||
|
||||
GetFullPathName(szPath, sizeof(szCwd)-1, szCwd, NULL);
|
||||
printf("%s\n", szCwd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements LocateDependency for a single directory. See that command
|
||||
* for an explanation.
|
||||
* Returns 0 if found after printing the directory.
|
||||
* Returns 1 if not found but no errors.
|
||||
* Returns 2 on any kind of error
|
||||
* Basically, these are used as exit codes for the process.
|
||||
*/
|
||||
static int LocateDependencyHelper(const char *dir, const char *keypath)
|
||||
{
|
||||
HANDLE hSearch;
|
||||
char path[MAX_PATH+1];
|
||||
size_t dirlen;
|
||||
int keylen, ret;
|
||||
WIN32_FIND_DATA finfo;
|
||||
|
||||
if (dir == NULL || keypath == NULL)
|
||||
return 2; /* Have no real error reporting mechanism into nmake */
|
||||
dirlen = strlen(dir);
|
||||
if ((dirlen + 3) > sizeof(path))
|
||||
return 2;
|
||||
strncpy(path, dir, dirlen);
|
||||
strncpy(path+dirlen, "\\*", 3); /* Including terminating \0 */
|
||||
keylen = strlen(keypath);
|
||||
|
||||
#if 0 /* This function is not available in Visual C++ 6 */
|
||||
/*
|
||||
* Use numerics 0 -> FindExInfoStandard,
|
||||
* 1 -> FindExSearchLimitToDirectories,
|
||||
* as these are not defined in Visual C++ 6
|
||||
*/
|
||||
hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
|
||||
#else
|
||||
hSearch = FindFirstFile(path, &finfo);
|
||||
#endif
|
||||
if (hSearch == INVALID_HANDLE_VALUE)
|
||||
return 1; /* Not found */
|
||||
|
||||
/* Loop through all subdirs checking if the keypath is under there */
|
||||
ret = 1; /* Assume not found */
|
||||
do {
|
||||
int sublen;
|
||||
/*
|
||||
* We need to check it is a directory despite the
|
||||
* FindExSearchLimitToDirectories in the above call. See SDK docs
|
||||
*/
|
||||
if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
continue;
|
||||
sublen = strlen(finfo.cFileName);
|
||||
if ((dirlen+1+sublen+1+keylen+1) > sizeof(path))
|
||||
continue; /* Path does not fit, assume not matched */
|
||||
strncpy(path+dirlen+1, finfo.cFileName, sublen);
|
||||
path[dirlen+1+sublen] = '\\';
|
||||
strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
|
||||
if (FileExists(path)) {
|
||||
/* Found a match, print to stdout */
|
||||
path[dirlen+1+sublen] = '\0';
|
||||
QualifyPath(path);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
} while (FindNextFile(hSearch, &finfo));
|
||||
FindClose(hSearch);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* LocateDependency --
|
||||
*
|
||||
* Locates a dependency for a package.
|
||||
* keypath - a relative path within the package directory
|
||||
* that is used to confirm it is the correct directory.
|
||||
* The search path for the package directory is currently only
|
||||
* the parent and grandparent of the current working directory.
|
||||
* If found, the command prints
|
||||
* name_DIRPATH=<full path of located directory>
|
||||
* and returns 0. If not found, does not print anything and returns 1.
|
||||
*/
|
||||
static int LocateDependency(const char *keypath)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
static const char *paths[] = {"..", "..\\..", "..\\..\\.."};
|
||||
|
||||
for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
|
||||
ret = LocateDependencyHelper(paths[i], keypath);
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* indent-tabs-mode: t
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,123 @@
|
||||
# This file should only be included in makefiles for Tcl extensions,
|
||||
# NOT in the makefile for Tcl itself.
|
||||
|
||||
!ifndef _RULES_EXT_VC
|
||||
|
||||
# We need to run from the directory the parent makefile is located in.
|
||||
# nmake does not tell us what makefile was used to invoke it so parent
|
||||
# makefile has to set the MAKEFILEVC macro or we just make a guess and
|
||||
# warn if we think that is not the case.
|
||||
!if "$(MAKEFILEVC)" == ""
|
||||
|
||||
!if exist("$(PROJECT).vc")
|
||||
MAKEFILEVC = $(PROJECT).vc
|
||||
!elseif exist("makefile.vc")
|
||||
MAKEFILEVC = makefile.vc
|
||||
!endif
|
||||
!endif # "$(MAKEFILEVC)" == ""
|
||||
|
||||
!if !exist("$(MAKEFILEVC)")
|
||||
MSG = ^
|
||||
You must run nmake from the directory containing the project makefile.^
|
||||
If you are doing that and getting this message, set the MAKEFILEVC^
|
||||
macro to the name of the project makefile.
|
||||
!message WARNING: $(MSG)
|
||||
!endif
|
||||
|
||||
!if "$(PROJECT)" == "tcl"
|
||||
!error The rules-ext.vc file is not intended for Tcl itself.
|
||||
!endif
|
||||
|
||||
# We extract version numbers using the nmakehlp program. For now use
|
||||
# the local copy of nmakehlp. Once we locate Tcl, we will use that
|
||||
# one if it is newer.
|
||||
!if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)"
|
||||
!if [$(CC) -nologo -DNDEBUG "nmakehlp.c" -link -subsystem:console > nul]
|
||||
!endif
|
||||
!else
|
||||
!if [copy x86_64-w64-mingw32-nmakehlp.exe nmakehlp.exe >NUL]
|
||||
!endif
|
||||
!endif
|
||||
|
||||
# First locate the Tcl directory that we are working with.
|
||||
!if "$(TCLDIR)" != ""
|
||||
|
||||
_RULESDIR = $(TCLDIR:/=\)
|
||||
|
||||
!else
|
||||
|
||||
# If an installation path is specified, that is also the Tcl directory.
|
||||
# Also Tk never builds against an installed Tcl, it needs Tcl sources
|
||||
!if defined(INSTALLDIR) && "$(PROJECT)" != "tk"
|
||||
_RULESDIR=$(INSTALLDIR:/=\)
|
||||
!else
|
||||
# Locate Tcl sources
|
||||
!if [echo _RULESDIR = \> nmakehlp.out] \
|
||||
|| [nmakehlp -L generic\tcl.h >> nmakehlp.out]
|
||||
_RULESDIR = ..\..\tcl
|
||||
!else
|
||||
!include nmakehlp.out
|
||||
!endif
|
||||
|
||||
!endif # defined(INSTALLDIR)....
|
||||
|
||||
!endif # ifndef TCLDIR
|
||||
|
||||
# Now look for the targets.vc file under the Tcl root. Note we check this
|
||||
# file and not rules.vc because the latter also exists on older systems.
|
||||
!if exist("$(_RULESDIR)\lib\nmake\targets.vc") # Building against installed Tcl
|
||||
_RULESDIR = $(_RULESDIR)\lib\nmake
|
||||
!elseif exist("$(_RULESDIR)\win\targets.vc") # Building against Tcl sources
|
||||
_RULESDIR = $(_RULESDIR)\win
|
||||
!else
|
||||
# If we have not located Tcl's targets file, most likely we are compiling
|
||||
# against an older version of Tcl and so must use our own support files.
|
||||
_RULESDIR = .
|
||||
!endif
|
||||
|
||||
!if "$(_RULESDIR)" != "."
|
||||
# Potentially using Tcl's support files. If this extension has its own
|
||||
# nmake support files, need to compare the versions and pick newer.
|
||||
|
||||
!if exist("rules.vc") # The extension has its own copy
|
||||
|
||||
!if [echo TCL_RULES_MAJOR = \> versions.vc] \
|
||||
&& [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MAJOR >> versions.vc]
|
||||
!endif
|
||||
!if [echo TCL_RULES_MINOR = \>> versions.vc] \
|
||||
&& [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MINOR >> versions.vc]
|
||||
!endif
|
||||
|
||||
!if [echo OUR_RULES_MAJOR = \>> versions.vc] \
|
||||
&& [nmakehlp -V "rules.vc" RULES_VERSION_MAJOR >> versions.vc]
|
||||
!endif
|
||||
!if [echo OUR_RULES_MINOR = \>> versions.vc] \
|
||||
&& [nmakehlp -V "rules.vc" RULES_VERSION_MINOR >> versions.vc]
|
||||
!endif
|
||||
!include versions.vc
|
||||
# We have a newer version of the support files, use them
|
||||
!if ($(TCL_RULES_MAJOR) != $(OUR_RULES_MAJOR)) || ($(TCL_RULES_MINOR) < $(OUR_RULES_MINOR))
|
||||
_RULESDIR = .
|
||||
!endif
|
||||
|
||||
!endif # if exist("rules.vc")
|
||||
|
||||
!endif # if $(_RULESDIR) != "."
|
||||
|
||||
# Let rules.vc know what copy of nmakehlp.c to use.
|
||||
NMAKEHLPC = $(_RULESDIR)\nmakehlp.c
|
||||
|
||||
# Get rid of our internal defines before calling rules.vc
|
||||
!undef TCL_RULES_MAJOR
|
||||
!undef TCL_RULES_MINOR
|
||||
!undef OUR_RULES_MAJOR
|
||||
!undef OUR_RULES_MINOR
|
||||
|
||||
!if exist("$(_RULESDIR)\rules.vc")
|
||||
!message *** Using $(_RULESDIR)\rules.vc
|
||||
!include "$(_RULESDIR)\rules.vc"
|
||||
!else
|
||||
!error *** Could not locate rules.vc in $(_RULESDIR)
|
||||
!endif
|
||||
|
||||
!endif # _RULES_EXT_VC
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,98 @@
|
||||
#------------------------------------------------------------- -*- makefile -*-
|
||||
# targets.vc --
|
||||
#
|
||||
# Part of the nmake based build system for Tcl and its extensions.
|
||||
# This file defines some standard targets for the convenience of extensions
|
||||
# and can be optionally included by the extension makefile.
|
||||
# See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for docs.
|
||||
|
||||
$(PROJECT): setup pkgindex $(PRJLIB)
|
||||
|
||||
!ifdef PRJ_STUBOBJS
|
||||
$(PROJECT): $(PRJSTUBLIB)
|
||||
$(PRJSTUBLIB): $(PRJ_STUBOBJS)
|
||||
$(LIBCMD) $**
|
||||
|
||||
$(PRJ_STUBOBJS):
|
||||
$(CCSTUBSCMD) %s
|
||||
!endif # PRJ_STUBOBJS
|
||||
|
||||
!ifdef PRJ_MANIFEST
|
||||
$(PROJECT): $(PRJLIB).manifest
|
||||
$(PRJLIB).manifest: $(PRJ_MANIFEST)
|
||||
@nmakehlp -s << $** >$@
|
||||
@MACHINE@ $(MACHINE:IX86=X86)
|
||||
<<
|
||||
!endif
|
||||
|
||||
!if "$(PROJECT)" != "tcl" && "$(PROJECT)" != "tk"
|
||||
$(PRJLIB): $(PRJ_OBJS) $(RESFILE)
|
||||
!if $(STATIC_BUILD)
|
||||
$(LIBCMD) $**
|
||||
!else
|
||||
$(DLLCMD) $**
|
||||
$(_VC_MANIFEST_EMBED_DLL)
|
||||
!endif
|
||||
-@del $*.exp
|
||||
!endif
|
||||
|
||||
!if "$(PRJ_HEADERS)" != "" && "$(PRJ_OBJS)" != ""
|
||||
$(PRJ_OBJS): $(PRJ_HEADERS)
|
||||
!endif
|
||||
|
||||
# If parent makefile has defined stub objects, add their installation
|
||||
# to the default install
|
||||
!if "$(PRJ_STUBOBJS)" != ""
|
||||
default-install: default-install-stubs
|
||||
!endif
|
||||
|
||||
# Unlike the other default targets, these cannot be in rules.vc because
|
||||
# the executed command depends on existence of macro PRJ_HEADERS_PUBLIC
|
||||
# that the parent makefile will not define until after including rules-ext.vc
|
||||
!if "$(PRJ_HEADERS_PUBLIC)" != ""
|
||||
default-install: default-install-headers
|
||||
default-install-headers:
|
||||
@echo Installing headers to '$(INCLUDE_INSTALL_DIR)'
|
||||
@for %f in ($(PRJ_HEADERS_PUBLIC)) do @$(COPY) %f "$(INCLUDE_INSTALL_DIR)"
|
||||
!endif
|
||||
|
||||
!if "$(DISABLE_STANDARD_TARGETS)" == ""
|
||||
DISABLE_STANDARD_TARGETS = 0
|
||||
!endif
|
||||
|
||||
!if "$(DISABLE_TARGET_setup)" == ""
|
||||
DISABLE_TARGET_setup = 0
|
||||
!endif
|
||||
!if "$(DISABLE_TARGET_install)" == ""
|
||||
DISABLE_TARGET_install = 0
|
||||
!endif
|
||||
!if "$(DISABLE_TARGET_clean)" == ""
|
||||
DISABLE_TARGET_clean = 0
|
||||
!endif
|
||||
!if "$(DISABLE_TARGET_test)" == ""
|
||||
DISABLE_TARGET_test = 0
|
||||
!endif
|
||||
!if "$(DISABLE_TARGET_shell)" == ""
|
||||
DISABLE_TARGET_shell = 0
|
||||
!endif
|
||||
|
||||
!if !$(DISABLE_STANDARD_TARGETS)
|
||||
!if !$(DISABLE_TARGET_setup)
|
||||
setup: default-setup
|
||||
!endif
|
||||
!if !$(DISABLE_TARGET_install)
|
||||
install: default-install
|
||||
!endif
|
||||
!if !$(DISABLE_TARGET_clean)
|
||||
clean: default-clean
|
||||
realclean: hose
|
||||
hose: default-hose
|
||||
distclean: realclean default-distclean
|
||||
!endif
|
||||
!if !$(DISABLE_TARGET_test)
|
||||
test: default-test
|
||||
!endif
|
||||
!if !$(DISABLE_TARGET_shell)
|
||||
shell: default-shell
|
||||
!endif
|
||||
!endif # DISABLE_STANDARD_TARGETS
|
||||
+44
-118
@@ -14,9 +14,7 @@ build infrastructure. It is not an [Autosetup][] reference.
|
||||
- Symbolic Names of Feature Flags
|
||||
- Do Not Update Global Shared State
|
||||
- [Updating Autosetup](#updating)
|
||||
- ***[Patching Autosetup for Project-local changes](#patching)***
|
||||
- [Branch-specific Customization](#branch-customization)
|
||||
|
||||
- [Patching Autosetup for Project-local changes](#patching)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
@@ -44,13 +42,12 @@ following files:
|
||||
(e.g. Fossil), and personal projects of SQLite's developers. It is
|
||||
essentially an amalgamation of a decade's worth of autosetup-related
|
||||
utility code.
|
||||
- [auto.def][]: the primary driver for the `./configure` process.
|
||||
When we talk about "the configure script," we're referring to
|
||||
this file.
|
||||
- [sqlite-config.tcl][]: utility code which is too project-specific
|
||||
for `proj.tcl`. We split this out of `auto.def` so that it can be
|
||||
used by both `auto.def` and...
|
||||
- [auto.def][]: the primary driver for the `./configure` process.
|
||||
When we talk about "the configure script," we're technically
|
||||
referring to this file, though it actually contains very little
|
||||
of the TCL code.
|
||||
- [autoconf/auto.def][]: the main driver script for the "autoconf"
|
||||
bundle's configure script. It is essentially a slightly trimmed-down
|
||||
version of the main `auto.def` file. The `autoconf` dir was ported
|
||||
@@ -64,11 +61,11 @@ Autosetup API Tips
|
||||
|
||||
This section briefly covers only APIs which are frequently useful in
|
||||
day-to-day maintenance and might not be immediately recognized as such
|
||||
from a casual perusal of the relevant TCL files. The complete docs of
|
||||
those with `proj-` prefix can be found in [proj.tcl][] and those with
|
||||
an `sqlite-` prefix are in [sqlite-config.tcl][]. The others are part
|
||||
of Autosetup's core packages and are scattered around [the TCL files
|
||||
in ./autosetup](/dir/autosetup).
|
||||
obvious from a casual perusal of the relevant TCL files. The complete
|
||||
docs of those with `proj-` prefix can be found in [proj.tcl][] and
|
||||
those with an `sqlite-` prefix are in [sqlite-config.tcl][]. The
|
||||
others are scattered around [the TCL files in
|
||||
./autosetup](/dir/autosetup).
|
||||
|
||||
In (mostly) alphabetical order:
|
||||
|
||||
@@ -86,14 +83,19 @@ In (mostly) alphabetical order:
|
||||
Works like `get-env` but will, if that function finds no match,
|
||||
look for a file named `./.env-$VAR` and, if found, return its
|
||||
trimmed contents. This can be used, e.g., to set a developer's
|
||||
local preferences for the default `CFLAGS`.\
|
||||
Tip: adding `-O0` to `.env-CFLAGS` reduces rebuild times
|
||||
considerably at the cost of performance in `make devtest` and the
|
||||
like.
|
||||
local preferences for the default `CFLAGS`.
|
||||
|
||||
- **`define-for-opt flag defineName ?checkingMsg? ?yesVal=1? ?noVal=0?`**\
|
||||
`[define $defineName]` to either `$yesVal` or `$noVal`, depending on
|
||||
whether `--$flag` is truthy or not. `$checkingMsg` is a
|
||||
human-readable description of the check being made, e.g. "enable foo?"
|
||||
If no `checkingMsg` is provided, the operation is silent.\
|
||||
Potential TODO: change the final two args to `-yes` and `-no`
|
||||
flags. They're rarely needed, though: search [auto.def][] for
|
||||
`TSTRNNR_OPTS` for an example of where they are used.
|
||||
|
||||
- **`proj-fatal msg`**\
|
||||
Emits `$msg` to stderr and exits with non-zero. Its differences from
|
||||
autosetup's `user-error` are purely cosmetic.
|
||||
Emits `$msg` to stderr and exits with non-zero.
|
||||
|
||||
- **`proj-if-opt-truthy flag thenScript ?elseScript?`**\
|
||||
Evals `thenScript` if the given `--flag` is truthy, else it
|
||||
@@ -115,10 +117,7 @@ In (mostly) alphabetical order:
|
||||
else 0. This distinction can be used to determine, e.g., whether
|
||||
`--with-readline` was provided or whether we're searching for
|
||||
readline by default. In the former case, failure to find it should
|
||||
be treated as fatal, where in the latter case it's not.\
|
||||
Unlike most functions which deal with `--flags`, this one does not
|
||||
validate that `$FLAG` is a registered flag so will not fail fatally
|
||||
if `$FLAG` is not registered as an Autosetup option.
|
||||
be treated as fatal, where in the latter case it's not.
|
||||
|
||||
- **`proj-val-truthy value`**\
|
||||
Returns 1 if `$value` is "truthy," See `proj-opt-truthy` for the definition
|
||||
@@ -140,15 +139,6 @@ In (mostly) alphabetical order:
|
||||
The shell-specific counterpart of `sqlite-add-feature-flag` which
|
||||
only adds the given flag(s) to the CLI-shell-specific CFLAGS.
|
||||
|
||||
- **`sqlite-configure BUILD-NAME {script}`**\
|
||||
This is where all configure `--flags` are defined for all known
|
||||
build modes ("canonical" or "autoconf"). After processing all flags,
|
||||
this function runs `$script`, which contains the build-mode-specific
|
||||
configuration bits, and then runs any finalization bits which are
|
||||
common to all build modes. The `auto.def` files are intended to contain
|
||||
exactly two commands:
|
||||
`use sqlite-config; sqlite-configure BUILD-NAME {script}`
|
||||
|
||||
- **`user-notice msg`**\
|
||||
Queues `$msg` to be sent to stderr, but does not emit it until
|
||||
either `show-notices` is called or the next time autosetup would
|
||||
@@ -162,18 +152,13 @@ In (mostly) alphabetical order:
|
||||
Ensuring TCL Compatibility
|
||||
========================================================================
|
||||
|
||||
One of the significant benefits of using Autosetup is that (A) this
|
||||
project uses many TCL scripts in the build process and (B) Autosetup
|
||||
comes with a TCL interpreter named [JimTCL][].
|
||||
|
||||
It is important that any TCL files used by the configure process and
|
||||
makefiles remain compatible with both [JimTCL][] and the canonical
|
||||
TCL. Though JimTCL has outstanding compatibility with canonical TCL,
|
||||
it does have a few corners with incompatibilities, e.g. regular
|
||||
expressions. If a script runs in JimTCL without using any
|
||||
JimTCL-specific features, then it's a certainty that it will run in
|
||||
canonical TCL as well. The opposite, however, is not _always_ the
|
||||
case.
|
||||
It is important that any TCL files used by the configure process
|
||||
remain compatible with both [JimTCL][] and the canonical TCL. Though
|
||||
JimTCL has outstanding compatibility with canonical TCL, it does have
|
||||
a few corners with incompatibilities, e.g. regular expressions. If a
|
||||
script runs in JimTCL without using any JimTCL-specific features, then
|
||||
it's a certainty that it will run in canonical TCL as well. The
|
||||
opposite, however, is not _always_ the case.
|
||||
|
||||
When [`./configure`](/file/configure) is run, it goes through a
|
||||
bootstrapping process to find a suitable TCL with which to run the
|
||||
@@ -202,17 +187,14 @@ compatibility across TCL implementations:
|
||||
before looking for a system-level `tclsh`. Be aware, though, that
|
||||
`make distclean` will remove that file.
|
||||
|
||||
**Note that `./jimsh0` is distinctly different from the `./jimsh`**
|
||||
which gets built for code-generation purposes. The latter requires
|
||||
**Note that `jimsh0` is distinctly different from the `jimsh`** which
|
||||
gets built for code-generation purposes. The latter requires
|
||||
non-default build flags to enable features which are
|
||||
platform-dependent, most notably to make its `[file normalize]` work.
|
||||
This means, for example, that the configure script and its utility
|
||||
APIs must not use `[file normalize]`, but autosetup provides a
|
||||
TCL-only implementation of `[file-normalize]` (note the dash) for
|
||||
portable use in the configure script. Contrariwise, code-generation
|
||||
scripts invoked via `make` may use `[file normalize]`, as they'll use
|
||||
`./jimsh` or `tclsh` instead of `./jimsh0`.
|
||||
|
||||
portable use in the configure script.
|
||||
|
||||
Known TCL Incompatibilities
|
||||
------------------------------------------------------------------------
|
||||
@@ -239,7 +221,6 @@ A summary of known incompatibilities in JimTCL
|
||||
- `regsub` does not support the `\y` flag. A workaround is demonstrated
|
||||
in [](/info/c2e5dd791cce3ec4).
|
||||
|
||||
|
||||
<a name="conventions"></a>
|
||||
Design Conventions
|
||||
========================================================================
|
||||
@@ -266,9 +247,8 @@ dots are not permitted.
|
||||
The `X.y` convention is used in the makefiles primarily because the
|
||||
person who did the initial port finds that considerably easier on the
|
||||
eyes and fingers. In practice, the `X_Y` form of such exports is used
|
||||
exactly once in [Makefile.in][], where it's translated from `@X_Y@`
|
||||
into into `X.y` form for consumption by [Makefile.in][] and
|
||||
[main.mk][]. For example:
|
||||
exactly once in [Makefile.in][], where it's translated into into `X.y`
|
||||
form for consumption by [Makefile.in][] and [main.mk][]. For example:
|
||||
|
||||
>
|
||||
```
|
||||
@@ -285,9 +265,9 @@ of taste, for which there is no accounting.)
|
||||
Do Not Update Global Shared State
|
||||
------------------------------------------------------------------------
|
||||
|
||||
In both the legacy Autotools-driven build and common Autosetup usage,
|
||||
feature tests performed by the configure script may amend global flags
|
||||
such as `LIBS`, `LDFLAGS`, and `CFLAGS`[^as-cflags]. That's
|
||||
In both the legacy Autotools-driven build and in common Autosetup
|
||||
usage, feature tests performed by the configure script may amend
|
||||
global flags such as `LIBS`, `LDFLAGS`, and `CFLAGS`[^as-cflags]. That's
|
||||
appropriate for a makefile which builds a single deliverable, but less
|
||||
so for makefiles which produce multiple deliverables. Drawbacks of
|
||||
that approach include:
|
||||
@@ -295,8 +275,8 @@ that approach include:
|
||||
- It's unlikely that every single deliverable will require the same
|
||||
core set of those flags.
|
||||
- It can be difficult to determine the origin of any given change to
|
||||
that global state because those changes are hidden behind voodoo
|
||||
performed outside the immediate visibility of the configure script's
|
||||
that global state because those changes are hidden behind voodoo performed
|
||||
outside the immediate visibility of the configure script's
|
||||
maintainer.
|
||||
- It can force the maintainers of the configure script to place tests
|
||||
in a specific order so that the resulting flags get applied at
|
||||
@@ -377,71 +357,17 @@ Patching Autosetup for Project-local Changes
|
||||
|
||||
Autosetup reserves the flag name **`--debug`** for its own purposes,
|
||||
and its own special handling of `--enable-...` flags makes `--debug`
|
||||
an alias for `--enable-debug`. As this project has a long history of
|
||||
using `--enable-debug`, we patch autosetup to use the name
|
||||
`--autosetup-debug` in place of `--debug`. That requires (as of this
|
||||
writing) four small edits in
|
||||
[/autosetup/autosetup](/file/autosetup/autosetup), as demonstrated in
|
||||
[check-in 3296c8d3](/info/3296c8d3).
|
||||
an alias for `--enable-debug`. As we have a long history of using
|
||||
`--enable-debug` for this project's own purposes, we patch autosetup
|
||||
to use the name `--autosetup-debug` in place of `--debug`. That
|
||||
requires (as of this writing) four small edits in
|
||||
[](/file/autosetup/autosetup), as demonstrated in [check-in
|
||||
3296c8d3](/info/3296c8d3).
|
||||
|
||||
If autosetup is upgraded and this patch is _not_ applied the invoking
|
||||
`./configure` will fail loudly because of the declaration of the
|
||||
`debug` flag in `auto.def` - duplicated flags are not permitted.
|
||||
|
||||
<a name="branch-customization"></a>
|
||||
Branch-specific Customization
|
||||
========================================================================
|
||||
|
||||
Certain vendor-specific branches require slight configure script
|
||||
customization. Rather than editing `sqlite-config.tcl` for this,
|
||||
which frequently leads to merge conflicts, the following approach
|
||||
is recommended:
|
||||
|
||||
In the vendor-specific branch, create a file named
|
||||
`autosetup/sqlite-custom.tcl`.
|
||||
|
||||
That file should contain the following content...
|
||||
|
||||
If flag customization is required, add:
|
||||
|
||||
>
|
||||
```
|
||||
proc sqlite-custom-flags {} {
|
||||
# If any existing --flags require different default values
|
||||
# then call:
|
||||
options-defaults {
|
||||
flag-name new-default-value
|
||||
...
|
||||
}
|
||||
# ^^^ That will replace the default value but will not update
|
||||
# the --help text, which may lead to some confusion:
|
||||
# https://github.com/msteveb/autosetup/issues/77
|
||||
|
||||
return {
|
||||
{*} {
|
||||
new-flag-name => {Help text}
|
||||
...
|
||||
}
|
||||
}; #see below
|
||||
}
|
||||
```
|
||||
|
||||
That function must return either an empty string or a list in the form
|
||||
used internally by [sqlite-config.tcl][]'s `sqlite-configure`.
|
||||
|
||||
Next, define:
|
||||
|
||||
>
|
||||
```
|
||||
proc sqlite-custom-handle-flags {} {
|
||||
... do any custom flag handling here ...
|
||||
}
|
||||
```
|
||||
|
||||
That function, if defined, will be called relatively late in the
|
||||
configure process, before any filtered files are generated but after
|
||||
all other significant processing.
|
||||
|
||||
|
||||
[Autosetup]: https://msteveb.github.io/autosetup/
|
||||
[auto.def]: /file/auto.def
|
||||
|
||||
+11
-19
@@ -406,8 +406,8 @@ proc options-add {opts} {
|
||||
# Find the corresponding value in the user options
|
||||
# and set the default if necessary
|
||||
if {[string match "-*" $opt]} {
|
||||
# We no longer support documentation-only options, like "-C <dir>"
|
||||
autosetup-error "Option $opt is not supported"
|
||||
# This is a documentation-only option, like "-C <dir>"
|
||||
set opthelp $opt
|
||||
} elseif {$colon eq ""} {
|
||||
# Boolean option
|
||||
lappend autosetup(options) $name
|
||||
@@ -1611,7 +1611,7 @@ proc autosetup_output_block {type lines} {
|
||||
# Generate a command reference from inline documentation
|
||||
proc automf_command_reference {} {
|
||||
lappend files $::autosetup(prog)
|
||||
lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/{*/*.tcl,*.tcl}]]
|
||||
lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]]
|
||||
|
||||
# We want to process all non-module files before module files
|
||||
# and then modules in alphabetical order.
|
||||
@@ -1634,8 +1634,8 @@ proc automf_command_reference {} {
|
||||
|
||||
if {[regexp {^#.*@section (.*)$} $line -> section]} {
|
||||
lappend doc($current) [list section $section]
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
# Find embedded module names
|
||||
if {[regexp {^#.*@module ([^ ]*)} $line -> modulename]} {
|
||||
@@ -1651,7 +1651,7 @@ proc automf_command_reference {} {
|
||||
if {$cmd eq "synopsis:"} {
|
||||
set current $modulename
|
||||
lappend doc($current) [list section "Module: $modulename"]
|
||||
} else {
|
||||
} else {
|
||||
lappend doc($current) [list subsection $cmd]
|
||||
}
|
||||
|
||||
@@ -2088,12 +2088,8 @@ if {$autosetup(iswin)} {
|
||||
proc split-path {} {
|
||||
split [getenv PATH .] :
|
||||
}
|
||||
# Check for an executable file
|
||||
proc file-isexec {exec} {
|
||||
if {[file executable $exec] && [file isfile $exec]} {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
file executable $exec
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2124,7 +2120,7 @@ if {$autosetup(istcl)} {
|
||||
set frame [info frame -$i]
|
||||
if {[dict exists $frame file]} {
|
||||
# We don't need proc, so use ""
|
||||
lappend stacktrace "" [dict get $frame file] [dict get $frame line] ""
|
||||
lappend stacktrace "" [dict get $frame file] [dict get $frame line]
|
||||
}
|
||||
}
|
||||
return $stacktrace
|
||||
@@ -2181,12 +2177,8 @@ proc error-location {msg} {
|
||||
if {$::autosetup(debug)} {
|
||||
return -code error $msg
|
||||
}
|
||||
set vars {p f l cmd}
|
||||
if {!$::autosetup(istcl) && ![dict exists $::tcl_platform stackFormat]} {
|
||||
# Older versions of Jim had a 3 element stacktrace
|
||||
set vars {p f l}
|
||||
}
|
||||
foreach $vars [stacktrace] {
|
||||
# Search back through the stack trace for the first error in a .def file
|
||||
foreach {p f l} [stacktrace] {
|
||||
if {[string match *.def $f]} {
|
||||
return "[relative-path $f]:$l: Error: $msg"
|
||||
}
|
||||
@@ -2538,7 +2530,7 @@ if {[catch {main $argv} msg opts] == 1} {
|
||||
show-notices
|
||||
autosetup-full-error [error-dump $msg $opts $autosetup(debug)]
|
||||
if {!$autosetup(debug)} {
|
||||
puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
|
||||
puts stderr "Try: '[file tail $autosetup(exe)] --autosetup-debug' for a full stack trace"
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ for tclsh in ./jimsh0 $autosetup_tclsh jimsh tclsh tclsh8.5 tclsh8.6 tclsh8.7; d
|
||||
done
|
||||
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
|
||||
for cc in ${CC_FOR_BUILD:-cc} gcc; do
|
||||
{ $cc -o jimsh0 "$d/jimsh0.c"; } 2>/dev/null >/dev/null || continue
|
||||
{ $cc -o jimsh0 "$d/jimsh0.c"; } >/dev/null 2>&1 || continue
|
||||
./jimsh0 "$d/${1-autosetup-test-tclsh}" && exit 0
|
||||
done
|
||||
echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc."
|
||||
|
||||
@@ -89,15 +89,13 @@ switch -glob -- [get-define host] {
|
||||
define SH_SOPREFIX -Wl,-h,
|
||||
}
|
||||
}
|
||||
*-*-hpux* {
|
||||
define SHOBJ_CFLAGS +z
|
||||
*-*-hpux {
|
||||
# XXX: These haven't been tested
|
||||
define SHOBJ_CFLAGS "+O3 +z"
|
||||
define SHOBJ_LDFLAGS -b
|
||||
define SH_CFLAGS +z
|
||||
define SH_LDFLAGS -b
|
||||
define SH_LINKFLAGS -Wl,+s
|
||||
define SH_LINKRPATH "-Wl,+b -Wl,%s"
|
||||
define SH_SOPREFIX -Wl,+h,
|
||||
define STRIPLIBFLAGS -Wl,-s
|
||||
define LD_LIBRARY_PATH SHLIB_PATH
|
||||
}
|
||||
*-*-haiku {
|
||||
define SHOBJ_CFLAGS ""
|
||||
|
||||
+12
-8
@@ -1252,14 +1252,6 @@ int Jim_OpenForRead(const char *filename);
|
||||
|
||||
#endif
|
||||
|
||||
# ifndef MAXPATHLEN
|
||||
# ifdef PATH_MAX
|
||||
# define MAXPATHLEN PATH_MAX
|
||||
# else
|
||||
# define MAXPATHLEN JIM_PATH_LEN
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
||||
int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb);
|
||||
|
||||
@@ -2096,6 +2088,10 @@ enum wbuftype {
|
||||
#define UNIX_SOCKETS 0
|
||||
#endif
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN JIM_PATH_LEN
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4177,6 +4173,14 @@ int Jim_regexpInit(Jim_Interp *interp)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
# ifndef MAXPATHLEN
|
||||
# ifdef PATH_MAX
|
||||
# define MAXPATHLEN PATH_MAX
|
||||
# else
|
||||
# define MAXPATHLEN JIM_PATH_LEN
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER)
|
||||
#define ISWINDOWS 1
|
||||
|
||||
|
||||
+211
-1483
File diff suppressed because it is too large
Load Diff
+320
-787
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
The *.tcl files in this directory are part of the SQLite's "autoconf"
|
||||
bundle which are specific to the TEA(-ish) build. During the tarball
|
||||
generation process, they are copied into <TOP>/autoconf/autosetup/teaish
|
||||
(which itself is created as part of that process).
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,214 +0,0 @@
|
||||
########################################################################
|
||||
# 2025 April 7
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# * May you do good and not evil.
|
||||
# * May you find forgiveness for yourself and forgive others.
|
||||
# * May you share freely, never taking more than you give.
|
||||
#
|
||||
########################################################################
|
||||
# ----- @module feature-tests.tcl -----
|
||||
# @section TEA-ish collection of feature tests.
|
||||
#
|
||||
# Functions in this file with a prefix of teaish__ are
|
||||
# private/internal APIs. Those with a prefix of teaish- are
|
||||
# public APIs.
|
||||
|
||||
|
||||
# @teaish-check-libz
|
||||
#
|
||||
# Checks for zlib.h and the function deflate in libz. If found,
|
||||
# prepends -lz to the extension's ldflags and returns 1, else returns
|
||||
# 0. It also defines LDFLAGS_LIBZ to the libs flag.
|
||||
#
|
||||
proc teaish-check-libz {} {
|
||||
teaish-check-cached "Checking for libz" {
|
||||
set rc 0
|
||||
if {[msg-quiet cc-check-includes zlib.h] && [msg-quiet proj-check-function-in-lib deflate z]} {
|
||||
teaish-ldflags-prepend [define LDFLAGS_LIBZ [get-define lib_deflate]]
|
||||
undefine lib_deflate
|
||||
incr rc
|
||||
}
|
||||
expr $rc
|
||||
}
|
||||
}
|
||||
|
||||
# @teaish-check-librt ?funclist?
|
||||
#
|
||||
# Checks whether -lrt is needed for any of the given functions. If
|
||||
# so, appends -lrt via [teaish-ldflags-prepend] and returns 1, else
|
||||
# returns 0. It also defines LDFLAGS_LIBRT to the libs flag or an
|
||||
# empty string.
|
||||
#
|
||||
# Some systems (ex: SunOS) require -lrt in order to use nanosleep.
|
||||
#
|
||||
proc teaish-check-librt {{funclist {fdatasync nanosleep}}} {
|
||||
teaish-check-cached -nostatus "Checking whether ($funclist) need librt" {
|
||||
define LDFLAGS_LIBRT ""
|
||||
foreach func $funclist {
|
||||
if {[msg-quiet proj-check-function-in-lib $func rt]} {
|
||||
set ldrt [get-define lib_${func}]
|
||||
undefine lib_${func}
|
||||
if {"" ne $ldrt} {
|
||||
teaish-ldflags-prepend -r [define LDFLAGS_LIBRT $ldrt]
|
||||
msg-result $ldrt
|
||||
return 1
|
||||
} else {
|
||||
msg-result "no lib needed"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
msg-result "not found"
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
# @teaish-check-stdint
|
||||
#
|
||||
# A thin proxy for [cc-with] which checks for <stdint.h> and the
|
||||
# various fixed-size int types it declares. It defines HAVE_STDINT_T
|
||||
# to 0 or 1 and (if it's 1) defines HAVE_XYZ_T for each XYZ int type
|
||||
# to 0 or 1, depending on whether its available.
|
||||
proc teaish-check-stdint {} {
|
||||
teaish-check-cached "Checking for stdint.h" {
|
||||
msg-quiet cc-with {-includes stdint.h} \
|
||||
{cc-check-types int8_t int16_t int32_t int64_t intptr_t \
|
||||
uint8_t uint16_t uint32_t uint64_t uintptr_t}
|
||||
}
|
||||
}
|
||||
|
||||
# @teaish-is-mingw
|
||||
#
|
||||
# Returns 1 if building for mingw, else 0.
|
||||
proc teaish-is-mingw {} {
|
||||
return [expr {
|
||||
[string match *mingw* [get-define host]] &&
|
||||
![file exists /dev/null]
|
||||
}]
|
||||
}
|
||||
|
||||
# @teaish-check-libdl
|
||||
#
|
||||
# Checks for whether dlopen() can be found and whether it requires
|
||||
# -ldl for linking. If found, returns 1, defines LDFLAGS_DLOPEN to the
|
||||
# linker flags (if any), and passes those flags to
|
||||
# teaish-ldflags-prepend. It unconditionally defines HAVE_DLOPEN to 0
|
||||
# or 1 (the its return result value).
|
||||
proc teaish-check-dlopen {} {
|
||||
teaish-check-cached -nostatus "Checking for dlopen()" {
|
||||
set rc 0
|
||||
set lfl ""
|
||||
if {[cc-with {-includes dlfcn.h} {
|
||||
cctest -link 1 -declare "extern char* dlerror(void);" -code "dlerror();"}]} {
|
||||
msg-result "-ldl not needed"
|
||||
incr rc
|
||||
} elseif {[cc-check-includes dlfcn.h]} {
|
||||
incr rc
|
||||
if {[cc-check-function-in-lib dlopen dl]} {
|
||||
set lfl [get-define lib_dlopen]
|
||||
undefine lib_dlopen
|
||||
msg-result " dlopen() needs $lfl"
|
||||
} else {
|
||||
msg-result " - dlopen() not found in libdl. Assuming dlopen() is built-in."
|
||||
}
|
||||
} else {
|
||||
msg-result "not found"
|
||||
}
|
||||
teaish-ldflags-prepend [define LDFLAGS_DLOPEN $lfl]
|
||||
define HAVE_DLOPEN $rc
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# @teaish-check-libmath
|
||||
#
|
||||
# Handles the --enable-math flag. Returns 1 if found, else 0.
|
||||
# If found, it prepends -lm (if needed) to the linker flags.
|
||||
proc teaish-check-libmath {} {
|
||||
teaish-check-cached "Checking for libc math library" {
|
||||
set lfl ""
|
||||
set rc 0
|
||||
if {[msg-quiet proj-check-function-in-lib ceil m]} {
|
||||
incr rc
|
||||
set lfl [get-define lib_ceil]
|
||||
undefine lib_ceil
|
||||
teaish-ldflags-prepend $lfl
|
||||
msg-checking "$lfl "
|
||||
}
|
||||
define LDFLAGS_LIBMATH $lfl
|
||||
expr $rc
|
||||
}
|
||||
}
|
||||
|
||||
# @teaish-import-features ?-flags? feature-names...
|
||||
#
|
||||
# For each $name in feature-names... it invokes:
|
||||
#
|
||||
# use teaish/feature/$name
|
||||
#
|
||||
# to load TEAISH_AUTOSETUP_DIR/feature/$name.tcl
|
||||
#
|
||||
# By default, if a proc named teaish-check-${name}-options is defined
|
||||
# after sourcing a file, it is called and its result is passed to
|
||||
# proj-append-options. This can be suppressed with the -no-options
|
||||
# flag.
|
||||
#
|
||||
# Flags:
|
||||
#
|
||||
# -no-options: disables the automatic running of
|
||||
# teaish-check-NAME-options,
|
||||
#
|
||||
# -run: if the function teaish-check-NAME exists after importing
|
||||
# then it is called. This flag must not be used when calling this
|
||||
# function from teaish-options. This trumps both -pre and -post.
|
||||
#
|
||||
# -pre: if the function teaish-check-NAME exists after importing
|
||||
# then it is passed to [teaish-checks-queue -pre].
|
||||
#
|
||||
# -post: works like -pre but instead uses[teaish-checks-queue -post].
|
||||
proc teaish-import-features {args} {
|
||||
set pk ""
|
||||
set doOpt 1
|
||||
proj-parse-simple-flags args flags {
|
||||
-no-options 0 {set doOpt 0}
|
||||
-run 0 {expr 1}
|
||||
-pre 0 {set pk -pre}
|
||||
-post 0 {set pk -post}
|
||||
}
|
||||
#
|
||||
# TODO: never import the same module more than once. The "use"
|
||||
# command is smart enough to not do that but we would need to
|
||||
# remember whether or not any teaish-check-${arg}* procs have been
|
||||
# called before, and skip them.
|
||||
#
|
||||
if {$flags(-run) && "" ne $pk} {
|
||||
proj-error "Cannot use both -run and $pk" \
|
||||
" (called from [proj-scope 1])"
|
||||
}
|
||||
|
||||
foreach arg $args {
|
||||
uplevel "use teaish/feature/$arg"
|
||||
if {$doOpt} {
|
||||
set n "teaish-check-${arg}-options"
|
||||
if {[llength [info proc $n]] > 0} {
|
||||
if {"" ne [set x [$n]]} {
|
||||
options-add $x
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$flags(-run)} {
|
||||
set n "teaish-check-${arg}"
|
||||
if {[llength [info proc $n]] > 0} {
|
||||
uplevel 1 $n
|
||||
}
|
||||
} elseif {"" ne $pk} {
|
||||
set n "teaish-check-${arg}"
|
||||
if {[llength [info proc $n]] > 0} {
|
||||
teaish-checks-queue {*}$pk $n
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
########################################################################
|
||||
# 2025 April 5
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# * May you do good and not evil.
|
||||
# * May you find forgiveness for yourself and forgive others.
|
||||
# * May you share freely, never taking more than you give.
|
||||
#
|
||||
########################################################################
|
||||
#
|
||||
# Helper routines for running tests on teaish extensions
|
||||
#
|
||||
########################################################################
|
||||
# ----- @module teaish/tester.tcl -----
|
||||
#
|
||||
# @section TEA-ish Testing APIs.
|
||||
#
|
||||
# Though these are part of the autosup dir hierarchy, they are not
|
||||
# intended to be run from autosetup code. Rather, they're for use
|
||||
# with/via teaish.tester.tcl and target canonical Tcl only, not JimTcl
|
||||
# (which the autosetup pieces do target).
|
||||
|
||||
#
|
||||
# @test-current-scope ?lvl?
|
||||
#
|
||||
# Returns the name of the _calling_ proc from ($lvl + 1) levels up the
|
||||
# call stack (where the caller's level will be 1 up from _this_
|
||||
# call). If $lvl would resolve to global scope "global scope" is
|
||||
# returned and if it would be negative then a string indicating such
|
||||
# is returned (as opposed to throwing an error).
|
||||
#
|
||||
proc test-current-scope {{lvl 0}} {
|
||||
#uplevel [expr {$lvl + 1}] {lindex [info level 0] 0}
|
||||
set ilvl [info level]
|
||||
set offset [expr {$ilvl - $lvl - 1}]
|
||||
if { $offset < 0} {
|
||||
return "invalid scope ($offset)"
|
||||
} elseif { $offset == 0} {
|
||||
return "global scope"
|
||||
} else {
|
||||
return [lindex [info level $offset] 0]
|
||||
}
|
||||
}
|
||||
|
||||
# @test-msg
|
||||
#
|
||||
# Emits all arugments to stdout.
|
||||
#
|
||||
proc test-msg {args} {
|
||||
puts "$args"
|
||||
}
|
||||
|
||||
# @test-warn
|
||||
#
|
||||
# Emits all arugments to stderr.
|
||||
#
|
||||
proc test-warn {args} {
|
||||
puts stderr "WARNING: $args"
|
||||
}
|
||||
|
||||
#
|
||||
# @test-error msg
|
||||
#
|
||||
# Triggers a test-failed error with a string describing the calling
|
||||
# scope and the provided message.
|
||||
#
|
||||
proc test-fail {args} {
|
||||
#puts stderr "ERROR: \[[test-current-scope 1]]: $msg"
|
||||
#exit 1
|
||||
error "FAIL: \[[test-current-scope 1]]: $args"
|
||||
}
|
||||
|
||||
array set ::test__Counters {}
|
||||
array set ::test__Config {
|
||||
verbose-assert 0 verbose-affirm 0
|
||||
}
|
||||
|
||||
# Internal impl for affirm and assert.
|
||||
#
|
||||
# $args = ?-v? script {msg-on-fail ""}
|
||||
proc test__affert {failMode args} {
|
||||
if {$failMode} {
|
||||
set what assert
|
||||
} else {
|
||||
set what affirm
|
||||
}
|
||||
set verbose $::test__Config(verbose-$what)
|
||||
if {"-v" eq [lindex $args 0]} {
|
||||
lassign $args - script msg
|
||||
if {1 == [llength $args]} {
|
||||
# If -v is the only arg, toggle default verbose mode
|
||||
set ::test__Config(verbose-$what) [expr {!$::test__Config(verbose-$what)}]
|
||||
return
|
||||
}
|
||||
incr verbose
|
||||
} else {
|
||||
lassign $args script msg
|
||||
}
|
||||
incr ::test__Counters($what)
|
||||
if {![uplevel 1 expr [list $script]]} {
|
||||
if {"" eq $msg} {
|
||||
set msg $script
|
||||
}
|
||||
set txt [join [list $what # $::test__Counters($what) "failed:" $msg]]
|
||||
if {$failMode} {
|
||||
puts stderr $txt
|
||||
exit 1
|
||||
} else {
|
||||
error $txt
|
||||
}
|
||||
} elseif {$verbose} {
|
||||
puts stderr [join [list $what # $::test__Counters($what) "passed:" $script]]
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# @affirm ?-v? script ?msg?
|
||||
#
|
||||
# Works like a conventional assert method does, but reports failures
|
||||
# using [error] instead of [exit]. If -v is used, it reports passing
|
||||
# assertions to stderr. $script is evaluated in the caller's scope as
|
||||
# an argument to [expr].
|
||||
#
|
||||
proc affirm {args} {
|
||||
tailcall test__affert 0 {*}$args
|
||||
}
|
||||
|
||||
#
|
||||
# @assert ?-v? script ?msg?
|
||||
#
|
||||
# Works like [affirm] but exits on error.
|
||||
#
|
||||
proc assert {args} {
|
||||
tailcall test__affert 1 {*}$args
|
||||
}
|
||||
|
||||
#
|
||||
# @assert-matches ?-e? pattern ?-e? rhs ?msg?
|
||||
#
|
||||
# Equivalent to assert {[string match $pattern $rhs]} except that
|
||||
# if either of those are prefixed with an -e flag, they are eval'd
|
||||
# and their results are used.
|
||||
#
|
||||
proc assert-matches {args} {
|
||||
set evalLhs 0
|
||||
set evalRhs 0
|
||||
if {"-e" eq [lindex $args 0]} {
|
||||
incr evalLhs
|
||||
set args [lassign $args -]
|
||||
}
|
||||
set args [lassign $args pattern]
|
||||
if {"-e" eq [lindex $args 0]} {
|
||||
incr evalRhs
|
||||
set args [lassign $args -]
|
||||
}
|
||||
set args [lassign $args rhs msg]
|
||||
|
||||
if {$evalLhs} {
|
||||
set pattern [uplevel 1 $pattern]
|
||||
}
|
||||
if {$evalRhs} {
|
||||
set rhs [uplevel 1 $rhs]
|
||||
}
|
||||
#puts "***pattern=$pattern\n***rhs=$rhs"
|
||||
tailcall test__affert 1 \
|
||||
[join [list \[ string match [list $pattern] [list $rhs] \]]] $msg
|
||||
# why does this not work? [list \[ string match [list $pattern] [list $rhs] \]] $msg
|
||||
# "\[string match [list $pattern] [list $rhs]\]"
|
||||
}
|
||||
|
||||
#
|
||||
# @test-assert testId script ?msg?
|
||||
#
|
||||
# Works like [assert] but emits $testId to stdout first.
|
||||
#
|
||||
proc test-assert {testId script {msg ""}} {
|
||||
puts "test $testId"
|
||||
tailcall test__affert 1 $script $msg
|
||||
}
|
||||
|
||||
#
|
||||
# @test-expect testId script result
|
||||
#
|
||||
# Runs $script in the calling scope and compares its result to
|
||||
# $result, minus any leading or trailing whitespace. If they differ,
|
||||
# it triggers an [assert].
|
||||
#
|
||||
proc test-expect {testId script result} {
|
||||
puts "test $testId"
|
||||
set x [string trim [uplevel 1 $script]]
|
||||
set result [string trim $result]
|
||||
tailcall test__affert 0 [list "{$x}" eq "{$result}"] \
|
||||
"\nEXPECTED: <<$result>>\nGOT: <<$x>>"
|
||||
}
|
||||
|
||||
#
|
||||
# @test-catch cmd ?...args?
|
||||
#
|
||||
# Runs [cmd ...args], repressing any exception except to possibly log
|
||||
# the failure. Returns 1 if it caught anything, 0 if it didn't.
|
||||
#
|
||||
proc test-catch {cmd args} {
|
||||
if {[catch {
|
||||
uplevel 1 $cmd {*}$args
|
||||
} rc xopts]} {
|
||||
puts "[test-current-scope] ignoring failure of: $cmd [lindex $args 0]: $rc"
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# @test-catch-matching pattern (script|cmd args...)
|
||||
#
|
||||
# Works like test-catch, but it expects its argument(s) to to throw an
|
||||
# error matching the given string (checked with [string match]). If
|
||||
# they do not throw, or the error does not match $pattern, this
|
||||
# function throws, else it returns 1.
|
||||
#
|
||||
# If there is no second argument, the $cmd is assumed to be a script,
|
||||
# and will be eval'd in the caller's scope.
|
||||
#
|
||||
# TODO: add -glob and -regex flags to control matching flavor.
|
||||
#
|
||||
proc test-catch-matching {pattern cmd args} {
|
||||
if {[catch {
|
||||
#puts "**** catch-matching cmd=$cmd args=$args"
|
||||
if {0 == [llength $args]} {
|
||||
uplevel 1 $cmd {*}$args
|
||||
} else {
|
||||
$cmd {*}$args
|
||||
}
|
||||
} rc xopts]} {
|
||||
if {[string match $pattern $rc]} {
|
||||
return 1
|
||||
} else {
|
||||
error "[test-current-scope] exception does not match {$pattern}: {$rc}"
|
||||
}
|
||||
}
|
||||
error "[test-current-scope] expecting to see an error matching {$pattern}"
|
||||
}
|
||||
|
||||
if {![array exists ::teaish__BuildFlags]} {
|
||||
array set ::teaish__BuildFlags {}
|
||||
}
|
||||
|
||||
#
|
||||
# @teaish-build-flag3 flag tgtVar ?dflt?
|
||||
#
|
||||
# If the current build has the configure-time flag named $flag set
|
||||
# then tgtVar is assigned its value and 1 is returned, else tgtVal is
|
||||
# assigned $dflt and 0 is returned.
|
||||
#
|
||||
# Caveat #1: only valid when called in the context of teaish's default
|
||||
# "make test" recipe, e.g. from teaish.test.tcl. It is not valid from
|
||||
# a teaish.tcl configure script because (A) the state it relies on
|
||||
# doesn't fully exist at that point and (B) that level of the API has
|
||||
# more direct access to the build state. This function requires that
|
||||
# an external script have populated its internal state, which is
|
||||
# normally handled via teaish.tester.tcl.in.
|
||||
#
|
||||
# Caveat #2: defines in the style of HAVE_FEATURENAME with a value of
|
||||
# 0 are, by long-standing configure script conventions, treated as
|
||||
# _undefined_ here.
|
||||
#
|
||||
proc teaish-build-flag3 {flag tgtVar {dflt ""}} {
|
||||
upvar $tgtVar tgt
|
||||
if {[info exists ::teaish__BuildFlags($flag)]} {
|
||||
set tgt $::teaish__BuildFlags($flag)
|
||||
return 1;
|
||||
} elseif {0==[array size ::teaish__BuildFlags]} {
|
||||
test-warn \
|
||||
"\[[test-current-scope]] was called from " \
|
||||
"[test-current-scope 1] without the build flags imported."
|
||||
}
|
||||
set tgt $dflt
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# @teaish-build-flag flag ?dflt?
|
||||
#
|
||||
# Convenience form of teaish-build-flag3 which returns the
|
||||
# configure-time-defined value of $flag or "" if it's not defined (or
|
||||
# if it's an empty string).
|
||||
#
|
||||
proc teaish-build-flag {flag {dflt ""}} {
|
||||
set tgt ""
|
||||
teaish-build-flag3 $flag tgt $dflt
|
||||
return $tgt
|
||||
}
|
||||
@@ -567,7 +567,7 @@ proc sqlitecon::Cut w {
|
||||
}
|
||||
}
|
||||
|
||||
# Do a paste operation.
|
||||
# Do a paste opeation.
|
||||
#
|
||||
proc sqlitecon::Paste w {
|
||||
if {[sqlitecon::canCut $w]==1} {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Notes On Compiling SQLite On Windows 11
|
||||
|
||||
Below are step-by-step instructions on how to build SQLite from
|
||||
canonical source on a new Windows 11 PC, as of 2025-10-31.
|
||||
canonical source on a new Windows 11 PC, as of 2024-10-09.
|
||||
See [](./compile-for-unix.md) for a similar guide for unix-like
|
||||
systems, including MacOS.
|
||||
|
||||
@@ -24,8 +24,7 @@ systems, including MacOS.
|
||||
application to your task bar, as you will use it a lot. Bring up
|
||||
an instance of this command prompt and do all of the subsequent steps
|
||||
in that "x64 Native Tools" command prompt. (Or use "x86" if you want
|
||||
a 32-bit build. Or use "ARM64" if you want to do a build for Windows
|
||||
on ARM.) The subsequent steps will not work in a vanilla
|
||||
a 32-bit build.) The subsequent steps will not work in a vanilla
|
||||
DOS prompt. Nor will they work in PowerShell.
|
||||
|
||||
3. *(Optional):* Install TCL development libraries.
|
||||
@@ -134,7 +133,9 @@ following minor changes:
|
||||
The command the developers use for building the deliverable DLL on the
|
||||
[download page](https://sqlite.org/download.html) is as follows:
|
||||
|
||||
> nmake /f Makefile.msc sqlite3.dll USE_NATIVE_LIBPATHS=1 "OPTS=-DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SERIALIZE=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1"
|
||||
> ~~~~
|
||||
nmake /f Makefile.msc sqlite3.dll USE_NATIVE_LIBPATHS=1 "OPTS=-DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SERIALIZE=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1"
|
||||
~~~~
|
||||
|
||||
That command generates both the sqlite3.dll and sqlite3.def files. The same
|
||||
command works for both 32-bit and 64-bit builds.
|
||||
@@ -146,7 +147,9 @@ with TCL in order to function. The [sqlite3_analyzer.exe program](https://sqlit
|
||||
is an example. You can build as described above, and then
|
||||
enter:
|
||||
|
||||
> nmake /f Makefile.msc sqlite3_analyzer.exe
|
||||
> ~~~~
|
||||
nmake /f Makefile.msc sqlite3_analyzer.exe
|
||||
~~~~
|
||||
|
||||
And you will end up with a working executable. However, that executable
|
||||
will depend on having the "tcl98.dll" library somewhere on your %PATH%.
|
||||
@@ -172,11 +175,17 @@ statically linked so that it does not depend on separate DLL:
|
||||
5. CD into your SQLite source code directory and build the desired
|
||||
utility program, but add the following extra argument to the
|
||||
nmake command line:
|
||||
<blockquote><pre>STATICALLY_LINK_TCL=1</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
STATICALLY_LINK_TCL=1
|
||||
</pre></blockquote>
|
||||
<p>So, for example, to build a statically linked version of
|
||||
sqlite3_analyzer.exe, you might type:
|
||||
<blockquote><pre>nmake /f Makefile.msc STATICALLY_LINK_TCL=1 sqlite3_analyzer.exe</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
nmake /f Makefile.msc STATICALLY_LINK_TCL=1 sqlite3_analyzer.exe
|
||||
</pre></blockquote>
|
||||
|
||||
6. After your executable is built, you can verify that it does not
|
||||
depend on the TCL DLL by running:
|
||||
<blockquote><pre>dumpbin /dependents sqlite3_analyzer.exe</pre></blockquote>
|
||||
<blockquote><pre>
|
||||
dumpbin /dependents sqlite3_analyzer.exe
|
||||
</pre></blockquote>
|
||||
|
||||
+10
-9
@@ -149,10 +149,11 @@ RFC 8259 format, without extensions. The payload is the ASCII
|
||||
text representation of that numeric value.
|
||||
|
||||
<li value="4"><p><b>INT5</b> →
|
||||
The element is a JSON integer literal in hexadecimal notation.
|
||||
The payload is the ASCII text representation of the literal.
|
||||
Because the payload is in a non-standard format, it will need
|
||||
to be translated when the JSONB is converted into RFC 8259 text JSON.
|
||||
The element is a JSON integer value that is not in the
|
||||
canonical format. The payload is the ASCII
|
||||
text representation of that numeric value. Because the payload is in a
|
||||
non-standard format, it will need to be translated when the JSONB is
|
||||
converted into RFC 8259 text JSON.
|
||||
|
||||
<li value="5"><p><b>FLOAT</b> →
|
||||
The element is a JSON floating-point value in the canonical
|
||||
@@ -161,10 +162,10 @@ text representation of that numeric value.
|
||||
|
||||
<li value="6"><p><b>FLOAT5</b> →
|
||||
The element is a JSON floating-point value that is not in the
|
||||
canonical JSON format but rather the extended JSON5 format.
|
||||
The payload is the ASCII text representation of that numeric value.
|
||||
Because the payload is in a non-standard format, it will need to
|
||||
be translated when the JSONB is converted into RFC 8259 text JSON.
|
||||
canonical format. The payload is the ASCII
|
||||
text representation of that numeric value. Because the payload is in a
|
||||
non-standard format, it will need to be translated when the JSONB is
|
||||
converted into RFC 8259 text JSON.
|
||||
|
||||
<li value="7"><p><b>TEXT</b> →
|
||||
The element is a JSON string value that does not contain
|
||||
@@ -280,7 +281,7 @@ happen if and when they are actually needed.
|
||||
A valid JSONB BLOB consists of a single JSON element. The element must
|
||||
exactly fill the BLOB. This one element is often a JSON object or array
|
||||
and those usually contain additional elements as its payload, but the
|
||||
element can be a primitive value such a string, number, boolean, or null.
|
||||
element can be a primite value such a string, number, boolean, or null.
|
||||
|
||||
When the built-in JSON functions are attempting to determine if a BLOB
|
||||
argument is a JSONB or just a random BLOB, they look at the header of
|
||||
|
||||
+2
-2
@@ -846,7 +846,7 @@ or more tokens. The alternative meaning is tried if the original token
|
||||
would have generated a syntax error.</p>
|
||||
|
||||
<p>The <tt>%fallback</tt> directive was added to support robust parsing of SQL
|
||||
syntax in <a href='https://sqlite.org/'>SQLite</a>.
|
||||
syntax in <a href='https://www.sqlite.org/'>SQLite</a>.
|
||||
The SQL language contains a large assortment of keywords, each of which
|
||||
appears as a different token to the language parser. SQL contains so
|
||||
many keywords that it can be difficult for programmers to keep up with
|
||||
@@ -881,7 +881,7 @@ is allowed between the "%" and the directive name.</p>
|
||||
<p>Grammar text in between "<tt>%ifdef MACRO</tt>" and the next nested
|
||||
"<tt>%endif</tt>" is
|
||||
ignored unless the "-DMACRO" command-line option is used. Grammar text
|
||||
between "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
|
||||
betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
|
||||
included except when the "-DMACRO" command-line option is used.<p>
|
||||
|
||||
<p>The text in between "<tt>%if</tt> <i>CONDITIONAL</i>" and its
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
*** Definition: Two databases (or the same database at two points it time)
|
||||
are said to be "logically equivalent" if they give the same answer to
|
||||
all queries. Note in particular the content of freelist leaf
|
||||
pages can be changed arbitrarily without effecting the logical equivalence
|
||||
pages can be changed arbitarily without effecting the logical equivalence
|
||||
of the database.
|
||||
|
||||
(7) At any time, if any subset, including the empty set and the total set,
|
||||
|
||||
+51
-107
@@ -35,69 +35,84 @@ perspective on how to compile SQLite on unix-like systems.
|
||||
### 2.1 Setup
|
||||
|
||||
<ol type="1">
|
||||
<li value="1">
|
||||
[Fossil][] installed.
|
||||
<li value="1">
|
||||
[Fossil](https://fossil-scm.org/) installed.
|
||||
<li> Check out source code and set environment variables:
|
||||
<ol type="a">
|
||||
<li> **TCLSOURCE** →
|
||||
The top-level directory of a [Fossil][] check-out of the
|
||||
[TCL source tree][tcl-fossil].
|
||||
The top-level directory of a Fossil check-out of the TCL source tree.
|
||||
<li> **SQLITESOURCE** →
|
||||
A Fossil check-out of the SQLite source tree.
|
||||
<li> **TCLHOME** →
|
||||
<li> **TCLBUILD** →
|
||||
A directory that does not exist at the start of the test and which
|
||||
will be deleted at the end of the test, and that will contain the
|
||||
test builds of the TCL libraries and the SQLite TCL Extensions.
|
||||
It is the top-most installation directory, i.e. the one provided
|
||||
to Tcl's `./configure --prefix=/path/to/tcl`.
|
||||
<li> **TCLVERSION** →
|
||||
The `X.Y`-form version of Tcl being used: 8.6, 9.0, 9.1...
|
||||
</ol>
|
||||
</ol>
|
||||
|
||||
### 2.2 Testing TCL 8.x and 9.x on unix
|
||||
|
||||
From a checked-out copy of [the core Tcl tree][tcl-fossil]
|
||||
### 2.2 Testing TCL 8.6 on unix
|
||||
|
||||
<ol type="1">
|
||||
<li value="3">`TCLVERSION=8.6` <br>
|
||||
↑ A version of your choice. This process has been tested with
|
||||
values of 8.6, 9.0, and 9.1 (as of 2025-04-16). The out-of-life
|
||||
version 8.5 fails some of `make devtest` for undetermined reasons.
|
||||
<li>`TCLHOME=$HOME/tcl/$TCLVERSION`
|
||||
<li>`TCLSOURCE=/path/to/tcl/checkout`
|
||||
<li>`SQLITESOURCE=/path/to/sqlite/checkout`
|
||||
<li>`rm -fr $TCLHOME` <br>
|
||||
↑ Ensure that no stale Tcl installation is laying around.
|
||||
<li> `cd $TCLSOURCE`
|
||||
<li> `fossil up core-8-6-branch` <br>
|
||||
↑ The branch corresponding to `$TCLVERSION`, e.g.
|
||||
`core-9-0-branch` or `trunk`.
|
||||
<li value="3"> `mkdir -p $TCLBUILD/tcl86`
|
||||
<li> `cd $TCLSOURCE/unix`
|
||||
<li> `fossil up core-8-6-16` <br>
|
||||
↑ Or some other version of Tcl8.6.
|
||||
<li> `fossil clean -x`
|
||||
<li> `cd unix`
|
||||
<li> `./configure --prefix=$TCLHOME --disable-shared` <br>
|
||||
↑ The `--disable-shared` is to avoid the need to set `LD_LIBRARY_PATH`
|
||||
<li> `./configure --prefix=$TCLBUILD/tcl86 --disable-shared` <br>
|
||||
↑ The --disable-shared is to avoid the need to set LD_LIBRARY_PATH
|
||||
when using this Tcl build.
|
||||
<li> `make install`
|
||||
<li> `cd $SQLITESOURCE`
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --with-tcl=$TCLHOME --all`
|
||||
<li> `./configure --with-tclsh=$TCLBUILD/tcl86/bin/tclsh8.6 --all`
|
||||
<li> `make tclextension-install` <br>
|
||||
↑ Verify extension installed at
|
||||
`$TCLHOME/lib/tcl${TCLVERSION}/sqlite<SQLITE_VERSION>`.
|
||||
↑ Verify extension installed at $TCLBUILD/tcl86/lib/tcl8.6/sqlite3.*
|
||||
<li> `make tclextension-list` <br>
|
||||
↑ Verify TCL extension correctly installed.
|
||||
<li> `make tclextension-verify` <br>
|
||||
↑ Verify that the correct version is installed.
|
||||
<li> `$TCLHOME/bin/tclsh[89].[0-9] test/testrunner.tcl release --explain` <br>
|
||||
<li> `$TCLBUILD/tcl86/bin/tclsh8.6 test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 2.3 Cleanup
|
||||
### 2.3 Testing TCL 9.0 on unix
|
||||
|
||||
<ol>
|
||||
<li value="16"> `mkdir -p $TCLBUILD/tcl90`
|
||||
<li> `fossil up core-9-0-0` <br>
|
||||
↑ Or some other version of Tcl9
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --prefix=$TCLBUILD/tcl90 --disable-shared` <br>
|
||||
↑ The --disable-shared is to avoid the need to set LD_LIBRARY_PATH
|
||||
when using this Tcl build.
|
||||
<li> `make install`
|
||||
<li> `cp -r ../library $TCLBUILD/tcl90/lib/tcl9.0` <br>
|
||||
↑ The Tcl library is not installed by "make install" for Tcl9.0 unless
|
||||
you also include the --disable-zipfs to ./configure. But if you do that
|
||||
then the generated tclsh9.0 is no longer stand-alone. On the other hand,
|
||||
if you don't install the Tcl library, other programs like testfixture
|
||||
won't be able to find the Tcl library and hence won't work. This
|
||||
extra installation step resolves the dilemma.
|
||||
This step is not required when building Tcl8.6, which lacks support for
|
||||
zipfs and hence always installs its Tcl library.
|
||||
<li> `cd $SQLITESOURCE`
|
||||
<li> `fossil clean -x`
|
||||
<li> `./configure --with-tclsh=$TCLBUILD/tcl90/bin/tclsh9.0 --all`
|
||||
<li> `make tclextension-install` <br>
|
||||
↑ Verify extension installed at $TCLBUILD/tcl90/lib/sqlite3.*
|
||||
<li> `make tclextension-list` <br>
|
||||
↑ Verify TCL extension correctly installed.
|
||||
<li> `make tclextension-verify`
|
||||
<li> `$TCLBUILD/tcl90/bin/tclsh9.0 test/testrunner.tcl release --explain` <br>
|
||||
↑ Verify thousands of lines of output with no errors. Or
|
||||
consider running "devtest" without --explain instead of "release".
|
||||
</ol>
|
||||
|
||||
### 2.4 Cleanup
|
||||
|
||||
<ol type="1">
|
||||
<li value="29"> `rm -rf $TCLHOME`
|
||||
<li value="29"> `rm -rf $TCLBUILD`
|
||||
</ol>
|
||||
|
||||
<a id="windows"></a>
|
||||
@@ -108,11 +123,9 @@ perspective on how to compile SQLite on Windows.
|
||||
|
||||
### 3.1 Setup for Windows
|
||||
|
||||
(These docs are not as up-to-date as the Unix docs, above.)
|
||||
|
||||
<ol type="1">
|
||||
<li value="1">
|
||||
[Fossil][] installed.
|
||||
<li value="1">
|
||||
[Fossil](https://fossil-scm.org/) installed.
|
||||
<li>
|
||||
Unix-like command-line tools installed. Example:
|
||||
[unxutils](https://unxutils.sourceforge.net/)
|
||||
@@ -193,72 +206,3 @@ perspective on how to compile SQLite on Windows.
|
||||
<ol type="1">
|
||||
<li value="35"> `rm -rf %TCLBUILD%`
|
||||
</ol>
|
||||
|
||||
## 4.0 Testing the TEA(ish) Build (unix only)
|
||||
|
||||
This part requires following the setup instructions for Unix systems,
|
||||
at the top of this document.
|
||||
|
||||
The former TEA, now TEA(ish), build of this extension uses the same
|
||||
code as the builds described above but is provided in a form more
|
||||
convenient for downstream Tcl users.
|
||||
|
||||
It lives in `autoconf/tea` and, as part of the `autoconf` bundle,
|
||||
_cannot be tested directly from the canonical tree_. Instead it has to
|
||||
be packaged.
|
||||
|
||||
### 4.1 Teaish Setup
|
||||
|
||||
Follow the same Tcl- and environment-related related setup described
|
||||
in the first section of this document, up to and including the
|
||||
installation of Tcl (unless, of course, it was already installed using
|
||||
those same instructions).
|
||||
|
||||
### 4.2 Teaish Testing
|
||||
|
||||
<ol>
|
||||
<li>`cd $SQLITESOURCE`
|
||||
<li>Run either `make snapshot-tarball` or `make amalgamation-tarball`
|
||||
↑
|
||||
Those steps will leave behind a temp dir called `mkpkg_tmp_dir`,
|
||||
under which the extension is most readily reached. It can optionally
|
||||
be extracted from the generated tarball, but that tarball was
|
||||
generated from this dir, and reusing this dir is a time saver
|
||||
during development.
|
||||
<li> `cd mkpkg_tmp/tea`
|
||||
<li> `./configure --with-tcl=$TCLHOME`
|
||||
<li> `make test install` <br>
|
||||
↑ Should run to completion without any errors.
|
||||
<li> `make uninstall` <br>
|
||||
↑ Will uninstall the extension. This _can_ be run
|
||||
in the same invocation as the `install` target, but only
|
||||
if the `-j#` make flag is _not_ used. If it is, the
|
||||
install/uninstall steps will race and make a mess of things.
|
||||
Parallel builds do not help in this build, anyway, as there's
|
||||
only a single C file to compile.
|
||||
</ol>
|
||||
|
||||
When actively developing and testing the teaish build, which requires
|
||||
going through the tarball generation, there's a caveat about the
|
||||
`mkpkg_tmp_dir` dir: it will be deleted every time a tarball is
|
||||
built, the shell console which is parked in that
|
||||
directory for testing needs to add `cd $PWD &&` to the start of the
|
||||
build commands, like:
|
||||
|
||||
>
|
||||
```
|
||||
[user@host:.../mkpkg_tmp_dir/tea]$ \
|
||||
cd $PWD && ./configure CFLAGS=-O0 --with-tcl=$TCLHOME \
|
||||
&& make test install uninstall
|
||||
```
|
||||
|
||||
### 4.3 Teaish Cleanup
|
||||
|
||||
|
||||
<ol type="1">
|
||||
<li> `rm -rf $TCLHOME`
|
||||
<li> `cd $SQLITESOURCE; rm -fr mkpkg_tmp_dir; fossil clean -x`
|
||||
</ol>
|
||||
|
||||
[Fossil]: https://fossil-scm.org/home
|
||||
[tcl-fossil]: https://core.tcl-lang.org/tcl
|
||||
|
||||
+20
-68
@@ -15,7 +15,6 @@
|
||||
<li> 3.1. <a href=#commands_to_run_tests>Commands to Run SQLite Tests</a>
|
||||
<li> 3.2. <a href=#zipvfs_tests>Running ZipVFS Tests</a>
|
||||
<li> 3.3. <a href=#source_code_test_failures>Investigating Source Code Test Failures</a>
|
||||
<li> 3.4. <a href=#fuzzdb>External Fuzzcheck Databases</a>
|
||||
</ul>
|
||||
<li> 4. <a href=#testrunner_options>Extra testrunner.tcl Options</a>
|
||||
<li> 5. <a href=#cpu_cores>Controlling CPU Core Utilization</a>
|
||||
@@ -24,62 +23,47 @@
|
||||
<a name=overview></a>
|
||||
# 1. Overview
|
||||
|
||||
The testrunner.tcl program is a Tcl script used to run multiple SQLite
|
||||
tests in parallel, thus reducing testing time on multi-core machines.
|
||||
It supports the following types of tests:
|
||||
testrunner.tcl is a Tcl script used to run multiple SQLite tests using
|
||||
multiple jobs. It supports the following types of tests:
|
||||
|
||||
* Tcl test scripts.
|
||||
|
||||
* Fuzzcheck tests, including using an external fuzzcheck database.
|
||||
|
||||
* Tests run with `make` commands. Examples:
|
||||
- `make devtest`
|
||||
- `make mdevtest`
|
||||
- `make releasetest`
|
||||
- `make sdevtest`
|
||||
- `make testrunner`
|
||||
|
||||
The testrunner.tcl program stores output of all tests and builds run in
|
||||
log file **testrunner.log**, created in the current working directory.
|
||||
Search this file to find details of errors. Suggested search commands:
|
||||
testrunner.tcl pipes the output of all tests and builds run into log file
|
||||
**testrunner.log**, created in the current working directory. Search this
|
||||
file to find details of errors. Suggested search commands:
|
||||
|
||||
* `grep "^!" testrunner.log`
|
||||
* `grep failed testrunner.log`
|
||||
|
||||
The testrunner.tcl program also populates SQLite database **testrunner.db**.
|
||||
This database contains details of all tests run, running and to be run.
|
||||
A useful query might be:
|
||||
testrunner.tcl also populates SQLite database **testrunner.db**. This database
|
||||
contains details of all tests run, running and to be run. A useful query
|
||||
might be:
|
||||
|
||||
```
|
||||
SELECT * FROM script WHERE state='failed'
|
||||
```
|
||||
|
||||
You can get a summary of errors in a prior run by invoking commands like
|
||||
these:
|
||||
|
||||
```
|
||||
tclsh $(TESTDIR)/testrunner.tcl errors
|
||||
tclsh $(TESTDIR)/testrunner.tcl errors -v
|
||||
```
|
||||
|
||||
Running the command:
|
||||
|
||||
```
|
||||
tclsh $(TESTDIR)/testrunner.tcl status
|
||||
./testfixture $(TESTDIR)/testrunner.tcl status
|
||||
```
|
||||
|
||||
in the directory containing the testrunner.db database runs various queries
|
||||
to produce a succinct report on the state of a running testrunner.tcl script.
|
||||
A good way to keep and eye on test progress is to run either of the two
|
||||
following commands:
|
||||
Running:
|
||||
|
||||
```
|
||||
watch tclsh $(TESTDIR)/testrunner.tcl status
|
||||
tclsh $(TESTDIR)/testrunner.tcl status -d 2
|
||||
watch ./testfixture $(TESTDIR)/testrunner.tcl status
|
||||
```
|
||||
|
||||
Both of the commands above accomplish about the same thing, but the second
|
||||
one has the advantage of not requiring "watch" to be installed on your
|
||||
system.
|
||||
in another terminal is a good way to keep an eye on a long running test.
|
||||
|
||||
Sometimes testrunner.tcl uses the `testfixture` binary that it is run with
|
||||
to run tests (see "Binary Tests" below). Sometimes it builds testfixture and
|
||||
@@ -255,7 +239,9 @@ of the specific tests run.
|
||||
|
||||
As with <a href=#source code tests>source code tests</a>, one or more patterns
|
||||
may be appended to any of the above commands (mdevtest, sdevtest or release).
|
||||
Pattern matching is used for both Tcl tests and fuzz tests.
|
||||
In that case only Tcl tests (no fuzz or other tests) that match the specified
|
||||
pattern are run. For example, to run the just the Tcl rtree tests in all
|
||||
builds and configurations supported by "release":
|
||||
|
||||
```
|
||||
tclsh $TESTDIR/testrunner.tcl release rtree%
|
||||
@@ -306,34 +292,6 @@ target to build. This may be used either to run a `make` command test directly,
|
||||
or else to build a testfixture (or testfixture.exe) binary with which to
|
||||
run a Tcl test script, as <a href=#binary_test_failures>described above</a>.
|
||||
|
||||
<a name=fuzzdb></a>
|
||||
## 3.4 External Fuzzcheck Databases
|
||||
|
||||
Testrunner.tcl will also run fuzzcheck against an external (out of tree)
|
||||
database, for example fuzzcheck databases generated by dbsqlfuzz. To do
|
||||
this, simply add the "`--fuzzdb` *FILENAME*" command-line option or set
|
||||
the FUZZDB environment variable to the name of the external
|
||||
database. For large external databases, testrunner.tcl will automatically use
|
||||
the "`--slice`" command-line option of fuzzcheck to divide the work up into
|
||||
multiple jobs, to increase parallelism.
|
||||
|
||||
Thus, for example, to run a full releasetest including an external
|
||||
dbsqlfuzz database, run a command like one of these:
|
||||
|
||||
```
|
||||
tclsh test/testrunner.tcl releasetest --fuzzdb ../fuzz/20250415.db
|
||||
FUZZDB=../fuzz/20250415.db make releasetest
|
||||
nmake /f Makefile.msc FUZZDB=../fuzz/20250415.db releasetest
|
||||
```
|
||||
|
||||
The patternlist option to testrunner.tcl will match against fuzzcheck
|
||||
databases. So if you want to run *only* tests involving the external
|
||||
database, you can use a command something like this:
|
||||
|
||||
```
|
||||
tclsh test/testrunner.tcl releasetest 20250415 --fuzzdb ../fuzz/20250415.db
|
||||
```
|
||||
|
||||
<a name=testrunner_options></a>
|
||||
# 4. Extra testrunner.tcl Options
|
||||
|
||||
@@ -357,22 +315,16 @@ would normally execute into the testrunner.log file. Example:
|
||||
tclsh $TESTDIR/testrunner.tcl --dryrun mdevtest"
|
||||
```
|
||||
|
||||
The **--explain** option is similar to --dryrun in that it prevents
|
||||
testrunner.tcl from building any binaries or running any tests. The
|
||||
difference is that --explain prints on standard output a human-readable
|
||||
summary of all the builds and tests that would have been run.
|
||||
The **--explain** option is similar to --dryrun in that it prevents testrunner.tcl
|
||||
from building any binaries or running any tests. The difference is that --explain
|
||||
prints on standard output a human-readable summary of all the builds and tests that
|
||||
would have been run.
|
||||
|
||||
```
|
||||
# Show what builds and tests would have been run
|
||||
tclsh $TESTDIR/testrunner.tcl --explain mdevtest
|
||||
```
|
||||
|
||||
The **--status** option uses VT100 escape sequences to display the test
|
||||
status full-screen. This is similar to running
|
||||
"`watch test/testrunner status`" in a separate window, just more convenient.
|
||||
Unfortunately, this option does not work correctly on Windows, due to the
|
||||
sketchy implementation of VT100 escapes on the Windows console.
|
||||
|
||||
<a name=cpu_cores></a>
|
||||
# 5. Controlling CPU Core Utilization
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
The 5 states of an historical rollback lock as implemented by the
|
||||
xLock, xUnlock, and xCheckReservedLock methods of the sqlite3_io_methods
|
||||
object are:
|
||||
objec are:
|
||||
|
||||
UNLOCKED
|
||||
SHARED
|
||||
@@ -58,7 +58,7 @@ The meanings of the various wal-index locking states is as follows:
|
||||
|
||||
A particular lock manager implementation may coalesce one or more of
|
||||
the wal-index locking states, though with a reduction in concurrency.
|
||||
For example, an implementation might implement only exclusive locking,
|
||||
For example, an implemention might implement only exclusive locking,
|
||||
in which case all states would be equivalent to CHECKPOINT, meaning that
|
||||
only one reader or one writer or one checkpointer could be active at a
|
||||
time. Or, an implementation might combine READ and READ_FULL into
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ facilitates transfer of OS priority between processes when a high priority
|
||||
process is blocked by a lower priority one.
|
||||
|
||||
Only read/write clients use blocking locks. Clients that have read-only access
|
||||
to the \*-shm file never use blocking locks.
|
||||
to the \*-shm file nevery use blocking locks.
|
||||
|
||||
Threads or processes that access a single database at a time never deadlock as
|
||||
a result of blocking database locks. But it is of course possible for threads
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
## Loadable Extensions
|
||||
|
||||
Various [loadable extensions](https://sqlite.org/loadext.html) for
|
||||
Various [loadable extensions](https://www.sqlite.org/loadext.html) for
|
||||
SQLite are found in subfolders.
|
||||
|
||||
Most subfolders are dedicated to a single loadable extension (for
|
||||
|
||||
+26
-28
@@ -172,11 +172,11 @@ struct sqlite3expert {
|
||||
** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
|
||||
** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
|
||||
*/
|
||||
static void *idxMalloc(int *pRc, i64 nByte){
|
||||
static void *idxMalloc(int *pRc, int nByte){
|
||||
void *pRet;
|
||||
assert( *pRc==SQLITE_OK );
|
||||
assert( nByte>0 );
|
||||
pRet = sqlite3_malloc64(nByte);
|
||||
pRet = sqlite3_malloc(nByte);
|
||||
if( pRet ){
|
||||
memset(pRet, 0, nByte);
|
||||
}else{
|
||||
@@ -243,7 +243,7 @@ static int idxHashAdd(
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + (i64)nKey+1 + (i64)nVal+1);
|
||||
pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
|
||||
if( pEntry ){
|
||||
pEntry->zKey = (char*)&pEntry[1];
|
||||
memcpy(pEntry->zKey, zKey, nKey);
|
||||
@@ -378,15 +378,15 @@ struct ExpertCsr {
|
||||
};
|
||||
|
||||
static char *expertDequote(const char *zIn){
|
||||
i64 n = STRLEN(zIn);
|
||||
char *zRet = sqlite3_malloc64(n);
|
||||
int n = STRLEN(zIn);
|
||||
char *zRet = sqlite3_malloc(n);
|
||||
|
||||
assert( zIn[0]=='\'' );
|
||||
assert( zIn[n-1]=='\'' );
|
||||
|
||||
if( zRet ){
|
||||
i64 iOut = 0;
|
||||
i64 iIn = 0;
|
||||
int iOut = 0;
|
||||
int iIn = 0;
|
||||
for(iIn=1; iIn<(n-1); iIn++){
|
||||
if( zIn[iIn]=='\'' ){
|
||||
assert( zIn[iIn+1]=='\'' );
|
||||
@@ -699,7 +699,7 @@ static int idxGetTableInfo(
|
||||
sqlite3_stmt *p1 = 0;
|
||||
int nCol = 0;
|
||||
int nTab;
|
||||
i64 nByte;
|
||||
int nByte;
|
||||
IdxTable *pNew = 0;
|
||||
int rc, rc2;
|
||||
char *pCsr = 0;
|
||||
@@ -791,14 +791,14 @@ static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
|
||||
va_list ap;
|
||||
char *zAppend = 0;
|
||||
char *zRet = 0;
|
||||
i64 nIn = zIn ? STRLEN(zIn) : 0;
|
||||
i64 nAppend = 0;
|
||||
int nIn = zIn ? STRLEN(zIn) : 0;
|
||||
int nAppend = 0;
|
||||
va_start(ap, zFmt);
|
||||
if( *pRc==SQLITE_OK ){
|
||||
zAppend = sqlite3_vmprintf(zFmt, ap);
|
||||
if( zAppend ){
|
||||
nAppend = STRLEN(zAppend);
|
||||
zRet = (char*)sqlite3_malloc64(nIn + nAppend + 1);
|
||||
zRet = (char*)sqlite3_malloc(nIn + nAppend + 1);
|
||||
}
|
||||
if( zAppend && zRet ){
|
||||
if( nIn ) memcpy(zRet, zIn, nIn);
|
||||
@@ -1562,8 +1562,8 @@ struct IdxRemCtx {
|
||||
int eType; /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
|
||||
i64 iVal; /* SQLITE_INTEGER value */
|
||||
double rVal; /* SQLITE_FLOAT value */
|
||||
i64 nByte; /* Bytes of space allocated at z */
|
||||
i64 n; /* Size of buffer z */
|
||||
int nByte; /* Bytes of space allocated at z */
|
||||
int n; /* Size of buffer z */
|
||||
char *z; /* SQLITE_TEXT/BLOB value */
|
||||
} aSlot[1];
|
||||
};
|
||||
@@ -1599,13 +1599,11 @@ static void idxRemFunc(
|
||||
break;
|
||||
|
||||
case SQLITE_BLOB:
|
||||
assert( pSlot->n <= 0x7fffffff );
|
||||
sqlite3_result_blob(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT);
|
||||
sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
|
||||
case SQLITE_TEXT:
|
||||
assert( pSlot->n <= 0x7fffffff );
|
||||
sqlite3_result_text(pCtx, pSlot->z, (int)pSlot->n, SQLITE_TRANSIENT);
|
||||
sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1625,10 +1623,10 @@ static void idxRemFunc(
|
||||
|
||||
case SQLITE_BLOB:
|
||||
case SQLITE_TEXT: {
|
||||
i64 nByte = sqlite3_value_bytes(argv[1]);
|
||||
int nByte = sqlite3_value_bytes(argv[1]);
|
||||
const void *pData = 0;
|
||||
if( nByte>pSlot->nByte ){
|
||||
char *zNew = (char*)sqlite3_realloc64(pSlot->z, nByte*2);
|
||||
char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
|
||||
if( zNew==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
return;
|
||||
@@ -1683,7 +1681,7 @@ static int idxPopulateOneStat1(
|
||||
int nCol = 0;
|
||||
int i;
|
||||
sqlite3_stmt *pQuery = 0;
|
||||
i64 *aStat = 0;
|
||||
int *aStat = 0;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( p->iSample>0 );
|
||||
@@ -1729,7 +1727,7 @@ static int idxPopulateOneStat1(
|
||||
sqlite3_free(zQuery);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
aStat = (i64*)idxMalloc(&rc, sizeof(i64)*(nCol+1));
|
||||
aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1));
|
||||
}
|
||||
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
|
||||
IdxHashEntry *pEntry;
|
||||
@@ -1746,11 +1744,11 @@ static int idxPopulateOneStat1(
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
i64 s0 = aStat[0];
|
||||
zStat = sqlite3_mprintf("%lld", s0);
|
||||
int s0 = aStat[0];
|
||||
zStat = sqlite3_mprintf("%d", s0);
|
||||
if( zStat==0 ) rc = SQLITE_NOMEM;
|
||||
for(i=1; rc==SQLITE_OK && i<=nCol; i++){
|
||||
zStat = idxAppendText(&rc, zStat, " %lld", (s0+aStat[i]/2) / aStat[i]);
|
||||
zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1829,7 +1827,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
i64 nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
|
||||
int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
|
||||
pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
|
||||
}
|
||||
|
||||
@@ -1846,7 +1844,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
pCtx->nSlot = (i64)nMax+1;
|
||||
pCtx->nSlot = nMax+1;
|
||||
rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2054,7 +2052,7 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
|
||||
sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
|
||||
}
|
||||
|
||||
/* If an error has occurred, free the new object and return NULL. Otherwise,
|
||||
/* If an error has occurred, free the new object and reutrn NULL. Otherwise,
|
||||
** return the new sqlite3expert handle. */
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_expert_destroy(pNew);
|
||||
@@ -2113,7 +2111,7 @@ int sqlite3_expert_sql(
|
||||
if( pStmt ){
|
||||
IdxStatement *pNew;
|
||||
const char *z = sqlite3_sql(pStmt);
|
||||
i64 n = STRLEN(z);
|
||||
int n = STRLEN(z);
|
||||
pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->zSql = (char*)&pNew[1];
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
static int dbHandleFromObj(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **pDb){
|
||||
Tcl_CmdInfo info;
|
||||
if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(pObj), &info) ){
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), NULL);
|
||||
Tcl_AppendResult(interp, "no such handle: ", Tcl_GetString(pObj), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,20 +62,20 @@
|
||||
matches rows that contain both the "engineering" and "consultancy" tokens
|
||||
in the same column with not more than 10 other words between them. It does
|
||||
not matter which of the two terms occurs first in the document, only that
|
||||
they be separated by only 10 tokens or less. The user may also specify
|
||||
they be seperated by only 10 tokens or less. The user may also specify
|
||||
a different required proximity by adding "/N" immediately after the NEAR
|
||||
operator, where N is an integer. For example:
|
||||
|
||||
<col> MATCH 'engineering NEAR/5 consultancy'
|
||||
|
||||
searches for a row containing an instance of each specified token separated
|
||||
searches for a row containing an instance of each specified token seperated
|
||||
by not more than 5 other tokens. More than one NEAR operator can be used
|
||||
in as sequence. For example this query:
|
||||
|
||||
<col> MATCH 'reliable NEAR/2 engineering NEAR/5 consultancy'
|
||||
|
||||
searches for a row that contains an instance of the token "reliable"
|
||||
separated by not more than two tokens from an instance of "engineering",
|
||||
seperated by not more than two tokens from an instance of "engineering",
|
||||
which is in turn separated by not more than 5 other tokens from an
|
||||
instance of the term "consultancy". Phrases enclosed in quotes may
|
||||
also be used as arguments to the NEAR operator.
|
||||
@@ -146,7 +146,7 @@
|
||||
<col> MATCH '(hello world) OR (simple example)'
|
||||
|
||||
matches documents that contain both "hello" and "world", and documents
|
||||
that contain both "simple" and "example". It is not possible to formulate
|
||||
that contain both "simple" and "example". It is not possible to forumlate
|
||||
such a query using the standard syntax.
|
||||
|
||||
2) Instead of separating tokens and phrases by whitespace, an AND operator
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
4) Unlike in the standard syntax, where the OR operator has a higher
|
||||
precedence than the implicit AND operator, when using the enhanced
|
||||
syntax implicit and explicit AND operators have a higher precedence
|
||||
syntax implicit and explict AND operators have a higher precedence
|
||||
than OR operators. Using the enhanced syntax, the following two
|
||||
queries are equivalent:
|
||||
|
||||
|
||||
+11
-5
@@ -87,7 +87,7 @@
|
||||
** Here, array { X } means zero or more occurrences of X, adjacent in
|
||||
** memory. A "position" is an index of a token in the token stream
|
||||
** generated by the tokenizer. Note that POS_END and POS_COLUMN occur
|
||||
** in the same logical place as the position element, and act as sentinels
|
||||
** in the same logical place as the position element, and act as sentinals
|
||||
** ending a position list array. POS_END is 0. POS_COLUMN is 1.
|
||||
** The positions numbers are not stored literally but rather as two more
|
||||
** than the difference from the prior position, or the just the position plus
|
||||
@@ -295,6 +295,12 @@
|
||||
# define SQLITE_CORE 1
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "fts3.h"
|
||||
#ifndef SQLITE_CORE
|
||||
@@ -2633,7 +2639,7 @@ static int fts3DoclistOrMerge(
|
||||
** sizes of the two inputs, plus enough space for exactly one of the input
|
||||
** docids to grow.
|
||||
**
|
||||
** A symmetric argument may be made if the doclists are in descending
|
||||
** A symetric argument may be made if the doclists are in descending
|
||||
** order.
|
||||
*/
|
||||
aOut = sqlite3_malloc64((i64)n1+n2+FTS3_VARINT_MAX-1+FTS3_BUFFER_PADDING);
|
||||
@@ -4432,7 +4438,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
|
||||
nDistance = iPrev - nMaxUndeferred;
|
||||
}
|
||||
|
||||
aOut = (char *)sqlite3Fts3MallocZero(((i64)nPoslist)+FTS3_BUFFER_PADDING);
|
||||
aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING);
|
||||
if( !aOut ){
|
||||
sqlite3_free(aPoslist);
|
||||
return SQLITE_NOMEM;
|
||||
@@ -4731,7 +4737,7 @@ static int incrPhraseTokenNext(
|
||||
**
|
||||
** * does not contain any deferred tokens.
|
||||
**
|
||||
** Advance it to the next matching document in the database and populate
|
||||
** Advance it to the next matching documnent in the database and populate
|
||||
** the Fts3Doclist.pList and nList fields.
|
||||
**
|
||||
** If there is no "next" entry and no error occurs, then *pbEof is set to
|
||||
@@ -5738,7 +5744,7 @@ static int fts3EvalNext(Fts3Cursor *pCsr){
|
||||
}
|
||||
|
||||
/*
|
||||
** Restart iteration for expression pExpr so that the next call to
|
||||
** Restart interation for expression pExpr so that the next call to
|
||||
** fts3EvalNext() visits the first row. Do not allow incremental
|
||||
** loading or merging of phrase doclists for this iteration.
|
||||
**
|
||||
|
||||
+12
-32
@@ -14,20 +14,10 @@
|
||||
#ifndef _FTSINT_H
|
||||
#define _FTSINT_H
|
||||
|
||||
/*
|
||||
** Activate assert() only if SQLITE_TEST is enabled.
|
||||
*/
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
# define NDEBUG 1
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* FTS3/FTS4 require virtual tables */
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
# undef SQLITE_ENABLE_FTS3
|
||||
@@ -47,7 +37,7 @@
|
||||
|
||||
/* If not building as part of the core, include sqlite3ext.h. */
|
||||
#ifndef SQLITE_CORE
|
||||
# include "sqlite3ext.h"
|
||||
# include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT3
|
||||
#endif
|
||||
|
||||
@@ -189,6 +179,13 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
|
||||
*/
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
|
||||
/*
|
||||
** Activate assert() only if SQLITE_TEST is enabled.
|
||||
*/
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
||||
# define NDEBUG 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The TESTONLY macro is used to enclose variable declarations or
|
||||
** other bits of code that are needed to support the arguments
|
||||
@@ -205,19 +202,6 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
|
||||
|
||||
#define deliberate_fall_through
|
||||
|
||||
/*
|
||||
** Macros needed to provide flexible arrays in a portable way
|
||||
*/
|
||||
#ifndef offsetof
|
||||
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
|
||||
#endif
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
#else
|
||||
# define FLEXARRAY 1
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SQLITE_AMALGAMATION */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -322,7 +306,7 @@ struct Fts3Table {
|
||||
#endif
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
/* True to disable the incremental doclist optimization. This is controlled
|
||||
/* True to disable the incremental doclist optimization. This is controled
|
||||
** by special insert command 'test-no-incr-doclist'. */
|
||||
int bNoIncrDoclist;
|
||||
|
||||
@@ -374,7 +358,7 @@ struct Fts3Cursor {
|
||||
|
||||
/*
|
||||
** The Fts3Cursor.eSearch member is always set to one of the following.
|
||||
** Actually, Fts3Cursor.eSearch can be greater than or equal to
|
||||
** Actualy, Fts3Cursor.eSearch can be greater than or equal to
|
||||
** FTS3_FULLTEXT_SEARCH. If so, then Fts3Cursor.eSearch - 2 is the index
|
||||
** of the column to be searched. For example, in
|
||||
**
|
||||
@@ -447,13 +431,9 @@ struct Fts3Phrase {
|
||||
*/
|
||||
int nToken; /* Number of tokens in the phrase */
|
||||
int iColumn; /* Index of column this phrase must match */
|
||||
Fts3PhraseToken aToken[FLEXARRAY]; /* One for each token in the phrase */
|
||||
Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts3Phrase object large enough to hold N tokens */
|
||||
#define SZ_FTS3PHRASE(N) \
|
||||
(offsetof(Fts3Phrase,aToken)+(N)*sizeof(Fts3PhraseToken))
|
||||
|
||||
/*
|
||||
** A tree of these objects forms the RHS of a MATCH operator.
|
||||
**
|
||||
|
||||
+16
-40
@@ -161,23 +161,6 @@ int sqlite3Fts3OpenTokenizer(
|
||||
*/
|
||||
static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
|
||||
|
||||
/*
|
||||
** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis
|
||||
** is defined, search for '(' and ')' as well. Return the index of the first
|
||||
** such character in the buffer. If there is no such character, return -1.
|
||||
*/
|
||||
static int findBarredChar(const char *z, int n){
|
||||
int ii;
|
||||
for(ii=0; ii<n; ii++){
|
||||
if( (z[ii]=='"')
|
||||
|| (sqlite3_fts3_enable_parentheses && (z[ii]=='(' || z[ii]==')'))
|
||||
){
|
||||
return ii;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Extract the next token from buffer z (length n) using the tokenizer
|
||||
** and other information (column names etc.) in pParse. Create an Fts3Expr
|
||||
@@ -202,9 +185,16 @@ static int getNextToken(
|
||||
int rc;
|
||||
sqlite3_tokenizer_cursor *pCursor;
|
||||
Fts3Expr *pRet = 0;
|
||||
int i = 0;
|
||||
|
||||
*pnConsumed = n;
|
||||
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
|
||||
/* Set variable i to the maximum number of bytes of input to tokenize. */
|
||||
for(i=0; i<n; i++){
|
||||
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
|
||||
if( z[i]=='"' ) break;
|
||||
}
|
||||
|
||||
*pnConsumed = i;
|
||||
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zToken;
|
||||
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
|
||||
@@ -212,18 +202,7 @@ static int getNextToken(
|
||||
|
||||
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Check that this tokenization did not gobble up any " characters. Or,
|
||||
** if enable_parenthesis is true, that it did not gobble up any
|
||||
** open or close parenthesis characters either. If it did, call
|
||||
** getNextToken() again, but pass only that part of the input buffer
|
||||
** up to the first such character. */
|
||||
int iBarred = findBarredChar(z, iEnd);
|
||||
if( iBarred>=0 ){
|
||||
pModule->xClose(pCursor);
|
||||
return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed);
|
||||
}
|
||||
|
||||
nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken;
|
||||
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
|
||||
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
|
||||
if( !pRet ){
|
||||
rc = SQLITE_NOMEM;
|
||||
@@ -233,7 +212,7 @@ static int getNextToken(
|
||||
pRet->pPhrase->nToken = 1;
|
||||
pRet->pPhrase->iColumn = iCol;
|
||||
pRet->pPhrase->aToken[0].n = nToken;
|
||||
pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1];
|
||||
pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
|
||||
memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
|
||||
|
||||
if( iEnd<n && z[iEnd]=='*' ){
|
||||
@@ -257,11 +236,7 @@ static int getNextToken(
|
||||
|
||||
}
|
||||
*pnConsumed = iEnd;
|
||||
}else if( n && rc==SQLITE_DONE ){
|
||||
int iBarred = findBarredChar(z, n);
|
||||
if( iBarred>=0 ){
|
||||
*pnConsumed = iBarred;
|
||||
}
|
||||
}else if( i && rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -308,9 +283,9 @@ static int getNextString(
|
||||
Fts3Expr *p = 0;
|
||||
sqlite3_tokenizer_cursor *pCursor = 0;
|
||||
char *zTemp = 0;
|
||||
i64 nTemp = 0;
|
||||
int nTemp = 0;
|
||||
|
||||
const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1);
|
||||
const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
|
||||
int nToken = 0;
|
||||
|
||||
/* The final Fts3Expr data structure, including the Fts3Phrase,
|
||||
@@ -682,7 +657,7 @@ static int fts3ExprParse(
|
||||
|
||||
/* The isRequirePhrase variable is set to true if a phrase or
|
||||
** an expression contained in parenthesis is required. If a
|
||||
** binary operator (AND, OR, NOT or NEAR) is encountered when
|
||||
** binary operator (AND, OR, NOT or NEAR) is encounted when
|
||||
** isRequirePhrase is set, this is a syntax error.
|
||||
*/
|
||||
if( !isPhrase && isRequirePhrase ){
|
||||
@@ -1264,6 +1239,7 @@ static void fts3ExprTestCommon(
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
|
||||
sqlite3Fts3ExprFree(pExpr);
|
||||
sqlite3_result_error(context, "Error parsing expression", -1);
|
||||
}else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
|
||||
@@ -187,7 +187,7 @@ static void fts3HashInsertElement(
|
||||
}
|
||||
|
||||
|
||||
/* Resize the hash table so that it contains "new_size" buckets.
|
||||
/* Resize the hash table so that it cantains "new_size" buckets.
|
||||
** "new_size" must be a power of 2. The hash table might fail
|
||||
** to resize if sqliteMalloc() fails.
|
||||
**
|
||||
|
||||
@@ -256,7 +256,7 @@ static int star_oh(const char *z){
|
||||
|
||||
/*
|
||||
** If the word ends with zFrom and xCond() is true for the stem
|
||||
** of the word that precedes the zFrom ending, then change the
|
||||
** of the word that preceeds the zFrom ending, then change the
|
||||
** ending to zTo.
|
||||
**
|
||||
** The input word *pz and zFrom are both in reverse order. zTo
|
||||
|
||||
+19
-19
@@ -17,6 +17,10 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
typedef sqlite3_int64 i64;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Characters that may appear in the second argument to matchinfo().
|
||||
*/
|
||||
@@ -104,13 +108,9 @@ struct MatchinfoBuffer {
|
||||
int nElem;
|
||||
int bGlobal; /* Set if global data is loaded */
|
||||
char *zMatchinfo;
|
||||
u32 aMI[FLEXARRAY];
|
||||
u32 aMatchinfo[1];
|
||||
};
|
||||
|
||||
/* Size (in bytes) of a MatchinfoBuffer sufficient for N elements */
|
||||
#define SZ_MATCHINFOBUFFER(N) \
|
||||
(offsetof(MatchinfoBuffer,aMI)+(((N)+1)/2)*sizeof(u64))
|
||||
|
||||
|
||||
/*
|
||||
** The snippet() and offsets() functions both return text values. An instance
|
||||
@@ -135,13 +135,13 @@ struct StrBuffer {
|
||||
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
|
||||
MatchinfoBuffer *pRet;
|
||||
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
|
||||
+ SZ_MATCHINFOBUFFER(1);
|
||||
+ sizeof(MatchinfoBuffer);
|
||||
sqlite3_int64 nStr = strlen(zMatchinfo);
|
||||
|
||||
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
|
||||
if( pRet ){
|
||||
pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet;
|
||||
pRet->aMI[1+nElem] = pRet->aMI[0]
|
||||
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
|
||||
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
|
||||
+ sizeof(u32)*((int)nElem+1);
|
||||
pRet->nElem = (int)nElem;
|
||||
pRet->zMatchinfo = ((char*)pRet) + nByte;
|
||||
@@ -155,10 +155,10 @@ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
|
||||
static void fts3MIBufferFree(void *p){
|
||||
MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
|
||||
|
||||
assert( (u32*)p==&pBuf->aMI[1]
|
||||
|| (u32*)p==&pBuf->aMI[pBuf->nElem+2]
|
||||
assert( (u32*)p==&pBuf->aMatchinfo[1]
|
||||
|| (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
|
||||
);
|
||||
if( (u32*)p==&pBuf->aMI[1] ){
|
||||
if( (u32*)p==&pBuf->aMatchinfo[1] ){
|
||||
pBuf->aRef[1] = 0;
|
||||
}else{
|
||||
pBuf->aRef[2] = 0;
|
||||
@@ -175,18 +175,18 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
|
||||
|
||||
if( p->aRef[1]==0 ){
|
||||
p->aRef[1] = 1;
|
||||
aOut = &p->aMI[1];
|
||||
aOut = &p->aMatchinfo[1];
|
||||
xRet = fts3MIBufferFree;
|
||||
}
|
||||
else if( p->aRef[2]==0 ){
|
||||
p->aRef[2] = 1;
|
||||
aOut = &p->aMI[p->nElem+2];
|
||||
aOut = &p->aMatchinfo[p->nElem+2];
|
||||
xRet = fts3MIBufferFree;
|
||||
}else{
|
||||
aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
|
||||
if( aOut ){
|
||||
xRet = sqlite3_free;
|
||||
if( p->bGlobal ) memcpy(aOut, &p->aMI[1], p->nElem*sizeof(u32));
|
||||
if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
|
||||
|
||||
static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
|
||||
p->bGlobal = 1;
|
||||
memcpy(&p->aMI[2+p->nElem], &p->aMI[1], p->nElem*sizeof(u32));
|
||||
memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -611,7 +611,7 @@ static int fts3StringAppend(
|
||||
}
|
||||
|
||||
/* If there is insufficient space allocated at StrBuffer.z, use realloc()
|
||||
** to grow the buffer until so that it is big enough to accommodate the
|
||||
** to grow the buffer until so that it is big enough to accomadate the
|
||||
** appended data.
|
||||
*/
|
||||
if( pStr->n+nAppend+1>=pStr->nAlloc ){
|
||||
@@ -1023,16 +1023,16 @@ static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
|
||||
break;
|
||||
|
||||
case FTS3_MATCHINFO_LHITS:
|
||||
nVal = (size_t)pInfo->nCol * pInfo->nPhrase;
|
||||
nVal = pInfo->nCol * pInfo->nPhrase;
|
||||
break;
|
||||
|
||||
case FTS3_MATCHINFO_LHITS_BM:
|
||||
nVal = (size_t)pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
|
||||
nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( cArg==FTS3_MATCHINFO_HITS );
|
||||
nVal = (size_t)pInfo->nCol * pInfo->nPhrase * 3;
|
||||
nVal = pInfo->nCol * pInfo->nPhrase * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ static int SQLITE_TCLAPI fts3_near_match_cmd(
|
||||
rc = Tcl_ListObjGetElements(interp, pPhrase, &nToken, &apToken);
|
||||
if( rc!=TCL_OK ) goto near_match_out;
|
||||
if( nToken>NM_MAX_TOKEN ){
|
||||
Tcl_AppendResult(interp, "Too many tokens in phrase", NULL);
|
||||
Tcl_AppendResult(interp, "Too many tokens in phrase", 0);
|
||||
rc = TCL_ERROR;
|
||||
goto near_match_out;
|
||||
}
|
||||
@@ -547,7 +547,7 @@ static int SQLITE_TCLAPI fts3_test_varint_cmd(
|
||||
if( w!=w2 || nByte!=nByte2 ){
|
||||
char *zErr = sqlite3_mprintf("error testing %lld", w);
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_AppendResult(interp, zErr, NULL);
|
||||
Tcl_AppendResult(interp, zErr, 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ static int SQLITE_TCLAPI fts3_test_varint_cmd(
|
||||
if( (int)w!=i || nByte!=nByte2 ){
|
||||
char *zErr = sqlite3_mprintf("error testing %lld (32-bit)", w);
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_AppendResult(interp, zErr, NULL);
|
||||
Tcl_AppendResult(interp, zErr, 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ static int fts3tokFilterMethod(
|
||||
fts3tokResetCursor(pCsr);
|
||||
if( idxNum==1 ){
|
||||
const char *zByte = (const char *)sqlite3_value_text(apVal[0]);
|
||||
sqlite3_int64 nByte = sqlite3_value_bytes(apVal[0]);
|
||||
int nByte = sqlite3_value_bytes(apVal[0]);
|
||||
pCsr->zInput = sqlite3_malloc64(nByte+1);
|
||||
if( pCsr->zInput==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
|
||||
@@ -3714,8 +3714,8 @@ struct NodeWriter {
|
||||
** to an appendable b-tree segment.
|
||||
*/
|
||||
struct IncrmergeWriter {
|
||||
i64 nLeafEst; /* Space allocated for leaf blocks */
|
||||
i64 nWork; /* Number of leaf pages flushed */
|
||||
int nLeafEst; /* Space allocated for leaf blocks */
|
||||
int nWork; /* Number of leaf pages flushed */
|
||||
sqlite3_int64 iAbsLevel; /* Absolute level of input segments */
|
||||
int iIdx; /* Index of *output* segment in iAbsLevel+1 */
|
||||
sqlite3_int64 iStart; /* Block number of first allocated block */
|
||||
@@ -3956,7 +3956,7 @@ static int fts3IncrmergePush(
|
||||
**
|
||||
** It is assumed that the buffer associated with pNode is already large
|
||||
** enough to accommodate the new entry. The buffer associated with pPrev
|
||||
** is extended by this function if required.
|
||||
** is extended by this function if requrired.
|
||||
**
|
||||
** If an error (i.e. OOM condition) occurs, an SQLite error code is
|
||||
** returned. Otherwise, SQLITE_OK.
|
||||
@@ -4461,7 +4461,7 @@ static int fts3IncrmergeWriter(
|
||||
){
|
||||
int rc; /* Return Code */
|
||||
int i; /* Iterator variable */
|
||||
i64 nLeafEst = 0; /* Blocks allocated for leaf nodes */
|
||||
int nLeafEst = 0; /* Blocks allocated for leaf nodes */
|
||||
sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */
|
||||
sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */
|
||||
|
||||
@@ -4471,7 +4471,7 @@ static int fts3IncrmergeWriter(
|
||||
sqlite3_bind_int64(pLeafEst, 1, iAbsLevel);
|
||||
sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment);
|
||||
if( SQLITE_ROW==sqlite3_step(pLeafEst) ){
|
||||
nLeafEst = sqlite3_column_int64(pLeafEst, 0);
|
||||
nLeafEst = sqlite3_column_int(pLeafEst, 0);
|
||||
}
|
||||
rc = sqlite3_reset(pLeafEst);
|
||||
}
|
||||
@@ -5619,7 +5619,7 @@ int sqlite3Fts3DeferToken(
|
||||
/*
|
||||
** SQLite value pRowid contains the rowid of a row that may or may not be
|
||||
** present in the FTS3 table. If it is, delete it and adjust the contents
|
||||
** of subsidiary data structures accordingly.
|
||||
** of subsiduary data structures accordingly.
|
||||
*/
|
||||
static int fts3DeleteByRowid(
|
||||
Fts3Table *p,
|
||||
|
||||
@@ -893,7 +893,7 @@ proc print_test_main {} {
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
# Process the command line arguments. Exit early if they are not to
|
||||
# Proces the command line arguments. Exit early if they are not to
|
||||
# our liking.
|
||||
#
|
||||
proc usage {} {
|
||||
|
||||
+15
-28
@@ -20,7 +20,6 @@ SQLITE_EXTENSION_INIT1
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
|
||||
@@ -60,34 +59,23 @@ typedef sqlite3_uint64 u64;
|
||||
# define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
|
||||
# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
|
||||
|
||||
/*
|
||||
** This macro is used in a single assert() within fts5 to check that an
|
||||
** allocation is aligned to an 8-byte boundary. But it is a complicated
|
||||
** macro to get right for multiple platforms without generating warnings.
|
||||
** So instead of reproducing the entire definition from sqliteInt.h, we
|
||||
** just do without this assert() for the rare non-amalgamation builds.
|
||||
/* The uptr type is an unsigned integer large enough to hold a pointer
|
||||
*/
|
||||
#define EIGHT_BYTE_ALIGNMENT(x) 1
|
||||
|
||||
/*
|
||||
** Macros needed to provide flexible arrays in a portable way
|
||||
*/
|
||||
#ifndef offsetof
|
||||
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
|
||||
#endif
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
# define FLEXARRAY
|
||||
#if defined(HAVE_STDINT_H)
|
||||
typedef uintptr_t uptr;
|
||||
#elif SQLITE_PTRSIZE==4
|
||||
typedef u32 uptr;
|
||||
#else
|
||||
# define FLEXARRAY 1
|
||||
typedef u64 uptr;
|
||||
#endif
|
||||
|
||||
#endif /* SQLITE_AMALGAMATION */
|
||||
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
|
||||
#else
|
||||
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Constants for the largest and smallest possible 32-bit signed integers.
|
||||
*/
|
||||
# define LARGEST_INT32 ((int)(0x7fffffff))
|
||||
# define SMALLEST_INT32 ((int)((-1) - LARGEST_INT32))
|
||||
#endif
|
||||
|
||||
/* Truncate very long tokens to this many bytes. Hard limit is
|
||||
** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
|
||||
@@ -159,11 +147,10 @@ typedef struct Fts5Colset Fts5Colset;
|
||||
*/
|
||||
struct Fts5Colset {
|
||||
int nCol;
|
||||
int aiCol[FLEXARRAY];
|
||||
int aiCol[1];
|
||||
};
|
||||
|
||||
/* Size (int bytes) of a complete Fts5Colset object with N columns. */
|
||||
#define SZ_FTS5COLSET(N) (sizeof(i64)*((N+2)/2))
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
** Interface to code in fts5_config.c. fts5_config.c contains contains code
|
||||
@@ -821,7 +808,7 @@ int sqlite3Fts5ExprPattern(
|
||||
** i64 iRowid = sqlite3Fts5ExprRowid(pExpr);
|
||||
** }
|
||||
*/
|
||||
int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, i64, int bDesc);
|
||||
int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc);
|
||||
int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax);
|
||||
int sqlite3Fts5ExprEof(Fts5Expr*);
|
||||
i64 sqlite3Fts5ExprRowid(Fts5Expr*);
|
||||
|
||||
+1
-1
@@ -667,7 +667,7 @@ static int fts5Bm25GetData(
|
||||
** under consideration.
|
||||
**
|
||||
** The problem with this is that if (N < 2*nHit), the IDF is
|
||||
** negative. Which is undesirable. So the minimum allowable IDF is
|
||||
** negative. Which is undesirable. So the mimimum allowable IDF is
|
||||
** (1e-6) - roughly the same as a term that appears in just over
|
||||
** half of set of 5,000,000 documents. */
|
||||
double idf = log( (nRow - nHit + 0.5) / (nHit + 0.5) );
|
||||
|
||||
@@ -308,7 +308,7 @@ char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){
|
||||
** * The 52 upper and lower case ASCII characters, and
|
||||
** * The 10 integer ASCII characters.
|
||||
** * The underscore character "_" (0x5F).
|
||||
** * The unicode "substitute" character (0x1A).
|
||||
** * The unicode "subsitute" character (0x1A).
|
||||
*/
|
||||
int sqlite3Fts5IsBareword(char t){
|
||||
u8 aBareword[128] = {
|
||||
|
||||
+24
-44
@@ -86,13 +86,9 @@ struct Fts5ExprNode {
|
||||
/* Child nodes. For a NOT node, this array always contains 2 entries. For
|
||||
** AND or OR nodes, it contains 2 or more entries. */
|
||||
int nChild; /* Number of child nodes */
|
||||
Fts5ExprNode *apChild[FLEXARRAY]; /* Array of child nodes */
|
||||
Fts5ExprNode *apChild[1]; /* Array of child nodes */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5ExprNode object that holds up to N children */
|
||||
#define SZ_FTS5EXPRNODE(N) \
|
||||
(offsetof(Fts5ExprNode,apChild) + (N)*sizeof(Fts5ExprNode*))
|
||||
|
||||
#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
|
||||
|
||||
/*
|
||||
@@ -123,13 +119,9 @@ struct Fts5ExprPhrase {
|
||||
Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
|
||||
Fts5Buffer poslist; /* Current position list */
|
||||
int nTerm; /* Number of entries in aTerm[] */
|
||||
Fts5ExprTerm aTerm[FLEXARRAY]; /* Terms that make up this phrase */
|
||||
Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5ExprPhrase object that holds up to N terms */
|
||||
#define SZ_FTS5EXPRPHRASE(N) \
|
||||
(offsetof(Fts5ExprPhrase,aTerm) + (N)*sizeof(Fts5ExprTerm))
|
||||
|
||||
/*
|
||||
** One or more phrases that must appear within a certain token distance of
|
||||
** each other within each matching document.
|
||||
@@ -138,12 +130,9 @@ struct Fts5ExprNearset {
|
||||
int nNear; /* NEAR parameter */
|
||||
Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
|
||||
int nPhrase; /* Number of entries in aPhrase[] array */
|
||||
Fts5ExprPhrase *apPhrase[FLEXARRAY]; /* Array of phrase pointers */
|
||||
Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5ExprNearset object covering up to N phrases */
|
||||
#define SZ_FTS5EXPRNEARSET(N) \
|
||||
(offsetof(Fts5ExprNearset,apPhrase)+(N)*sizeof(Fts5ExprPhrase*))
|
||||
|
||||
/*
|
||||
** Parse context.
|
||||
@@ -303,7 +292,7 @@ int sqlite3Fts5ExprNew(
|
||||
/* If the LHS of the MATCH expression was a user column, apply the
|
||||
** implicit column-filter. */
|
||||
if( sParse.rc==SQLITE_OK && iCol<pConfig->nCol ){
|
||||
int n = SZ_FTS5COLSET(1);
|
||||
int n = sizeof(Fts5Colset);
|
||||
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
|
||||
if( pColset ){
|
||||
pColset->nCol = 1;
|
||||
@@ -1549,13 +1538,7 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
|
||||
** Return SQLITE_OK if successful, or an SQLite error code otherwise. It
|
||||
** is not considered an error if the query does not match any documents.
|
||||
*/
|
||||
int sqlite3Fts5ExprFirst(
|
||||
Fts5Expr *p,
|
||||
Fts5Index *pIdx,
|
||||
i64 iFirst,
|
||||
i64 iLast,
|
||||
int bDesc
|
||||
){
|
||||
int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
|
||||
Fts5ExprNode *pRoot = p->pRoot;
|
||||
int rc; /* Return code */
|
||||
|
||||
@@ -1577,9 +1560,6 @@ int sqlite3Fts5ExprFirst(
|
||||
assert( pRoot->bEof==0 );
|
||||
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
|
||||
}
|
||||
if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){
|
||||
pRoot->bEof = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1670,7 +1650,7 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
if( pParse->rc==SQLITE_OK ){
|
||||
if( pNear==0 ){
|
||||
sqlite3_int64 nByte;
|
||||
nByte = SZ_FTS5EXPRNEARSET(SZALLOC+1);
|
||||
nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
|
||||
pRet = sqlite3_malloc64(nByte);
|
||||
if( pRet==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
@@ -1681,7 +1661,7 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
|
||||
int nNew = pNear->nPhrase + SZALLOC;
|
||||
sqlite3_int64 nByte;
|
||||
|
||||
nByte = SZ_FTS5EXPRNEARSET(nNew+1);
|
||||
nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
|
||||
pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
|
||||
if( pRet==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
@@ -1772,12 +1752,12 @@ static int fts5ParseTokenize(
|
||||
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
|
||||
|
||||
pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
|
||||
SZ_FTS5EXPRPHRASE(nNew+1)
|
||||
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
|
||||
);
|
||||
if( pNew==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
if( pPhrase==0 ) memset(pNew, 0, SZ_FTS5EXPRPHRASE(1));
|
||||
if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
|
||||
pCtx->pPhrase = pPhrase = pNew;
|
||||
pNew->nTerm = nNew - SZALLOC;
|
||||
}
|
||||
@@ -1885,7 +1865,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
if( sCtx.pPhrase==0 ){
|
||||
/* This happens when parsing a token or quoted phrase that contains
|
||||
** no token characters at all. (e.g ... MATCH '""'). */
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, SZ_FTS5EXPRPHRASE(1));
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
|
||||
}else if( sCtx.pPhrase->nTerm ){
|
||||
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
|
||||
}
|
||||
@@ -1920,18 +1900,19 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
sizeof(Fts5ExprPhrase*));
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRNODE(1));
|
||||
pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprNode));
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
|
||||
SZ_FTS5EXPRNEARSET(2));
|
||||
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
|
||||
}
|
||||
if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
|
||||
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
|
||||
if( pColsetOrig ){
|
||||
sqlite3_int64 nByte;
|
||||
Fts5Colset *pColset;
|
||||
nByte = SZ_FTS5COLSET(pColsetOrig->nCol);
|
||||
nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
|
||||
pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
if( pColset ){
|
||||
memcpy(pColset, pColsetOrig, (size_t)nByte);
|
||||
@@ -1959,7 +1940,7 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
}else{
|
||||
/* This happens when parsing a token or quoted phrase that contains
|
||||
** no token characters at all. (e.g ... MATCH '""'). */
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRPHRASE(1));
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2024,8 +2005,7 @@ void sqlite3Fts5ParseSetDistance(
|
||||
);
|
||||
return;
|
||||
}
|
||||
if( nNear<214748363 ) nNear = nNear * 10 + (p->p[i] - '0');
|
||||
/* ^^^^^^^^^^^^^^^--- Prevent integer overflow */
|
||||
nNear = nNear * 10 + (p->p[i] - '0');
|
||||
}
|
||||
}else{
|
||||
nNear = FTS5_DEFAULT_NEARDIST;
|
||||
@@ -2054,7 +2034,7 @@ static Fts5Colset *fts5ParseColset(
|
||||
assert( pParse->rc==SQLITE_OK );
|
||||
assert( iCol>=0 && iCol<pParse->pConfig->nCol );
|
||||
|
||||
pNew = sqlite3_realloc64(p, SZ_FTS5COLSET(nCol+1));
|
||||
pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
|
||||
if( pNew==0 ){
|
||||
pParse->rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
@@ -2089,7 +2069,7 @@ Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
|
||||
int nCol = pParse->pConfig->nCol;
|
||||
|
||||
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
|
||||
SZ_FTS5COLSET(nCol+1)
|
||||
sizeof(Fts5Colset) + sizeof(int)*nCol
|
||||
);
|
||||
if( pRet ){
|
||||
int i;
|
||||
@@ -2150,7 +2130,7 @@ Fts5Colset *sqlite3Fts5ParseColset(
|
||||
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
|
||||
Fts5Colset *pRet;
|
||||
if( pOrig ){
|
||||
sqlite3_int64 nByte = SZ_FTS5COLSET(pOrig->nCol);
|
||||
sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
|
||||
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
|
||||
if( pRet ){
|
||||
memcpy(pRet, pOrig, (size_t)nByte);
|
||||
@@ -2318,7 +2298,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
|
||||
assert( pNear->nPhrase==1 );
|
||||
assert( pParse->bPhraseToAnd );
|
||||
|
||||
nByte = SZ_FTS5EXPRNODE(nTerm+1);
|
||||
nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
|
||||
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
|
||||
if( pRet ){
|
||||
pRet->eType = FTS5_AND;
|
||||
@@ -2328,7 +2308,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
|
||||
pParse->nPhrase--;
|
||||
for(ii=0; ii<nTerm; ii++){
|
||||
Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
|
||||
&pParse->rc, SZ_FTS5EXPRPHRASE(1)
|
||||
&pParse->rc, sizeof(Fts5ExprPhrase)
|
||||
);
|
||||
if( pPhrase ){
|
||||
if( parseGrowPhraseArray(pParse) ){
|
||||
@@ -2397,7 +2377,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
|
||||
if( pRight->eType==eType ) nChild += pRight->nChild-1;
|
||||
}
|
||||
|
||||
nByte = SZ_FTS5EXPRNODE(nChild);
|
||||
nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
|
||||
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
|
||||
|
||||
if( pRet ){
|
||||
@@ -3272,7 +3252,7 @@ int sqlite3Fts5ExprInstToken(
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the token mappings for all Fts5IndexIter objects managed by
|
||||
** Clear the token mappings for all Fts5IndexIter objects mannaged by
|
||||
** the expression passed as the only argument.
|
||||
*/
|
||||
void sqlite3Fts5ExprClearTokens(Fts5Expr *pExpr){
|
||||
|
||||
@@ -20,7 +20,7 @@ typedef struct Fts5HashEntry Fts5HashEntry;
|
||||
|
||||
/*
|
||||
** This file contains the implementation of an in-memory hash table used
|
||||
** to accumulate "term -> doclist" content before it is flushed to a level-0
|
||||
** to accumuluate "term -> doclist" content before it is flused to a level-0
|
||||
** segment.
|
||||
*/
|
||||
|
||||
@@ -77,7 +77,7 @@ struct Fts5HashEntry {
|
||||
};
|
||||
|
||||
/*
|
||||
** Equivalent to:
|
||||
** Eqivalent to:
|
||||
**
|
||||
** char *fts5EntryKey(Fts5HashEntry *pEntry){ return zKey; }
|
||||
*/
|
||||
|
||||
+96
-179
@@ -422,13 +422,9 @@ struct Fts5Structure {
|
||||
u64 nOriginCntr; /* Origin value for next top-level segment */
|
||||
int nSegment; /* Total segments in this structure */
|
||||
int nLevel; /* Number of levels in this index */
|
||||
Fts5StructureLevel aLevel[FLEXARRAY]; /* Array of nLevel level objects */
|
||||
Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5Structure object holding up to N levels */
|
||||
#define SZ_FTS5STRUCTURE(N) \
|
||||
(offsetof(Fts5Structure,aLevel) + (N)*sizeof(Fts5StructureLevel))
|
||||
|
||||
/*
|
||||
** An object of type Fts5SegWriter is used to write to segments.
|
||||
*/
|
||||
@@ -554,49 +550,15 @@ struct Fts5SegIter {
|
||||
u8 bDel; /* True if the delete flag is set */
|
||||
};
|
||||
|
||||
static int fts5IndexCorruptRowid(Fts5Index *pIdx, i64 iRowid){
|
||||
pIdx->rc = FTS5_CORRUPT;
|
||||
sqlite3Fts5ConfigErrmsg(pIdx->pConfig,
|
||||
"fts5: corruption found reading blob %lld from table \"%s\"",
|
||||
iRowid, pIdx->pConfig->zName
|
||||
);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
#define FTS5_CORRUPT_ROWID(pIdx, iRowid) fts5IndexCorruptRowid(pIdx, iRowid)
|
||||
|
||||
static int fts5IndexCorruptIter(Fts5Index *pIdx, Fts5SegIter *pIter){
|
||||
pIdx->rc = FTS5_CORRUPT;
|
||||
sqlite3Fts5ConfigErrmsg(pIdx->pConfig,
|
||||
"fts5: corruption on page %d, segment %d, table \"%s\"",
|
||||
pIter->iLeafPgno, pIter->pSeg->iSegid, pIdx->pConfig->zName
|
||||
);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
#define FTS5_CORRUPT_ITER(pIdx, pIter) fts5IndexCorruptIter(pIdx, pIter)
|
||||
|
||||
static int fts5IndexCorruptIdx(Fts5Index *pIdx){
|
||||
pIdx->rc = FTS5_CORRUPT;
|
||||
sqlite3Fts5ConfigErrmsg(pIdx->pConfig,
|
||||
"fts5: corruption in table \"%s\"", pIdx->pConfig->zName
|
||||
);
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
#define FTS5_CORRUPT_IDX(pIdx) fts5IndexCorruptIdx(pIdx)
|
||||
|
||||
|
||||
/*
|
||||
** Array of tombstone pages. Reference counted.
|
||||
*/
|
||||
struct Fts5TombstoneArray {
|
||||
int nRef; /* Number of pointers to this object */
|
||||
int nRef; /* Number of pointers to this object */
|
||||
int nTombstone;
|
||||
Fts5Data *apTombstone[FLEXARRAY]; /* Array of tombstone pages */
|
||||
Fts5Data *apTombstone[1]; /* Array of tombstone pages */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5TombstoneArray holding up to N tombstones */
|
||||
#define SZ_FTS5TOMBSTONEARRAY(N) \
|
||||
(offsetof(Fts5TombstoneArray,apTombstone)+(N)*sizeof(Fts5Data*))
|
||||
|
||||
/*
|
||||
** Argument is a pointer to an Fts5Data structure that contains a
|
||||
** leaf page.
|
||||
@@ -665,12 +627,9 @@ struct Fts5Iter {
|
||||
|
||||
i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
|
||||
Fts5CResult *aFirst; /* Current merge state (see above) */
|
||||
Fts5SegIter aSeg[FLEXARRAY]; /* Array of segment iterators */
|
||||
Fts5SegIter aSeg[1]; /* Array of segment iterators */
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5Iter object holding up to N segment iterators */
|
||||
#define SZ_FTS5ITER(N) (offsetof(Fts5Iter,aSeg)+(N)*sizeof(Fts5SegIter))
|
||||
|
||||
/*
|
||||
** An instance of the following type is used to iterate through the contents
|
||||
** of a doclist-index record.
|
||||
@@ -697,13 +656,9 @@ struct Fts5DlidxLvl {
|
||||
struct Fts5DlidxIter {
|
||||
int nLvl;
|
||||
int iSegid;
|
||||
Fts5DlidxLvl aLvl[FLEXARRAY];
|
||||
Fts5DlidxLvl aLvl[1];
|
||||
};
|
||||
|
||||
/* Size (in bytes) of an Fts5DlidxIter object with up to N levels */
|
||||
#define SZ_FTS5DLIDXITER(N) \
|
||||
(offsetof(Fts5DlidxIter,aLvl)+(N)*sizeof(Fts5DlidxLvl))
|
||||
|
||||
static void fts5PutU16(u8 *aOut, u16 iVal){
|
||||
aOut[0] = (iVal>>8);
|
||||
aOut[1] = (iVal&0xFF);
|
||||
@@ -873,13 +828,13 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
|
||||
** All the reasons those functions might return SQLITE_ERROR - missing
|
||||
** table, missing row, non-blob/text in block column - indicate
|
||||
** backing store corruption. */
|
||||
if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
if( rc==SQLITE_ERROR ) rc = FTS5_CORRUPT;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
u8 *aOut = 0; /* Read blob data into this buffer */
|
||||
i64 nByte = sqlite3_blob_bytes(p->pReader);
|
||||
i64 szData = (sizeof(Fts5Data) + 7) & ~7;
|
||||
i64 nAlloc = szData + nByte + FTS5_DATA_PADDING;
|
||||
int nByte = sqlite3_blob_bytes(p->pReader);
|
||||
int szData = (sizeof(Fts5Data) + 7) & ~7;
|
||||
sqlite3_int64 nAlloc = szData + nByte + FTS5_DATA_PADDING;
|
||||
pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
|
||||
if( pRet ){
|
||||
pRet->nn = nByte;
|
||||
@@ -923,7 +878,7 @@ static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
|
||||
Fts5Data *pRet = fts5DataRead(p, iRowid);
|
||||
if( pRet ){
|
||||
if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
|
||||
FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
fts5DataRelease(pRet);
|
||||
pRet = 0;
|
||||
}
|
||||
@@ -1071,7 +1026,7 @@ int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
|
||||
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
|
||||
Fts5Structure *p = *pp;
|
||||
if( *pRc==SQLITE_OK && p->nRef>1 ){
|
||||
i64 nByte = SZ_FTS5STRUCTURE(p->nLevel);
|
||||
i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
|
||||
Fts5Structure *pNew;
|
||||
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
|
||||
if( pNew ){
|
||||
@@ -1145,7 +1100,10 @@ static int fts5StructureDecode(
|
||||
){
|
||||
return FTS5_CORRUPT;
|
||||
}
|
||||
nByte = SZ_FTS5STRUCTURE(nLevel);
|
||||
nByte = (
|
||||
sizeof(Fts5Structure) + /* Main structure */
|
||||
sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
|
||||
);
|
||||
pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||
|
||||
if( pRet ){
|
||||
@@ -1225,7 +1183,10 @@ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
|
||||
if( *pRc==SQLITE_OK ){
|
||||
Fts5Structure *pStruct = *ppStruct;
|
||||
int nLevel = pStruct->nLevel;
|
||||
sqlite3_int64 nByte = SZ_FTS5STRUCTURE(nLevel+2);
|
||||
sqlite3_int64 nByte = (
|
||||
sizeof(Fts5Structure) + /* Main structure */
|
||||
sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
|
||||
);
|
||||
|
||||
pStruct = sqlite3_realloc64(pStruct, nByte);
|
||||
if( pStruct ){
|
||||
@@ -1282,14 +1243,8 @@ static Fts5Structure *fts5StructureReadUncached(Fts5Index *p){
|
||||
/* TODO: Do we need this if the leaf-index is appended? Probably... */
|
||||
memset(&pData->p[pData->nn], 0, FTS5_DATA_PADDING);
|
||||
p->rc = fts5StructureDecode(pData->p, pData->nn, &iCookie, &pRet);
|
||||
if( p->rc==SQLITE_OK ){
|
||||
if( (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){
|
||||
p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie);
|
||||
}
|
||||
}else if( p->rc==SQLITE_CORRUPT_VTAB ){
|
||||
sqlite3Fts5ConfigErrmsg(p->pConfig,
|
||||
"fts5: corrupt structure record for table \"%s\"", p->pConfig->zName
|
||||
);
|
||||
if( p->rc==SQLITE_OK && (pConfig->pgsz==0 || pConfig->iCookie!=iCookie) ){
|
||||
p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie);
|
||||
}
|
||||
fts5DataRelease(pData);
|
||||
if( p->rc!=SQLITE_OK ){
|
||||
@@ -1770,7 +1725,7 @@ static Fts5DlidxIter *fts5DlidxIterInit(
|
||||
int bDone = 0;
|
||||
|
||||
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
|
||||
sqlite3_int64 nByte = SZ_FTS5DLIDXITER(i+1);
|
||||
sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
|
||||
Fts5DlidxIter *pNew;
|
||||
|
||||
pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
|
||||
@@ -1912,7 +1867,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
|
||||
while( iOff>=pIter->pLeaf->szLeaf ){
|
||||
fts5SegIterNextPage(p, pIter);
|
||||
if( pIter->pLeaf==0 ){
|
||||
if( p->rc==SQLITE_OK ) FTS5_CORRUPT_ITER(p, pIter);
|
||||
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
iOff = 4;
|
||||
@@ -1944,7 +1899,7 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
|
||||
|
||||
iOff += fts5GetVarint32(&a[iOff], nNew);
|
||||
if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
pIter->term.n = nKeep;
|
||||
@@ -1986,9 +1941,9 @@ static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
|
||||
** leave an error in the Fts5Index object.
|
||||
*/
|
||||
static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
|
||||
const i64 nTomb = (i64)pIter->pSeg->nPgTombstone;
|
||||
const int nTomb = pIter->pSeg->nPgTombstone;
|
||||
if( nTomb>0 ){
|
||||
i64 nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1);
|
||||
int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray);
|
||||
Fts5TombstoneArray *pNew;
|
||||
pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
|
||||
if( pNew ){
|
||||
@@ -2074,7 +2029,6 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||
while( 1 ){
|
||||
u64 iDelta = 0;
|
||||
|
||||
if( i>=n ) break;
|
||||
if( eDetail==FTS5_DETAIL_NONE ){
|
||||
/* todo */
|
||||
if( i<n && a[i]==0 ){
|
||||
@@ -2140,7 +2094,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||
iRowidOff = fts5LeafFirstRowidOff(pNew);
|
||||
if( iRowidOff ){
|
||||
if( iRowidOff>=pNew->szLeaf ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
pIter->pLeaf = pNew;
|
||||
pIter->iLeafOffset = iRowidOff;
|
||||
@@ -2374,7 +2328,7 @@ static void fts5SegIterNext(
|
||||
}
|
||||
assert_nc( iOff<pLeaf->szLeaf );
|
||||
if( iOff>pLeaf->szLeaf ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2482,20 +2436,18 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||
fts5DataRelease(pIter->pLeaf);
|
||||
pIter->pLeaf = pLast;
|
||||
pIter->iLeafPgno = pgnoLast;
|
||||
if( p->rc==SQLITE_OK ){
|
||||
iOff = fts5LeafFirstRowidOff(pLast);
|
||||
if( iOff>pLast->szLeaf ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
return;
|
||||
}
|
||||
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
|
||||
pIter->iLeafOffset = iOff;
|
||||
iOff = fts5LeafFirstRowidOff(pLast);
|
||||
if( iOff>pLast->szLeaf ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
|
||||
pIter->iLeafOffset = iOff;
|
||||
|
||||
if( fts5LeafIsTermless(pLast) ){
|
||||
pIter->iEndofDoclist = pLast->nn+1;
|
||||
}else{
|
||||
pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
|
||||
}
|
||||
if( fts5LeafIsTermless(pLast) ){
|
||||
pIter->iEndofDoclist = pLast->nn+1;
|
||||
}else{
|
||||
pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2565,7 +2517,7 @@ static void fts5LeafSeek(
|
||||
iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
|
||||
iOff = iTermOff;
|
||||
if( iOff>n ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2608,7 +2560,7 @@ static void fts5LeafSeek(
|
||||
iOff = iTermOff;
|
||||
|
||||
if( iOff>=n ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2630,7 +2582,7 @@ static void fts5LeafSeek(
|
||||
iPgidx = (u32)pIter->pLeaf->szLeaf;
|
||||
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
|
||||
if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}else{
|
||||
nKeep = 0;
|
||||
@@ -2645,7 +2597,7 @@ static void fts5LeafSeek(
|
||||
|
||||
search_success:
|
||||
if( (i64)iOff+nNew>n || nNew<1 ){
|
||||
FTS5_CORRUPT_ITER(p, pIter);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}
|
||||
pIter->iLeafOffset = iOff + nNew;
|
||||
@@ -3110,7 +3062,7 @@ static void fts5SegIterGotoPage(
|
||||
assert( iLeafPgno>pIter->iLeafPgno );
|
||||
|
||||
if( iLeafPgno>pIter->pSeg->pgnoLast ){
|
||||
FTS5_CORRUPT_IDX(p);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
fts5DataRelease(pIter->pNextLeaf);
|
||||
pIter->pNextLeaf = 0;
|
||||
@@ -3125,7 +3077,7 @@ static void fts5SegIterGotoPage(
|
||||
u8 *a = pIter->pLeaf->p;
|
||||
int n = pIter->pLeaf->szLeaf;
|
||||
if( iOff<4 || iOff>=n ){
|
||||
FTS5_CORRUPT_IDX(p);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid);
|
||||
pIter->iLeafOffset = iOff;
|
||||
@@ -3452,7 +3404,8 @@ static Fts5Iter *fts5MultiIterAlloc(
|
||||
|
||||
for(nSlot=2; nSlot<nSeg; nSlot=nSlot*2);
|
||||
pNew = fts5IdxMalloc(p,
|
||||
SZ_FTS5ITER(nSlot) + /* pNew + pNew->aSeg[] */
|
||||
sizeof(Fts5Iter) + /* pNew */
|
||||
sizeof(Fts5SegIter) * (nSlot-1) + /* pNew->aSeg[] */
|
||||
sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
|
||||
);
|
||||
if( pNew ){
|
||||
@@ -3604,7 +3557,7 @@ static void fts5ChunkIterate(
|
||||
if( nRem<=0 ){
|
||||
break;
|
||||
}else if( pSeg->pSeg==0 ){
|
||||
FTS5_CORRUPT_IDX(p);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
return;
|
||||
}else{
|
||||
pgno++;
|
||||
@@ -4707,7 +4660,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){
|
||||
** a single page has been assigned to more than one segment. In
|
||||
** this case a prior iteration of this loop may have corrupted the
|
||||
** segment currently being trimmed. */
|
||||
FTS5_CORRUPT_ROWID(p, iLeafRowid);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
fts5BufferZero(&buf);
|
||||
fts5BufferGrow(&p->rc, &buf, pData->nn);
|
||||
@@ -5174,7 +5127,7 @@ static void fts5SecureDeleteOverflow(
|
||||
}else if( bDetailNone ){
|
||||
break;
|
||||
}else if( iNext>=pLeaf->szLeaf || pLeaf->nn<pLeaf->szLeaf || iNext<4 ){
|
||||
FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}else{
|
||||
int nShift = iNext - 4;
|
||||
@@ -5194,7 +5147,7 @@ static void fts5SecureDeleteOverflow(
|
||||
|
||||
i1 += fts5GetVarint32(&aPg[i1], iFirst);
|
||||
if( iFirst<iNext ){
|
||||
FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
aIdx = sqlite3Fts5MallocZero(&p->rc, (pLeaf->nn-pLeaf->szLeaf)+2);
|
||||
@@ -5253,7 +5206,7 @@ static void fts5DoSecureDelete(
|
||||
int iDelKeyOff = 0; /* Offset of deleted key, if any */
|
||||
|
||||
nIdx = nPg-iPgIdx;
|
||||
aIdx = sqlite3Fts5MallocZero(&p->rc, ((i64)nIdx)+16);
|
||||
aIdx = sqlite3Fts5MallocZero(&p->rc, nIdx+16);
|
||||
if( p->rc ) return;
|
||||
memcpy(aIdx, &aPg[iPgIdx], nIdx);
|
||||
|
||||
@@ -5417,14 +5370,14 @@ static void fts5DoSecureDelete(
|
||||
nSuffix = (nPrefix2 + nSuffix2) - nPrefix;
|
||||
|
||||
if( (iKeyOff+nSuffix)>iPgIdx || (iNextOff+nSuffix2)>iPgIdx ){
|
||||
FTS5_CORRUPT_IDX(p);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
if( iKey!=1 ){
|
||||
iOff += sqlite3Fts5PutVarint(&aPg[iOff], nPrefix);
|
||||
}
|
||||
iOff += sqlite3Fts5PutVarint(&aPg[iOff], nSuffix);
|
||||
if( nPrefix2>pSeg->term.n ){
|
||||
FTS5_CORRUPT_IDX(p);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else if( nPrefix2>nPrefix ){
|
||||
memcpy(&aPg[iOff], &pSeg->term.p[nPrefix], nPrefix2-nPrefix);
|
||||
iOff += (nPrefix2-nPrefix);
|
||||
@@ -5818,7 +5771,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
|
||||
Fts5Structure *pStruct
|
||||
){
|
||||
Fts5Structure *pNew = 0;
|
||||
sqlite3_int64 nByte = SZ_FTS5STRUCTURE(1);
|
||||
sqlite3_int64 nByte = sizeof(Fts5Structure);
|
||||
int nSeg = pStruct->nSegment;
|
||||
int i;
|
||||
|
||||
@@ -5847,8 +5800,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
|
||||
assert( pStruct->aLevel[i].nMerge<=nThis );
|
||||
}
|
||||
|
||||
nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel);
|
||||
assert( nByte==(i64)SZ_FTS5STRUCTURE(pStruct->nLevel+2) );
|
||||
nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel);
|
||||
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
|
||||
|
||||
if( pNew ){
|
||||
@@ -5931,7 +5883,7 @@ int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
|
||||
fts5StructureRelease(pStruct);
|
||||
pStruct = pNew;
|
||||
nMin = 1;
|
||||
nMerge = (nMerge==SMALLEST_INT32 ? LARGEST_INT32 : (nMerge*-1));
|
||||
nMerge = nMerge*-1;
|
||||
}
|
||||
if( pStruct && pStruct->nLevel ){
|
||||
if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
|
||||
@@ -6217,7 +6169,7 @@ static void fts5MergePrefixLists(
|
||||
}
|
||||
|
||||
if( pHead==0 || pHead->pNext==0 ){
|
||||
FTS5_CORRUPT_IDX(p);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6254,7 +6206,7 @@ static void fts5MergePrefixLists(
|
||||
assert_nc( tmp.n+nTail<=nTmp );
|
||||
assert( tmp.n+nTail<=nTmp+nMerge*10 );
|
||||
if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
|
||||
if( p->rc==SQLITE_OK ) FTS5_CORRUPT_IDX(p);
|
||||
if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
|
||||
break;
|
||||
}
|
||||
fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
|
||||
@@ -6425,13 +6377,9 @@ struct Fts5TokenDataIter {
|
||||
int nIterAlloc;
|
||||
Fts5PoslistReader *aPoslistReader;
|
||||
int *aPoslistToIter;
|
||||
Fts5Iter *apIter[FLEXARRAY];
|
||||
Fts5Iter *apIter[1];
|
||||
};
|
||||
|
||||
/* Size in bytes of an Fts5TokenDataIter object holding up to N iterators */
|
||||
#define SZ_FTS5TOKENDATAITER(N) \
|
||||
(offsetof(Fts5TokenDataIter,apIter) + (N)*sizeof(Fts5Iter))
|
||||
|
||||
/*
|
||||
** The two input arrays - a1[] and a2[] - are in sorted order. This function
|
||||
** merges the two arrays together and writes the result to output array
|
||||
@@ -6503,7 +6451,7 @@ static void fts5TokendataIterAppendMap(
|
||||
/*
|
||||
** Sort the contents of the pT->aMap[] array.
|
||||
**
|
||||
** The sorting algorithm requires a malloc(). If this fails, an error code
|
||||
** The sorting algorithm requries a malloc(). If this fails, an error code
|
||||
** is left in Fts5Index.rc before returning.
|
||||
*/
|
||||
static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
|
||||
@@ -6694,7 +6642,7 @@ static void fts5SetupPrefixIter(
|
||||
&& p->pConfig->bPrefixInsttoken
|
||||
){
|
||||
s.pTokendata = &s2;
|
||||
s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, SZ_FTS5TOKENDATAITER(1));
|
||||
s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
|
||||
}
|
||||
|
||||
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
|
||||
@@ -6740,8 +6688,7 @@ static void fts5SetupPrefixIter(
|
||||
}
|
||||
}
|
||||
|
||||
pData = fts5IdxMalloc(p, sizeof(*pData)
|
||||
+ ((i64)s.doclist.n)+FTS5_DATA_ZERO_PADDING);
|
||||
pData = fts5IdxMalloc(p, sizeof(*pData)+s.doclist.n+FTS5_DATA_ZERO_PADDING);
|
||||
assert( pData!=0 || p->rc!=SQLITE_OK );
|
||||
if( pData ){
|
||||
pData->p = (u8*)&pData[1];
|
||||
@@ -6822,20 +6769,15 @@ int sqlite3Fts5IndexRollback(Fts5Index *p){
|
||||
** and the initial version of the "averages" record (a zero-byte blob).
|
||||
*/
|
||||
int sqlite3Fts5IndexReinit(Fts5Index *p){
|
||||
Fts5Structure *pTmp;
|
||||
union {
|
||||
Fts5Structure sFts;
|
||||
u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
|
||||
} uFts;
|
||||
Fts5Structure s;
|
||||
fts5StructureInvalidate(p);
|
||||
fts5IndexDiscardData(p);
|
||||
pTmp = &uFts.sFts;
|
||||
memset(uFts.tmpSpace, 0, sizeof(uFts.tmpSpace));
|
||||
memset(&s, 0, sizeof(Fts5Structure));
|
||||
if( p->pConfig->bContentlessDelete ){
|
||||
pTmp->nOriginCntr = 1;
|
||||
s.nOriginCntr = 1;
|
||||
}
|
||||
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
|
||||
fts5StructureWrite(p, pTmp);
|
||||
fts5StructureWrite(p, &s);
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
|
||||
@@ -7043,7 +6985,7 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
|
||||
if( p->rc==SQLITE_OK ){
|
||||
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
|
||||
int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
|
||||
int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
|
||||
int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter);
|
||||
Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
|
||||
|
||||
if( pNew==0 ){
|
||||
@@ -7559,8 +7501,7 @@ static int fts5SetupPrefixIterTokendata(
|
||||
|
||||
fts5BufferGrow(&p->rc, &token, nToken+1);
|
||||
assert( token.p!=0 || p->rc!=SQLITE_OK );
|
||||
ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
|
||||
SZ_FTS5TOKENDATAITER(1));
|
||||
ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
|
||||
|
||||
if( p->rc==SQLITE_OK ){
|
||||
|
||||
@@ -7691,8 +7632,7 @@ int sqlite3Fts5IndexIterWriteTokendata(
|
||||
if( pIter->nSeg>0 ){
|
||||
/* This is a prefix term iterator. */
|
||||
if( pT==0 ){
|
||||
pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
|
||||
SZ_FTS5TOKENDATAITER(1));
|
||||
pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
|
||||
pIter->pTokenDataIter = pT;
|
||||
}
|
||||
if( pT ){
|
||||
@@ -8290,27 +8230,19 @@ static int fts5TestUtf8(const char *z, int n){
|
||||
/*
|
||||
** This function is also purely an internal test. It does not contribute to
|
||||
** FTS functionality, or even the integrity-check, in any way.
|
||||
**
|
||||
** This function sets output variable (*pbFail) to true if the test fails. Or
|
||||
** leaves it unchanged if the test succeeds.
|
||||
*/
|
||||
static void fts5TestTerm(
|
||||
Fts5Index *p,
|
||||
Fts5Buffer *pPrev, /* Previous term */
|
||||
const char *z, int n, /* Possibly new term to test */
|
||||
u64 expected,
|
||||
u64 *pCksum,
|
||||
int *pbFail
|
||||
u64 *pCksum
|
||||
){
|
||||
int rc = p->rc;
|
||||
if( pPrev->n==0 ){
|
||||
fts5BufferSet(&rc, pPrev, n, (const u8*)z);
|
||||
}else
|
||||
if( *pbFail==0
|
||||
&& rc==SQLITE_OK
|
||||
&& (pPrev->n!=n || memcmp(pPrev->p, z, n))
|
||||
&& (p->pHash==0 || p->pHash->nEntry==0)
|
||||
){
|
||||
if( rc==SQLITE_OK && (pPrev->n!=n || memcmp(pPrev->p, z, n)) ){
|
||||
u64 cksum3 = *pCksum;
|
||||
const char *zTerm = (const char*)&pPrev->p[1]; /* term sans prefix-byte */
|
||||
int nTerm = pPrev->n-1; /* Size of zTerm in bytes */
|
||||
@@ -8360,7 +8292,7 @@ static void fts5TestTerm(
|
||||
fts5BufferSet(&rc, pPrev, n, (const u8*)z);
|
||||
|
||||
if( rc==SQLITE_OK && cksum3!=expected ){
|
||||
*pbFail = 1;
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
*pCksum = cksum3;
|
||||
}
|
||||
@@ -8369,7 +8301,7 @@ static void fts5TestTerm(
|
||||
|
||||
#else
|
||||
# define fts5TestDlidxReverse(x,y,z)
|
||||
# define fts5TestTerm(t,u,v,w,x,y,z)
|
||||
# define fts5TestTerm(u,v,w,x,y,z)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -8394,17 +8326,14 @@ static void fts5IndexIntegrityCheckEmpty(
|
||||
for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){
|
||||
Fts5Data *pLeaf = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
|
||||
if( pLeaf ){
|
||||
if( !fts5LeafIsTermless(pLeaf)
|
||||
|| (i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf))
|
||||
){
|
||||
FTS5_CORRUPT_ROWID(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
|
||||
}
|
||||
if( !fts5LeafIsTermless(pLeaf) ) p->rc = FTS5_CORRUPT;
|
||||
if( i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf) ) p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
fts5DataRelease(pLeaf);
|
||||
}
|
||||
}
|
||||
|
||||
static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){
|
||||
static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
|
||||
i64 iTermOff = 0;
|
||||
int ii;
|
||||
|
||||
@@ -8422,12 +8351,12 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){
|
||||
iOff = iTermOff;
|
||||
|
||||
if( iOff>=pLeaf->szLeaf ){
|
||||
FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else if( iTermOff==nIncr ){
|
||||
int nByte;
|
||||
iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
|
||||
if( (iOff+nByte)>pLeaf->szLeaf ){
|
||||
FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
|
||||
}
|
||||
@@ -8436,7 +8365,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){
|
||||
iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep);
|
||||
iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
|
||||
if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){
|
||||
FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
buf1.n = nKeep;
|
||||
fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
|
||||
@@ -8444,7 +8373,7 @@ static void fts5IntegrityCheckPgidx(Fts5Index *p, i64 iRowid, Fts5Data *pLeaf){
|
||||
|
||||
if( p->rc==SQLITE_OK ){
|
||||
res = fts5BufferCompare(&buf1, &buf2);
|
||||
if( res<=0 ) FTS5_CORRUPT_ROWID(p, iRowid);
|
||||
if( res<=0 ) p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
}
|
||||
fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p);
|
||||
@@ -8505,7 +8434,7 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
** entry even if all the terms are removed from it by secure-delete
|
||||
** operations. */
|
||||
}else{
|
||||
FTS5_CORRUPT_ROWID(p, iRow);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
|
||||
}else{
|
||||
@@ -8517,15 +8446,15 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
iOff = fts5LeafFirstTermOff(pLeaf);
|
||||
iRowidOff = fts5LeafFirstRowidOff(pLeaf);
|
||||
if( iRowidOff>=iOff || iOff>=pLeaf->szLeaf ){
|
||||
FTS5_CORRUPT_ROWID(p, iRow);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else{
|
||||
iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
|
||||
res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
|
||||
if( res==0 ) res = nTerm - nIdxTerm;
|
||||
if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow);
|
||||
if( res<0 ) p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
|
||||
fts5IntegrityCheckPgidx(p, iRow, pLeaf);
|
||||
fts5IntegrityCheckPgidx(p, pLeaf);
|
||||
}
|
||||
fts5DataRelease(pLeaf);
|
||||
if( p->rc ) break;
|
||||
@@ -8555,7 +8484,7 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
iKey = FTS5_SEGMENT_ROWID(iSegid, iPg);
|
||||
pLeaf = fts5DataRead(p, iKey);
|
||||
if( pLeaf ){
|
||||
if( fts5LeafFirstRowidOff(pLeaf)!=0 ) FTS5_CORRUPT_ROWID(p, iKey);
|
||||
if( fts5LeafFirstRowidOff(pLeaf)!=0 ) p->rc = FTS5_CORRUPT;
|
||||
fts5DataRelease(pLeaf);
|
||||
}
|
||||
}
|
||||
@@ -8570,12 +8499,12 @@ static void fts5IndexIntegrityCheckSegment(
|
||||
int iRowidOff = fts5LeafFirstRowidOff(pLeaf);
|
||||
ASSERT_SZLEAF_OK(pLeaf);
|
||||
if( iRowidOff>=pLeaf->szLeaf ){
|
||||
FTS5_CORRUPT_ROWID(p, iKey);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}else if( bSecureDelete==0 || iRowidOff>0 ){
|
||||
i64 iDlRowid = fts5DlidxIterRowid(pDlidx);
|
||||
fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid);
|
||||
if( iRowid<iDlRowid || (bSecureDelete==0 && iRowid!=iDlRowid) ){
|
||||
FTS5_CORRUPT_ROWID(p, iKey);
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
}
|
||||
fts5DataRelease(pLeaf);
|
||||
@@ -8627,7 +8556,6 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
/* Used by extra internal tests only run if NDEBUG is not defined */
|
||||
u64 cksum3 = 0; /* Checksum based on contents of indexes */
|
||||
Fts5Buffer term = {0,0,0}; /* Buffer used to hold most recent term */
|
||||
int bTestFail = 0;
|
||||
#endif
|
||||
const int flags = FTS5INDEX_QUERY_NOOUTPUT;
|
||||
|
||||
@@ -8670,7 +8598,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
char *z = (char*)fts5MultiIterTerm(pIter, &n);
|
||||
|
||||
/* If this is a new term, query for it. Update cksum3 with the results. */
|
||||
fts5TestTerm(p, &term, z, n, cksum2, &cksum3, &bTestFail);
|
||||
fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
|
||||
if( p->rc ) break;
|
||||
|
||||
if( eDetail==FTS5_DETAIL_NONE ){
|
||||
@@ -8688,26 +8616,15 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
|
||||
}
|
||||
}
|
||||
}
|
||||
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3, &bTestFail);
|
||||
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
|
||||
|
||||
fts5MultiIterFree(pIter);
|
||||
if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
sqlite3Fts5ConfigErrmsg(p->pConfig,
|
||||
"fts5: checksum mismatch for table \"%s\"", p->pConfig->zName
|
||||
);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* In SQLITE_DEBUG builds, expensive extra checks were run as part of
|
||||
** the integrity-check above. If no other errors were detected, but one
|
||||
** of these tests failed, set the result to SQLITE_CORRUPT_VTAB here. */
|
||||
if( p->rc==SQLITE_OK && bTestFail ){
|
||||
p->rc = FTS5_CORRUPT;
|
||||
}
|
||||
fts5BufferFree(&term);
|
||||
#endif
|
||||
if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
|
||||
|
||||
fts5StructureRelease(pStruct);
|
||||
#ifdef SQLITE_DEBUG
|
||||
fts5BufferFree(&term);
|
||||
#endif
|
||||
fts5BufferFree(&poslist);
|
||||
return fts5IndexReturn(p);
|
||||
}
|
||||
@@ -8749,7 +8666,7 @@ static void fts5DecodeRowid(
|
||||
|
||||
#if defined(SQLITE_TEST) || defined(SQLITE_FTS5_DEBUG)
|
||||
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
|
||||
int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid components */
|
||||
int iSegid, iHeight, iPgno, bDlidx, bTomb; /* Rowid compenents */
|
||||
fts5DecodeRowid(iKey, &bTomb, &iSegid, &bDlidx, &iHeight, &iPgno);
|
||||
|
||||
if( iSegid==0 ){
|
||||
@@ -8995,7 +8912,7 @@ static void fts5DecodeFunction(
|
||||
** buffer overreads even if the record is corrupt. */
|
||||
n = sqlite3_value_bytes(apVal[1]);
|
||||
aBlob = sqlite3_value_blob(apVal[1]);
|
||||
nSpace = ((i64)n) + FTS5_DATA_ZERO_PADDING;
|
||||
nSpace = n + FTS5_DATA_ZERO_PADDING;
|
||||
a = (u8*)sqlite3Fts5MallocZero(&rc, nSpace);
|
||||
if( a==0 ) goto decode_out;
|
||||
if( n>0 ) memcpy(a, aBlob, n);
|
||||
|
||||
+22
-45
@@ -170,11 +170,9 @@ struct Fts5Sorter {
|
||||
i64 iRowid; /* Current rowid */
|
||||
const u8 *aPoslist; /* Position lists for current row */
|
||||
int nIdx; /* Number of entries in aIdx[] */
|
||||
int aIdx[FLEXARRAY]; /* Offsets into aPoslist for current row */
|
||||
int aIdx[1]; /* Offsets into aPoslist for current row */
|
||||
};
|
||||
|
||||
/* Size (int bytes) of an Fts5Sorter object with N indexes */
|
||||
#define SZ_FTS5SORTER(N) (offsetof(Fts5Sorter,nIdx)+((N+2)/2)*sizeof(i64))
|
||||
|
||||
/*
|
||||
** Virtual-table cursor object.
|
||||
@@ -511,17 +509,6 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
|
||||
#endif
|
||||
}
|
||||
|
||||
static void fts5SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
|
||||
#if SQLITE_VERSION_NUMBER>=3008002
|
||||
#ifndef SQLITE_CORE
|
||||
if( sqlite3_libversion_number()>=3008002 )
|
||||
#endif
|
||||
{
|
||||
pIdxInfo->estimatedRows = nRow;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int fts5UsePatternMatch(
|
||||
Fts5Config *pConfig,
|
||||
struct sqlite3_index_constraint *p
|
||||
@@ -657,7 +644,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
nSeenMatch++;
|
||||
idxStr[iIdxStr++] = 'M';
|
||||
sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
|
||||
iIdxStr += (int)strlen(&idxStr[iIdxStr]);
|
||||
idxStr += strlen(&idxStr[iIdxStr]);
|
||||
assert( idxStr[iIdxStr]=='\0' );
|
||||
}
|
||||
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
||||
@@ -676,7 +663,6 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
idxStr[iIdxStr++] = '=';
|
||||
bSeenEq = 1;
|
||||
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
||||
pInfo->aConstraintUsage[i].omit = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -724,21 +710,17 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
|
||||
/* Calculate the estimated cost based on the flags set in idxFlags. */
|
||||
if( bSeenEq ){
|
||||
pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0;
|
||||
fts5SetUniqueFlag(pInfo);
|
||||
fts5SetEstimatedRows(pInfo, 1);
|
||||
pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
|
||||
if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
|
||||
}else if( bSeenLt && bSeenGt ){
|
||||
pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
|
||||
}else if( bSeenLt || bSeenGt ){
|
||||
pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
|
||||
}else{
|
||||
if( bSeenLt && bSeenGt ){
|
||||
pInfo->estimatedCost = nSeenMatch ? 5000.0 : 750000.0;
|
||||
}else if( bSeenLt || bSeenGt ){
|
||||
pInfo->estimatedCost = nSeenMatch ? 7500.0 : 2250000.0;
|
||||
}else{
|
||||
pInfo->estimatedCost = nSeenMatch ? 10000.0 : 3000000.0;
|
||||
}
|
||||
for(i=1; i<nSeenMatch; i++){
|
||||
pInfo->estimatedCost *= 0.4;
|
||||
}
|
||||
fts5SetEstimatedRows(pInfo, (i64)(pInfo->estimatedCost / 4.0));
|
||||
pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
|
||||
}
|
||||
for(i=1; i<nSeenMatch; i++){
|
||||
pInfo->estimatedCost *= 0.4;
|
||||
}
|
||||
|
||||
pInfo->idxNum = idxFlags;
|
||||
@@ -937,9 +919,7 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
|
||||
int bDesc = pCsr->bDesc;
|
||||
i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
|
||||
|
||||
rc = sqlite3Fts5ExprFirst(
|
||||
pCsr->pExpr, pTab->p.pIndex, iRowid, pCsr->iLastRowid, bDesc
|
||||
);
|
||||
rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc);
|
||||
if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
|
||||
*pbSkip = 1;
|
||||
}
|
||||
@@ -1070,7 +1050,7 @@ static int fts5CursorFirstSorted(
|
||||
const char *zRankArgs = pCsr->zRankArgs;
|
||||
|
||||
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
|
||||
nByte = SZ_FTS5SORTER(nPhrase);
|
||||
nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
|
||||
pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
|
||||
if( pSorter==0 ) return SQLITE_NOMEM;
|
||||
memset(pSorter, 0, (size_t)nByte);
|
||||
@@ -1111,9 +1091,7 @@ static int fts5CursorFirstSorted(
|
||||
static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
|
||||
int rc;
|
||||
Fts5Expr *pExpr = pCsr->pExpr;
|
||||
rc = sqlite3Fts5ExprFirst(
|
||||
pExpr, pTab->p.pIndex, pCsr->iFirstRowid, pCsr->iLastRowid, bDesc
|
||||
);
|
||||
rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc);
|
||||
if( sqlite3Fts5ExprEof(pExpr) ){
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
||||
}
|
||||
@@ -3621,9 +3599,9 @@ static void fts5LocaleFunc(
|
||||
sqlite3_value **apArg /* Function arguments */
|
||||
){
|
||||
const char *zLocale = 0;
|
||||
i64 nLocale = 0;
|
||||
int nLocale = 0;
|
||||
const char *zText = 0;
|
||||
i64 nText = 0;
|
||||
int nText = 0;
|
||||
|
||||
assert( nArg==2 );
|
||||
UNUSED_PARAM(nArg);
|
||||
@@ -3640,10 +3618,10 @@ static void fts5LocaleFunc(
|
||||
Fts5Global *p = (Fts5Global*)sqlite3_user_data(pCtx);
|
||||
u8 *pBlob = 0;
|
||||
u8 *pCsr = 0;
|
||||
i64 nBlob = 0;
|
||||
int nBlob = 0;
|
||||
|
||||
nBlob = FTS5_LOCALE_HDR_SIZE + nLocale + 1 + nText;
|
||||
pBlob = (u8*)sqlite3_malloc64(nBlob);
|
||||
pBlob = (u8*)sqlite3_malloc(nBlob);
|
||||
if( pBlob==0 ){
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
return;
|
||||
@@ -3721,9 +3699,8 @@ static int fts5IntegrityMethod(
|
||||
" FTS5 table %s.%s: %s",
|
||||
zSchema, zTabname, sqlite3_errstr(rc));
|
||||
}
|
||||
}else if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
|
||||
pTab->p.pConfig->pzErrmsg = 0;
|
||||
|
||||
@@ -3824,8 +3801,8 @@ static int fts5Init(sqlite3 *db){
|
||||
** its entry point to enable the matchinfo() demo. */
|
||||
#ifdef SQLITE_FTS5_ENABLE_TEST_MI
|
||||
if( rc==SQLITE_OK ){
|
||||
extern int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api*);
|
||||
rc = sqlite3Fts5TestRegisterMatchinfoAPI(&pGlobal->api);
|
||||
extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*);
|
||||
rc = sqlite3Fts5TestRegisterMatchinfo(db);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+5
-18
@@ -539,7 +539,6 @@ static int fts5StorageDeleteFromIndex(
|
||||
for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){
|
||||
if( pConfig->abUnindexed[iCol-1]==0 ){
|
||||
sqlite3_value *pVal = 0;
|
||||
sqlite3_value *pFree = 0;
|
||||
const char *pText = 0;
|
||||
int nText = 0;
|
||||
const char *pLoc = 0;
|
||||
@@ -556,22 +555,11 @@ static int fts5StorageDeleteFromIndex(
|
||||
if( pConfig->bLocale && sqlite3Fts5IsLocaleValue(pConfig, pVal) ){
|
||||
rc = sqlite3Fts5DecodeLocaleValue(pVal, &pText, &nText, &pLoc, &nLoc);
|
||||
}else{
|
||||
if( sqlite3_value_type(pVal)!=SQLITE_TEXT ){
|
||||
/* Make a copy of the value to work with. This is because the call
|
||||
** to sqlite3_value_text() below forces the type of the value to
|
||||
** SQLITE_TEXT, and we may need to use it again later. */
|
||||
pFree = pVal = sqlite3_value_dup(pVal);
|
||||
if( pVal==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->bLocale && pSeek ){
|
||||
pLoc = (const char*)sqlite3_column_text(pSeek, iCol+pConfig->nCol);
|
||||
nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
|
||||
}
|
||||
pText = (const char*)sqlite3_value_text(pVal);
|
||||
nText = sqlite3_value_bytes(pVal);
|
||||
if( pConfig->bLocale && pSeek ){
|
||||
pLoc = (const char*)sqlite3_column_text(pSeek, iCol + pConfig->nCol);
|
||||
nLoc = sqlite3_column_bytes(pSeek, iCol + pConfig->nCol);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,7 +575,6 @@ static int fts5StorageDeleteFromIndex(
|
||||
}
|
||||
sqlite3Fts5ClearLocale(pConfig);
|
||||
}
|
||||
sqlite3_value_free(pFree);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && p->nTotalRow<1 ){
|
||||
|
||||
+11
-23
@@ -14,7 +14,7 @@
|
||||
** versions of FTS5. It contains the implementation of an FTS5 auxiliary
|
||||
** function very similar to the FTS4 function matchinfo():
|
||||
**
|
||||
** https://sqlite.org/fts3.html#matchinfo
|
||||
** https://www.sqlite.org/fts3.html#matchinfo
|
||||
**
|
||||
** Known differences are that:
|
||||
**
|
||||
@@ -393,13 +393,17 @@ static void fts5MatchinfoFunc(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Register "matchinfo" with global API object pApi.
|
||||
*/
|
||||
int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api *pApi){
|
||||
int rc;
|
||||
int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
|
||||
int rc; /* Return code */
|
||||
fts5_api *pApi; /* FTS5 API functions */
|
||||
|
||||
/* If fts5_api_from_db() returned NULL, then either FTS5 is not registered
|
||||
/* Extract the FTS5 API pointer from the database handle. The
|
||||
** fts5_api_from_db() function above is copied verbatim from the
|
||||
** FTS5 documentation. Refer there for details. */
|
||||
rc = fts5_api_from_db(db, &pApi);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
/* If fts5_api_from_db() returns NULL, then either FTS5 is not registered
|
||||
** with this database handle, or an error (OOM perhaps?) has occurred.
|
||||
**
|
||||
** Also check that the fts5_api object is version 2 or newer.
|
||||
@@ -414,20 +418,4 @@ int sqlite3Fts5TestRegisterMatchinfoAPI(fts5_api *pApi){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Register "matchinfo" with database handle db.
|
||||
*/
|
||||
int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
|
||||
int rc; /* Return code */
|
||||
fts5_api *pApi; /* FTS5 API functions */
|
||||
|
||||
/* Extract the FTS5 API pointer from the database handle. The
|
||||
** fts5_api_from_db() function above is copied verbatim from the
|
||||
** FTS5 documentation. Refer there for details. */
|
||||
rc = fts5_api_from_db(db, &pApi);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
return sqlite3Fts5TestRegisterMatchinfoAPI(pApi);
|
||||
}
|
||||
|
||||
#endif /* SQLITE_ENABLE_FTS5 */
|
||||
|
||||
@@ -778,3 +778,4 @@ void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
|
||||
}
|
||||
aAscii[0] = 0; /* 0x00 is never a token character */
|
||||
}
|
||||
|
||||
|
||||
+3
-14
@@ -193,12 +193,12 @@ static int fts5VocabInitVtab(
|
||||
*pzErr = sqlite3_mprintf("wrong number of vtable arguments");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
i64 nByte; /* Bytes of space to allocate */
|
||||
int nByte; /* Bytes of space to allocate */
|
||||
const char *zDb = bDb ? argv[3] : argv[1];
|
||||
const char *zTab = bDb ? argv[4] : argv[3];
|
||||
const char *zType = bDb ? argv[5] : argv[4];
|
||||
i64 nDb = strlen(zDb)+1;
|
||||
i64 nTab = strlen(zTab)+1;
|
||||
int nDb = (int)strlen(zDb)+1;
|
||||
int nTab = (int)strlen(zTab)+1;
|
||||
int eType = 0;
|
||||
|
||||
rc = fts5VocabTableType(zType, pzErr, &eType);
|
||||
@@ -396,12 +396,7 @@ static int fts5VocabOpenMethod(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Restore cursor pCsr to the state it was in immediately after being
|
||||
** created by the xOpen() method.
|
||||
*/
|
||||
static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
|
||||
int nCol = pCsr->pFts5->pConfig->nCol;
|
||||
pCsr->rowid = 0;
|
||||
sqlite3Fts5IterClose(pCsr->pIter);
|
||||
sqlite3Fts5StructureRelease(pCsr->pStruct);
|
||||
@@ -411,12 +406,6 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
|
||||
pCsr->nLeTerm = -1;
|
||||
pCsr->zLeTerm = 0;
|
||||
pCsr->bEof = 0;
|
||||
pCsr->iCol = 0;
|
||||
pCsr->iInstPos = 0;
|
||||
pCsr->iInstOff = 0;
|
||||
pCsr->colUsed = 0;
|
||||
memset(pCsr->aCnt, 0, sizeof(i64)*nCol);
|
||||
memset(pCsr->aDoc, 0, sizeof(i64)*nCol);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -428,7 +428,7 @@ do_execsql_test 15.1 {
|
||||
}
|
||||
do_catchsql_test 15.2 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
} {1 {fts5: checksum mismatch for table "t1"}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -294,39 +294,6 @@ do_execsql_test 7.0 {
|
||||
INSERT INTO x1 VALUES($doc);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Forum post: https://sqlite.org/forum/forumpost/ea4d8c9acb
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.0 {
|
||||
PRAGMA encoding = 'UTF-16le';
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
}
|
||||
set v [db one {SELECT x'2a12'}]
|
||||
do_execsql_test 8.1 {
|
||||
INSERT INTO vt0 VALUES ($v);
|
||||
}
|
||||
do_execsql_test 8.2 {
|
||||
SELECT quote(c0) FROM vt0
|
||||
} {X'2A12'}
|
||||
do_execsql_test 8.3 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
} {}
|
||||
reset_db
|
||||
do_execsql_test 8.4 {
|
||||
PRAGMA encoding = 'UTF-16le';
|
||||
CREATE VIRTUAL TABLE vt0 USING fts5(c0);
|
||||
}
|
||||
do_execsql_test 8.5 {
|
||||
INSERT INTO vt0 VALUES (x'2a12');
|
||||
}
|
||||
do_execsql_test 8.6 {
|
||||
SELECT quote(c0) FROM vt0
|
||||
} {X'2A12'}
|
||||
do_execsql_test 8.7 {
|
||||
INSERT INTO vt0(vt0) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
} ;# foreach_detail_mode...
|
||||
|
||||
|
||||
|
||||
@@ -47,10 +47,11 @@ do_test 1.3 {
|
||||
DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4);
|
||||
}
|
||||
catchsql { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
} {1 {fts5: corruption found reading blob 137438953476 from table "t1"}}
|
||||
} {1 {database disk image is malformed}}
|
||||
do_execsql_test 1.3b {
|
||||
PRAGMA integrity_check(t1);
|
||||
} {{fts5: corruption found reading blob 137438953476 from table "t1"}}
|
||||
} {{malformed inverted index for FTS5 table main.t1}}
|
||||
|
||||
|
||||
do_test 1.4 {
|
||||
db_restore_and_reopen
|
||||
@@ -60,7 +61,7 @@ do_test 1.4 {
|
||||
rowid = fts5_rowid('segment', $segid, 4);
|
||||
}
|
||||
catchsql { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
} {1 {fts5: corruption found reading blob 137438953476 from table "t1"}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
db_restore_and_reopen
|
||||
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
|
||||
|
||||
@@ -109,12 +109,12 @@ for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} {
|
||||
|
||||
do_catchsql_test 2.$i.2 {
|
||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||
} {/1.*fts5: corruption.*/}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_test 2.$i.3 {
|
||||
set res [catchsql {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'}]
|
||||
expr {
|
||||
[string match {*fts5: corruption*} $res]
|
||||
$res=="1 {database disk image is malformed}"
|
||||
|| $res=="0 {$all}"
|
||||
}
|
||||
} 1
|
||||
@@ -160,17 +160,17 @@ foreach {tn hdr} {
|
||||
close $fd
|
||||
|
||||
set res [catchsql {SELECT rowid FROM x3 WHERE x3 MATCH 'x AND a'}]
|
||||
if {[string match {*fts5: corruption*} $res]} {incr nCorrupt}
|
||||
if {$res == "1 {database disk image is malformed}"} {incr nCorrupt}
|
||||
set {} 1
|
||||
} {1}
|
||||
|
||||
if {($tn2 % 10)==0 && $existing != $hdr} {
|
||||
do_test 3.$tn.$tn2.2 {
|
||||
catchsql { INSERT INTO x3(x3) VALUES('integrity-check') }
|
||||
} {/.*fts5: corruption.*/}
|
||||
} {1 {database disk image is malformed}}
|
||||
do_execsql_test 3.$tn.$tn2.3 {
|
||||
PRAGMA integrity_check(x3);
|
||||
} {/.*fts5: corruption.*/}
|
||||
} {{malformed inverted index for FTS5 table main.x3}}
|
||||
}
|
||||
|
||||
execsql ROLLBACK
|
||||
@@ -209,7 +209,7 @@ foreach {tn nCut} {
|
||||
set res [catchsql {
|
||||
SELECT rowid FROM x4 WHERE x4 MATCH 'a' ORDER BY 1 DESC
|
||||
}]
|
||||
if {[string match {*fts5: corruption*} $res]} {incr nCorrupt}
|
||||
if {$res == "1 {database disk image is malformed}"} {incr nCorrupt}
|
||||
set {} 1
|
||||
} {1}
|
||||
|
||||
|
||||
+43
-616
File diff suppressed because one or more lines are too long
@@ -237,7 +237,7 @@ do_test 1.0 {
|
||||
|
||||
do_catchsql_test 1.1 {
|
||||
SELECT * FROM t1('R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC;
|
||||
} {/.*fts5: corrupt.*/}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -450,7 +450,7 @@ do_test 2.0 {
|
||||
|
||||
do_catchsql_test 2.1 {
|
||||
SELECT * FROM t1('R*R*R*R*') WHERE (a,b)<=(current_date,0) ORDER BY rowid DESC;
|
||||
} {/.*fts5: corrupt.*/}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -569,7 +569,7 @@ do_test 3.0 {
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
UPDATE t1 SET b=quote(zeroblob(200)) WHERE a MATCH 'thra*T';
|
||||
} {/.*fts5: corrupt.*/}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
@@ -878,7 +878,7 @@ do_execsql_test 5.1 {
|
||||
}
|
||||
do_catchsql_test 5.4 {
|
||||
UPDATE t1 SET content=randomblob(500);
|
||||
} {/.*fts5: corrupt.*/}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
@@ -123,6 +123,6 @@ do_execsql_test 2.2 {
|
||||
|
||||
do_catchsql_test 2.3 {
|
||||
DELETE FROM t1 WHERE rowid = 1
|
||||
} {/.*fts5: corrupt.*/}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -32,7 +32,7 @@ sqlite3 db test.db
|
||||
|
||||
do_catchsql_test 1.2 {
|
||||
SELECT * FROM t1
|
||||
} {1 {fts5: corrupt structure record for table "t1"}}
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 1.3 {
|
||||
DROP TABLE t1
|
||||
} {0 {}}
|
||||
@@ -90,58 +90,5 @@ do_execsql_test 3.7 {
|
||||
SELECT * FROM sqlite_schema
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
proc hex_to_blob {hex} {
|
||||
binary encode hex $hex
|
||||
}
|
||||
db func hex_to_blob hex_to_blob
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x, content='', contentless_delete=1);
|
||||
BEGIN;
|
||||
INSERT INTO x1(rowid, x) VALUES(1, 'a b c d e f g h');
|
||||
INSERT INTO x1(rowid, x) VALUES(2, 'a b c d e f g h');
|
||||
COMMIT;
|
||||
DELETE FROM x1 WHERE rowid=1;
|
||||
}
|
||||
|
||||
do_execsql_test 4.1 {
|
||||
SELECT hex(block) FROM x1_data WHERE id=10
|
||||
} {
|
||||
00000000FF00000101010200010101010101010102
|
||||
}
|
||||
|
||||
do_execsql_test 4.2.1 {
|
||||
UPDATE x1_data SET block=
|
||||
X'00000000FF00000101010200010101010101819C9B95A8000102'
|
||||
WHERE id=10;
|
||||
}
|
||||
|
||||
do_catchsql_test 4.2.2 {
|
||||
SELECT * FROM x1('c d e');
|
||||
} {1 {out of memory}}
|
||||
|
||||
do_execsql_test 4.3.1 {
|
||||
UPDATE x1_data SET block=
|
||||
X'00000000FF000001010102000101010101019282AFF9A0000102'
|
||||
WHERE id=10;
|
||||
}
|
||||
|
||||
do_catchsql_test 4.3.2 {
|
||||
SELECT * FROM x1('c d e');
|
||||
} {1 {out of memory}}
|
||||
|
||||
do_execsql_test 4.4.1 {
|
||||
UPDATE x1_data SET block=
|
||||
X'00000000FF000001010102000101010101018181808080130102'
|
||||
WHERE id=10;
|
||||
}
|
||||
|
||||
do_catchsql_test 4.3.2 {
|
||||
SELECT * FROM x1('c d e');
|
||||
} {1 {out of memory}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
# 2025 October 13
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This test is focused on really large position lists. Those that require
|
||||
# 4 or 5 byte position-list size varints. Because of the amount of memory
|
||||
# required, these tests only run on 64-bit platforms.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5corruptbig
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
if { $tcl_platform(wordSize)<8 } {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
if { $SQLITE_MAX_LENGTH!=0x7FFFFFFF } {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
UPDATE t1_data SET block = zeroblob(2147483640) WHERE id=10;
|
||||
}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT id, length(block) FROM t1_data
|
||||
} {1 0 10 2147483640}
|
||||
|
||||
do_catchsql_test 1.3 {
|
||||
SELECT * FROM t1('abc')
|
||||
} {1 {out of memory}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -325,25 +325,5 @@ ifcapable foreignkey {
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 13.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, b);
|
||||
INSERT INTO t1 VALUES('abc def', X'123456');
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
|
||||
do_faultsim_test 13 -faults oom* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
} -body {
|
||||
execsql {
|
||||
UPDATE t1 SET a='def abc'
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -37,12 +37,6 @@ do_execsql_test 2.1 {
|
||||
INSERT INTO yy(yy) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 2.1 {
|
||||
INSERT INTO yy(yy) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 3.0 {
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
# 2014 June 17
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing the FTS5 module.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5join
|
||||
|
||||
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||
ifcapable !fts5 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE vt USING fts5(x);
|
||||
INSERT INTO vt VALUES('abc');
|
||||
INSERT INTO vt VALUES('xyz');
|
||||
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b TIMESTAMP);
|
||||
INSERT INTO t1 VALUES(1, 1), (2, 2);
|
||||
CREATE INDEX i1 ON t1(b);
|
||||
}
|
||||
|
||||
# set sqlite_where_trace [expr 0xFFF]
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT * FROM vt, t1 WHERE vt.rowid = t1.rowid ORDER BY t1.rowid;
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1
|
||||
`--SCAN vt VIRTUAL TABLE INDEX 0:=
|
||||
}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM vt, t1 WHERE vt.rowid = t1.rowid AND b>? ORDER BY b LIMIT 10
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SEARCH t1 USING COVERING INDEX i1 (b>?)
|
||||
`--SCAN vt VIRTUAL TABLE INDEX 0:=
|
||||
}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM vt, t1 WHERE vt.rowid = t1.rowid AND b>?
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SEARCH t1 USING COVERING INDEX i1 (b>?)
|
||||
`--SCAN vt VIRTUAL TABLE INDEX 0:=
|
||||
}
|
||||
|
||||
do_eqp_test 1.4 {
|
||||
SELECT * FROM vt, t1 WHERE vt.rowid = t1.rowid ORDER BY b
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN t1 USING COVERING INDEX i1
|
||||
`--SCAN vt VIRTUAL TABLE INDEX 0:=
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -40,53 +40,4 @@ do_execsql_test 1.2 {
|
||||
SELECT * FROM t1 LEFT JOIN vt ON (vt MATCH 'abc')
|
||||
} {1 abc 2 abc}
|
||||
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES(14);
|
||||
}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
SELECT * FROM vt LEFT JOIN t1 ON vt.rowid = 1;
|
||||
} {
|
||||
abc 14
|
||||
xyz {}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts5(a,b);
|
||||
INSERT INTO t0(a,b)VALUES(1,0);
|
||||
CREATE TABLE t1(x);
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
SELECT * FROM t0 LEFT JOIN t1;
|
||||
} {1 0 {}}
|
||||
|
||||
breakpoint
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT * FROM t0 LEFT JOIN t1 ON t0.b MATCH '1';
|
||||
} {1 {no query solution}}
|
||||
|
||||
do_execsql_test 2.3 {
|
||||
SELECT * FROM t0 LEFT JOIN t1 ON +b MATCH '1';
|
||||
} {1 0 {}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts5(c0, c1);
|
||||
INSERT INTO t0(c0,c1) VALUES (1,0);
|
||||
}
|
||||
|
||||
do_catchsql_test 3.1 {
|
||||
SELECT * FROM t0
|
||||
LEFT JOIN ( SELECT 0 AS col_0 )
|
||||
ON ((((t0.c1 MATCH '1')AND(CASE WHEN t0.c0 THEN CAST(t0.c1 AS INTEGER) ELSE 1 END))));
|
||||
} {1 {no query solution}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -520,28 +520,4 @@ do_execsql_test 15.3 {
|
||||
{columnsize {1 1} columntext {c d} columntotalsize {2 2} poslist {} tokenize {c d} rowcount 2}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 16.0 {
|
||||
CREATE TABLE t1(x);
|
||||
BEGIN EXCLUSIVE;
|
||||
}
|
||||
|
||||
do_test 16.1 {
|
||||
set rc [catch {
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {SELECT * FROM t1}
|
||||
} errmsg]
|
||||
lappend rc $errmsg
|
||||
} {1 {database is locked}}
|
||||
|
||||
do_execsql_test 16.2 {
|
||||
ROLLBACK;
|
||||
}
|
||||
|
||||
do_test 16.3 {
|
||||
catchsql { SELECT * FROM t1 } db2
|
||||
} {0 {}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -238,22 +238,6 @@ do_execsql_test 6.3 {
|
||||
INSERT INTO g1(g1) VALUES('integrity-check');
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check that passing -2147483648 as the parameter to a merge command
|
||||
# does not cause a signed integer overflow error.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE f1 USING fts5(a);
|
||||
}
|
||||
do_execsql_test 7.1 {
|
||||
INSERT INTO f1 VALUES('one two three');
|
||||
INSERT INTO f1 VALUES('four five six');
|
||||
INSERT INTO f1 VALUES('seven eight nine');
|
||||
}
|
||||
do_execsql_test 7.2 {
|
||||
INSERT INTO f1(f1, rank) VALUES('merge', -2147483648);
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -685,17 +685,5 @@ do_execsql_test 26.1 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 27.0 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts5(a, b);
|
||||
INSERT INTO ft1(rowid, a, b) VALUES(3, '3', '3');
|
||||
}
|
||||
|
||||
do_execsql_test 27.1 {
|
||||
SELECT * FROM ft1 WHERE rowid=3 AND b MATCH 'hello';
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -38,15 +38,15 @@ foreach {tn sql uses} {
|
||||
1.2 { DELETE FROM ft WHERE rowid=? } 0
|
||||
1.3 { DELETE FROM ft WHERE rowid=? } 0
|
||||
1.4 { DELETE FROM ft WHERE ft MATCH '1' } 1
|
||||
1.5 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 0
|
||||
1.6 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 0
|
||||
1.5 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
|
||||
1.6 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
|
||||
|
||||
2.1 { UPDATE ft SET content='a b c' } 1
|
||||
2.2 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
|
||||
2.3 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
|
||||
2.4 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' } 1
|
||||
2.5 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 0
|
||||
2.6 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 0
|
||||
2.5 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
|
||||
2.6 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
|
||||
} {
|
||||
do_test 1.$tn { sql_uses_stmt db $sql } $uses
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ do_execsql_test 1.5 {
|
||||
|
||||
do_catchsql_test 1.6 {
|
||||
INSERT INTO f1(f1) VALUES('integrity-check');
|
||||
} {/.*fts5: corrupt.*/}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_execsql_test 1.7 {
|
||||
INSERT INTO f1(f1) VALUES('rebuild');
|
||||
|
||||
@@ -81,7 +81,7 @@ do_execsql_test 3.0 {
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that a crash occurring when the second or subsequent tokens in a
|
||||
# Test that a crash occuring when the second or subsequent tokens in a
|
||||
# phrase matched zero rows has been fixed.
|
||||
#
|
||||
do_execsql_test 4.0 {
|
||||
|
||||
@@ -28,34 +28,4 @@ do_execsql_test 1.1 {
|
||||
INSERT INTO sss VALUES('まりや');
|
||||
}
|
||||
|
||||
foreach {tn enc tok} {
|
||||
1 utf-8 ascii
|
||||
2 utf-16 ascii
|
||||
3 utf-8 unicode61
|
||||
4 utf-16 unicode61
|
||||
} {
|
||||
reset_db
|
||||
|
||||
do_execsql_test 1.$tn.0 "
|
||||
PRAGMA encoding = '$enc';
|
||||
CREATE VIRTUAL TABLE vt2 USING fts5(c0, c1, tokenize=$tok);
|
||||
"
|
||||
|
||||
do_execsql_test 1.$tn.1 {
|
||||
INSERT INTO vt2(c0, c1) VALUES ('bhal', x'17db');
|
||||
}
|
||||
|
||||
do_execsql_test 1.$tn.2 {
|
||||
UPDATE vt2 SET c0='bhal';
|
||||
}
|
||||
|
||||
do_execsql_test 1.$tn.3 {
|
||||
INSERT INTO vt2(vt2) VALUES('integrity-check')
|
||||
}
|
||||
|
||||
do_execsql_test 1.$tn.4 {
|
||||
SELECT quote(c1) FROM vt2
|
||||
} {X'17DB'}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -305,28 +305,6 @@ do_catchsql_test 6.2 {
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(a, b);
|
||||
CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, col);
|
||||
|
||||
INSERT INTO t1 VALUES('xx', 'xx');
|
||||
|
||||
CREATE TABLE x1(t);
|
||||
INSERT INTO x1 VALUES('xx');
|
||||
INSERT INTO x1 VALUES('xx');
|
||||
|
||||
SELECT term, col FROM v1;
|
||||
} {
|
||||
xx a xx b
|
||||
}
|
||||
|
||||
do_execsql_test 7.1 {
|
||||
SELECT * FROM x1 WHERE 'a'=(SELECT col FROM v1 WHERE term=t)
|
||||
} {xx xx}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -139,7 +139,6 @@ do_test 2.3 {
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 0
|
||||
|
||||
db eval {
|
||||
PRAGMA writable_schema=on;
|
||||
DELETE FROM imp1 WHERE rowid=1;
|
||||
DELETE FROM imp2 WHERE rowid=2;
|
||||
}
|
||||
@@ -175,7 +174,6 @@ do_test 3.2 {
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 0
|
||||
|
||||
db eval {
|
||||
PRAGMA writable_schema=on;
|
||||
DELETE FROM imp1 WHERE a=5;
|
||||
}
|
||||
execsql_pp {
|
||||
|
||||
@@ -29,7 +29,6 @@ do_execsql_test 1.0 {
|
||||
proc imposter_edit {obj create sql} {
|
||||
sqlite3 xdb test.db
|
||||
set pgno [xdb one {SELECT rootpage FROM sqlite_schema WHERE name=$obj}]
|
||||
xdb eval {PRAGMA Writable_schema=ON}
|
||||
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER xdb main 1 $pgno
|
||||
xdb eval $create
|
||||
|
||||
@@ -160,7 +160,6 @@ static char *intckMprintf(sqlite3_intck *p, const char *zFmt, ...){
|
||||
sqlite3_free(zRet);
|
||||
zRet = 0;
|
||||
}
|
||||
va_end(ap);
|
||||
return zRet;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -79,7 +79,7 @@ $(bin.version-info): $(dir.tool)/version-info.c $(sqlite3.h) $(dir.top)/Makefile
|
||||
$(MAKE) -C $(dir.top) version-info
|
||||
|
||||
# Be explicit about which Java files to compile so that we can work on
|
||||
# in-progress files without requiring them to be in a compilable state.
|
||||
# in-progress files without requiring them to be in a compilable statae.
|
||||
JAVA_FILES.main := $(patsubst %,$(dir.src.jni)/annotation/%,\
|
||||
Experimental.java \
|
||||
NotNull.java \
|
||||
@@ -429,7 +429,7 @@ $(doc.index): $(JAVA_FILES.main) $(MAKEFILE)
|
||||
.FORCE: doc
|
||||
doc: $(doc.index)
|
||||
javadoc: $(doc.index)
|
||||
# Force rebuild of docs
|
||||
# Force rebild of docs
|
||||
redoc:
|
||||
@rm -f $(doc.index)
|
||||
@$(MAKE) doc
|
||||
@@ -451,7 +451,7 @@ distclean: clean
|
||||
-rm -fr $(dir.bld.c) $(dir.doc)
|
||||
|
||||
########################################################################
|
||||
# distribution bundle rules...
|
||||
# disttribution bundle rules...
|
||||
|
||||
ifeq (,$(filter snapshot,$(MAKECMDGOALS)))
|
||||
dist-name-prefix := sqlite-jni
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ deliberately return an error code, instead of segfaulting, when passed
|
||||
a `null`.
|
||||
|
||||
Client-defined callbacks _must never throw exceptions_ unless _very
|
||||
explicitly documented_ as being throw-safe. Exceptions are generally
|
||||
explitly documented_ as being throw-safe. Exceptions are generally
|
||||
reserved for higher-level bindings which are constructed to
|
||||
specifically deal with them and ensure that they do not leak C-level
|
||||
resources. In some cases, callback handlers are permitted to throw, in
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user