From 82c0087c2faeafa9ff011abe97d089613637684f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 16 Oct 2014 23:38:10 -0400 Subject: [PATCH 01/36] SQLCipher headers are installed into ${includedir}/sqlcipher see line #163 of Makefile.in --- sqlcipher.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlcipher.pc.in b/sqlcipher.pc.in index 6ef1a0d..a8789bd 100644 --- a/sqlcipher.pc.in +++ b/sqlcipher.pc.in @@ -10,4 +10,4 @@ Description: SQL database engine Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lsqlcipher Libs.private: @LIBS@ -Cflags: -I${includedir} +Cflags: -I${includedir}/sqlcipher From fafb0d05bdae394037ac495fe7261573f5f675eb Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Wed, 25 Mar 2015 14:47:02 -0500 Subject: [PATCH 02/36] Update change log --- CHANGELOG.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2156daa..43d6fdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. ## [Unreleased][unreleased] +## [3.3.0] - 2015-03-25 +### Added +- Added FIPS API calls within the OpenSSL crpyto provider +- `PRAGMA cipher_default_page_size` - support for attaching non-default page sizes + +### Changed +- Merged upstream SQLite 3.8.8.3 + ## [3.2.0] - 2014-09-30 ### Added - Added PRAGMA cipher_store_pass @@ -13,22 +21,22 @@ All notable changes to this project will be documented in this file. ## [3.1.0] - 2014-04-23 ### Added -- Added PRAGMA cipher_profile +- Added `PRAGMA cipher_profile` ### Changed - Merged upstream SQLite 3.8.4.3 ## [3.0.1] - 2013-12-06 ### Added -- Add PRAGMA cipher_add_random to source external entropy +- Add `PRAGMA cipher_add_random` to source external entropy ### Changed -- Fix cipher_migrate to handle passphrases longer than 64 characters & raw keys +- Fix `PRAGMA cipher_migrate` to handle passphrases longer than 64 characters & raw keys - Improvements to the libtomcrypt provider ## [3.0.0] - 2013-11-05 ### Added -- Added PRAGMA cipher_migrate to migrate older database file formats +- Added `PRAGMA cipher_migrate` to migrate older database file formats ### Changed - Merged upstream SQLite 3.8.0.2 @@ -41,7 +49,8 @@ All notable changes to this project will be documented in this file. ### Security - Change KDF iteration length from 4,000 to 64,000 -[unreleased]: https://github.com/sqlcipher/sqlcipher/compare/v3.2.0...prerelease +[unreleased]: https://github.com/sqlcipher/sqlcipher/compare/v3.3.0...prerelease +[3.3.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.2.0...v3.3.0 [3.2.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.1.0...v3.2.0 [3.1.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.0.1...v3.1.0 [3.0.1]: https://github.com/sqlcipher/sqlcipher/compare/v3.0.0...v3.0.1 From 388970a669f244c771d9ebe24f976ad91a6ce7c8 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Wed, 25 Mar 2015 14:53:22 -0500 Subject: [PATCH 03/36] Fix spelling --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43d6fdb..c67f1fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. ## [3.3.0] - 2015-03-25 ### Added -- Added FIPS API calls within the OpenSSL crpyto provider +- Added FIPS API calls within the OpenSSL crypto provider - `PRAGMA cipher_default_page_size` - support for attaching non-default page sizes ### Changed From c14afcf742ac1e3b439e4939ae39f6003e272083 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Thu, 16 Apr 2015 08:55:44 -0500 Subject: [PATCH 04/36] Prevent segfault when invalid cipher name provided, identified by Nicholas Starke --- src/crypto_openssl.c | 7 +++++-- test/crypto.test | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/crypto_openssl.c b/src/crypto_openssl.c index 66553a0..eaa2a17 100644 --- a/src/crypto_openssl.c +++ b/src/crypto_openssl.c @@ -186,8 +186,11 @@ static int sqlcipher_openssl_cipher(void *ctx, int mode, unsigned char *key, int static int sqlcipher_openssl_set_cipher(void *ctx, const char *cipher_name) { openssl_ctx *o_ctx = (openssl_ctx *)ctx; - o_ctx->evp_cipher = (EVP_CIPHER *) EVP_get_cipherbyname(cipher_name); - return SQLITE_OK; + EVP_CIPHER* cipher = (EVP_CIPHER *) EVP_get_cipherbyname(cipher_name); + if(cipher != NULL) { + o_ctx->evp_cipher = cipher; + } + return cipher != NULL ? SQLITE_OK : SQLITE_ERROR; } static const char* sqlcipher_openssl_get_cipher(void *ctx) { diff --git a/test/crypto.test b/test/crypto.test index a55b474..b7cbf7b 100644 --- a/test/crypto.test +++ b/test/crypto.test @@ -1922,6 +1922,18 @@ do_test verify-pragma-cipher-page-size-changed { db close file delete -force test.db +# verify invalid cipher does not cause segfault +if_built_with_openssl verify-invalid-cipher-does_not_segfault { + sqlite_orig db test.db + execsql { + PRAGMA key = 'test'; + PRAGMA cipher = 'junk'; + PRAGMA cipher; + } +} {AES-256-CBC} +db close +file delete -force test.db + # verify the pragma cipher # reports the default value if_built_with_openssl verify-pragma-cipher-default { From e26aa0db094c0c48978a93ccfff92786e9b7dfac Mon Sep 17 00:00:00 2001 From: Jan Berkel Date: Sat, 18 Apr 2015 22:43:52 +0100 Subject: [PATCH 05/36] Fix amalgamation output paths sqlite3.c gets generated as a result of this script --- sqlcipher.xcodeproj/project.pbxproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sqlcipher.xcodeproj/project.pbxproj b/sqlcipher.xcodeproj/project.pbxproj index 5c66f77..a3459bc 100644 --- a/sqlcipher.xcodeproj/project.pbxproj +++ b/sqlcipher.xcodeproj/project.pbxproj @@ -153,10 +153,9 @@ files = ( ); inputPaths = ( - "$(SRCROOT)/sqlite3.c", ); outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/libsqlcipher.a", + "$(SRCROOT)/sqlite3.c", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; From 18f95ebbea977b6be7dd714044205843cbfe3346 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Tue, 21 Apr 2015 14:06:30 -0500 Subject: [PATCH 06/36] Check for valid context before using cipher_store_pass Identified by Nicholas Starke --- src/crypto.c | 12 ++++++++---- test/crypto.test | 14 +++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/crypto.c b/src/crypto.c index c79e5c5..79451ae 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -97,12 +97,16 @@ int sqlcipher_codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLef } } else if( sqlite3StrICmp(zLeft, "cipher_store_pass")==0 && zRight ) { - sqlcipher_codec_set_store_pass(ctx, sqlite3GetBoolean(zRight, 1)); + if(ctx) { + sqlcipher_codec_set_store_pass(ctx, sqlite3GetBoolean(zRight, 1)); + } } else if( sqlite3StrICmp(zLeft, "cipher_store_pass")==0 && !zRight ) { - char *store_pass_value = sqlite3_mprintf("%d", sqlcipher_codec_get_store_pass(ctx)); - codec_vdbe_return_static_string(pParse, "cipher_store_pass", store_pass_value); - sqlite3_free(store_pass_value); + if(ctx){ + char *store_pass_value = sqlite3_mprintf("%d", sqlcipher_codec_get_store_pass(ctx)); + codec_vdbe_return_static_string(pParse, "cipher_store_pass", store_pass_value); + sqlite3_free(store_pass_value); + } } if( sqlite3StrICmp(zLeft, "cipher_profile")== 0 && zRight ){ char *profile_status = sqlite3_mprintf("%d", sqlcipher_cipher_profile(db, zRight)); diff --git a/test/crypto.test b/test/crypto.test index b7cbf7b..84f8d57 100644 --- a/test/crypto.test +++ b/test/crypto.test @@ -1923,7 +1923,7 @@ db close file delete -force test.db # verify invalid cipher does not cause segfault -if_built_with_openssl verify-invalid-cipher-does_not_segfault { +if_built_with_openssl verify-invalid-cipher-does-not-segfault { sqlite_orig db test.db execsql { PRAGMA key = 'test'; @@ -1934,6 +1934,18 @@ if_built_with_openssl verify-invalid-cipher-does_not_segfault { db close file delete -force test.db +# verify setting cipher_store_pass before key +# does not cause segfault +do_test verify-cipher-store-pass-before-key-does-not-segfault { + sqlite_orig db test.db + execsql { + PRAGMA cipher_store_pass = 1; + PRAGMA key = 'test'; + } +} {} +db close +file delete -force test.db + # verify the pragma cipher # reports the default value if_built_with_openssl verify-pragma-cipher-default { From 4eeb4a0dc1fc03152866de50946d7fba97d45820 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Thu, 28 May 2015 11:41:52 -0500 Subject: [PATCH 07/36] Add contributions section to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ab571b0..d30a16e 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ an iPhone data vault and password manager (http://getstrip.com). - Algorithms provided by the peer reviewed OpenSSL crypto library. - Configurable crypto providers +## Contributions + +We welcome contributions, to contribute to SQLCipher, a [contributor agreement](https://www.zetetic.net/contributions/) needs to be submitted. All submissions should be based on the =prerelease= branch. + ## Compiling Building SQLCipher is almost the same as compiling a regular version of From def3373d6f538059befdf2b1e43b777937dde258 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Thu, 28 May 2015 11:42:42 -0500 Subject: [PATCH 08/36] Fix format in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d30a16e..fc4547f 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ an iPhone data vault and password manager (http://getstrip.com). ## Contributions -We welcome contributions, to contribute to SQLCipher, a [contributor agreement](https://www.zetetic.net/contributions/) needs to be submitted. All submissions should be based on the =prerelease= branch. +We welcome contributions, to contribute to SQLCipher, a [contributor agreement](https://www.zetetic.net/contributions/) needs to be submitted. All submissions should be based on the `prerelease` branch. ## Compiling From 6e87d2db26fe48f77d0213df2d79dd7ed6648910 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Thu, 28 May 2015 11:41:52 -0500 Subject: [PATCH 09/36] Add contributions section to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ab571b0..d30a16e 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ an iPhone data vault and password manager (http://getstrip.com). - Algorithms provided by the peer reviewed OpenSSL crypto library. - Configurable crypto providers +## Contributions + +We welcome contributions, to contribute to SQLCipher, a [contributor agreement](https://www.zetetic.net/contributions/) needs to be submitted. All submissions should be based on the =prerelease= branch. + ## Compiling Building SQLCipher is almost the same as compiling a regular version of From b5443984768236ea077fa2cf32c377dfef017e92 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Thu, 28 May 2015 11:42:42 -0500 Subject: [PATCH 10/36] Fix format in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d30a16e..fc4547f 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ an iPhone data vault and password manager (http://getstrip.com). ## Contributions -We welcome contributions, to contribute to SQLCipher, a [contributor agreement](https://www.zetetic.net/contributions/) needs to be submitted. All submissions should be based on the =prerelease= branch. +We welcome contributions, to contribute to SQLCipher, a [contributor agreement](https://www.zetetic.net/contributions/) needs to be submitted. All submissions should be based on the `prerelease` branch. ## Compiling From e451540b9c18faad0dfd6a3e708c274963483993 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Wed, 17 Jun 2015 11:57:00 -0500 Subject: [PATCH 11/36] Remove null check, assignment always occurs --- src/crypto_impl.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 8c891d5..12fefb8 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -1158,11 +1158,9 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) { db->nTotalChange = saved_nTotalChange; db->xTrace = saved_xTrace; db->autoCommit = 1; - if( pDb ){ - sqlite3BtreeClose(pDb->pBt); - pDb->pBt = 0; - pDb->pSchema = 0; - } + sqlite3BtreeClose(pDb->pBt); + pDb->pBt = 0; + pDb->pSchema = 0; sqlite3ResetAllSchemasOfConnection(db); remove(migrated_db_filename); sqlite3_free(migrated_db_filename); From 724d1aac992d6d1af0992d703f00e0f3486dbfe9 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Fri, 10 Jul 2015 14:14:29 -0500 Subject: [PATCH 12/36] Snapshot of upstream SQLite 3.8.10.2 --- Makefile.in | 65 +- Makefile.msc | 561 ++- VERSION | 2 +- autoconf/Makefile.am | 3 +- configure | 6679 +++++++++++---------------------- configure.ac | 1 + ext/fts3/fts3.c | 171 +- ext/fts3/fts3Int.h | 6 + ext/fts3/fts3_aux.c | 2 +- ext/fts3/fts3_expr.c | 4 +- ext/fts3/fts3_snippet.c | 67 +- ext/fts3/fts3_term.c | 2 +- ext/fts3/fts3_tokenize_vtab.c | 2 +- ext/fts3/fts3_tokenizer.c | 20 +- ext/fts3/fts3_write.c | 18 +- ext/fts3/tool/fts3view.c | 4 +- ext/misc/amatch.c | 28 +- ext/misc/compress.c | 11 +- ext/misc/fuzzer.c | 2 +- ext/rtree/rtree.c | 16 +- ext/rtree/rtree9.test | 1 - main.mk | 56 +- manifest | 459 +-- manifest.uuid | 2 +- mkopcodeh.awk | 27 +- mptest/crash01.test | 4 + mptest/mptest.c | 56 +- mptest/multiwrite01.test | 10 + src/alter.c | 6 +- src/analyze.c | 15 +- src/attach.c | 5 +- src/backup.c | 2 +- src/bitvec.c | 2 +- src/btmutex.c | 1 + src/btree.c | 197 +- src/btree.h | 19 +- src/btreeInt.h | 4 + src/build.c | 42 +- src/complete.c | 2 +- src/ctime.c | 3 + src/{test_stat.c => dbstat.c} | 223 +- src/delete.c | 2 +- src/expr.c | 89 +- src/fkey.c | 28 +- src/func.c | 30 +- src/global.c | 10 +- src/insert.c | 84 +- src/loadext.c | 20 +- src/main.c | 124 +- src/malloc.c | 54 +- src/msvc.h | 1 + src/mutex_noop.c | 17 +- src/mutex_unix.c | 31 +- src/mutex_w32.c | 19 +- src/os_common.h | 10 - src/os_unix.c | 375 +- src/os_win.c | 164 +- src/os_win.h | 11 + src/pager.c | 6 +- src/parse.y | 70 +- src/pcache.c | 10 +- src/pcache1.c | 19 +- src/pragma.c | 569 +-- src/pragma.h | 459 +++ src/prepare.c | 6 +- src/printf.c | 106 +- src/resolve.c | 86 +- src/select.c | 99 +- src/shell.c | 496 ++- src/sqlite.h.in | 247 +- src/sqliteInt.h | 143 +- src/sqliteLimit.h | 12 +- src/status.c | 94 +- src/table.c | 6 +- src/tclsqlite.c | 101 +- src/test1.c | 60 +- src/test3.c | 15 +- src/test4.c | 2 +- src/test7.c | 2 +- src/test8.c | 4 +- src/test_backup.c | 2 +- src/test_blob.c | 5 +- src/test_config.c | 1 - src/test_demovfs.c | 2 +- src/test_func.c | 17 +- src/test_intarray.c | 8 +- src/test_malloc.c | 10 +- src/test_multiplex.c | 40 +- src/test_onefile.c | 6 +- src/test_osinst.c | 3 - src/test_rtree.c | 2 +- src/test_sqllog.c | 6 +- src/test_superlock.c | 2 +- src/test_thread.c | 2 +- src/test_vfs.c | 21 +- src/threads.c | 4 +- src/tokenize.c | 22 +- src/trigger.c | 20 +- src/util.c | 1 + src/vacuum.c | 6 +- src/vdbe.c | 543 +-- src/vdbe.h | 1 + src/vdbeInt.h | 12 +- src/vdbeapi.c | 46 +- src/vdbeaux.c | 48 +- src/vdbeblob.c | 11 +- src/vdbemem.c | 130 +- src/vdbesort.c | 399 +- src/vdbetrace.c | 9 +- src/vtab.c | 72 +- src/vxworks.h | 29 + src/wal.c | 33 +- src/where.c | 503 ++- src/whereInt.h | 7 +- test/alter.test | 9 + test/analyze.test | 2 +- test/analyze3.test | 54 +- test/analyze9.test | 112 + test/analyzeF.test | 127 + test/attach.test | 12 + test/autoindex1.test | 10 + test/btree02.test | 52 + test/capi3.test | 14 +- test/collate1.test | 72 +- test/collate3.test | 7 +- test/collate8.test | 34 +- test/corruptC.test | 2 +- test/corruptJ.test | 80 + test/count.test | 5 + test/crashM.test | 80 + test/e_insert.test | 6 +- test/e_reindex.test | 8 +- test/e_wal.test | 9 +- test/e_walauto.test | 8 + test/expr.test | 8 + test/fkey1.test | 30 + test/fkey2.test | 23 +- test/fkey5.test | 29 +- test/fts3aa.test | 22 + test/fts3atoken.test | 24 +- test/fts3expr5.test | 48 + test/fts3fault2.test | 19 + test/fts3matchinfo.test | 63 + test/fts3prefix.test | 82 + test/fts3query.test | 76 + test/fts3snippet.test | 38 + test/fts3tok1.test | 10 + test/fts4check.test | 30 + test/fts4content.test | 18 +- test/fuzz2.test | 10 + test/fuzzdata1.txt | Bin 0 -> 2966109 bytes test/fuzzdata2.txt | Bin 0 -> 15739506 bytes test/hexlit.test | 5 + test/imposter1.test | 141 + test/in.test | 6 + test/incrblob2.test | 32 + test/incrcorrupt.test | 127 + test/incrvacuum2.test | 4 +- test/index3.test | 2 +- test/index6.test | 31 + test/index7.test | 38 + test/indexedby.test | 49 +- test/insert2.test | 20 + test/insert4.test | 5 + test/jrnlmode.test | 14 + test/like.test | 4 +- test/like3.test | 112 + test/limit.test | 6 + test/lock.test | 3 + test/lock_common.tcl | 58 +- test/malloc.test | 21 + test/malloc5.test | 29 +- test/mallocK.test | 37 + test/misc1.test | 65 +- test/misc5.test | 18 + test/mkfuzzdata1.tcl | 113 + test/multiplex4.test | 18 + test/null.test | 17 + test/orderby1.test | 32 + test/pagesize.test | 18 + test/pragma.test | 203 +- test/pragma2.test | 4 + test/printf.test | 27 + test/printf2.test | 3 + test/rdonly.test | 5 + test/releasetest.tcl | 98 +- test/resolver01.test | 10 +- test/select1.test | 8 + test/select4.test | 50 + test/select6.test | 56 + test/selectA.test | 60 + test/selectE.test | 5 + test/shell1.test | 115 +- test/shell4.test | 24 +- test/shell5.test | 30 + test/shrink.test | 3 + test/softheap1.test | 8 + test/sort4.test | 15 +- test/speedtest1.c | 2 +- test/sqllimits1.test | 26 + test/stat.test | 10 +- test/statfault.test | 45 + test/subquery.test | 10 + test/table.test | 19 + test/tclsqlite.test | 2 +- test/tester.tcl | 33 + test/trace2.test | 2 +- test/trigger1.test | 16 + test/trigger7.test | 2 +- test/triggerC.test | 49 + test/vacuum2.test | 20 + test/vtab1.test | 91 + test/vtab2.test | 22 +- test/vtabA.test | 23 +- test/wal5.test | 14 +- test/walblock.test | 114 + test/where8.test | 4 +- test/whereD.test | 14 +- test/whereK.test | 72 + test/win32lock.test | 2 + test/with1.test | 21 + test/without_rowid6.test | 76 + test/zeroblob.test | 9 + tool/build-all-msvc.bat | 224 +- tool/fuzzershell.c | 846 +++++ tool/lemon.c | 78 +- tool/mkpragmatab.tcl | 67 +- tool/mksqlite3c-noext.tcl | 94 +- tool/mksqlite3c.tcl | 96 +- tool/mksqlite3h.tcl | 45 +- tool/mkvsix.tcl | 52 +- tool/showdb.c | 8 +- tool/showlocks.c | 64 + tool/spaceanal.tcl | 35 +- tool/sqldiff.c | 1242 ++++++ 235 files changed, 13690 insertions(+), 7345 deletions(-) rename src/{test_stat.c => dbstat.c} (81%) create mode 100644 src/pragma.h create mode 100644 src/vxworks.h create mode 100644 test/analyzeF.test create mode 100644 test/btree02.test create mode 100644 test/corruptJ.test create mode 100644 test/crashM.test create mode 100644 test/fts3expr5.test create mode 100644 test/fuzzdata1.txt create mode 100644 test/fuzzdata2.txt create mode 100644 test/imposter1.test create mode 100644 test/incrcorrupt.test create mode 100644 test/like3.test create mode 100644 test/mkfuzzdata1.tcl create mode 100644 test/statfault.test create mode 100644 test/walblock.test create mode 100644 test/whereK.test create mode 100644 tool/fuzzershell.c create mode 100644 tool/showlocks.c create mode 100644 tool/sqldiff.c diff --git a/Makefile.in b/Makefile.in index 3d6e0f2..0591150 100644 --- a/Makefile.in +++ b/Makefile.in @@ -167,7 +167,7 @@ USE_AMALGAMATION = @USE_AMALGAMATION@ # LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ backup.lo bitvec.lo btmutex.lo btree.lo build.lo \ - callback.lo complete.lo ctime.lo date.lo delete.lo \ + callback.lo complete.lo ctime.lo date.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 \ fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \ @@ -213,6 +213,7 @@ SRC = \ $(TOP)/src/complete.c \ $(TOP)/src/ctime.c \ $(TOP)/src/date.c \ + $(TOP)/src/dbstat.c \ $(TOP)/src/delete.c \ $(TOP)/src/expr.c \ $(TOP)/src/fault.c \ @@ -255,6 +256,7 @@ SRC = \ $(TOP)/src/pcache.h \ $(TOP)/src/pcache1.c \ $(TOP)/src/pragma.c \ + $(TOP)/src/pragma.h \ $(TOP)/src/prepare.c \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ @@ -286,6 +288,7 @@ SRC = \ $(TOP)/src/vdbetrace.c \ $(TOP)/src/vdbeInt.h \ $(TOP)/src/vtab.c \ + $(TOP)/src/vxworks.h \ $(TOP)/src/wal.c \ $(TOP)/src/wal.h \ $(TOP)/src/walker.c \ @@ -387,7 +390,6 @@ TESTSRC = \ $(TOP)/src/test_server.c \ $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ - $(TOP)/src/test_stat.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ @@ -421,6 +423,7 @@ TESTSRC2 = \ $(TOP)/src/build.c \ $(TOP)/src/ctime.c \ $(TOP)/src/date.c \ + $(TOP)/src/dbstat.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ @@ -474,12 +477,14 @@ HDR = \ $(TOP)/src/pager.h \ $(TOP)/src/pcache.h \ parse.h \ + $(TOP)/src/pragma.h \ sqlite3.h \ $(TOP)/src/sqlite3ext.h \ $(TOP)/src/sqliteInt.h \ $(TOP)/src/sqliteLimit.h \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeInt.h \ + $(TOP)/src/vxworks.h \ $(TOP)/src/whereInt.h \ config.h @@ -532,15 +537,29 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h -o $@ $(TOP)/src/shell.c libsqlite3.la \ $(LIBREADLINE) $(TLIBS) -rpath "$(libdir)" -mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c +sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h + $(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) + +fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h + $(LTLINK) -o $@ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) + +mptester$(TEXE): sqlite3.c $(TOP)/mptest/mptest.c $(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \ $(TLIBS) -rpath "$(libdir)" -mptest: mptester$(EXE) - rm -f mptest1.db - ./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test - rm -f mptest2.db - ./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test +MPTEST1=./mptester$(TEXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20 +MPTEST2=./mptester$(TEXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20 +mptest: mptester$(TEXE) + rm -f mptest.db + $(MPTEST1) --journalmode DELETE + $(MPTEST2) --journalmode WAL + $(MPTEST1) --journalmode WAL + $(MPTEST2) --journalmode PERSIST + $(MPTEST1) --journalmode PERSIST + $(MPTEST2) --journalmode TRUNCATE + $(MPTEST1) --journalmode TRUNCATE + $(MPTEST2) --journalmode DELETE + # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to @@ -634,6 +653,9 @@ ctime.lo: $(TOP)/src/ctime.c $(HDR) date.lo: $(TOP)/src/date.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/date.c +dbstat.lo: $(TOP)/src/dbstat.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbstat.c + delete.lo: $(TOP)/src/delete.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/delete.c @@ -933,39 +955,48 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC) -o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS) # A very detailed test running most or all test cases -fulltest: testfixture$(TEXE) sqlite3$(TEXE) +fulltest: testfixture$(TEXE) sqlite3$(TEXE) fuzztest ./testfixture$(TEXE) $(TOP)/test/all.test # Really really long testing -soaktest: testfixture$(TEXE) sqlite3$(TEXE) +soaktest: testfixture$(TEXE) sqlite3$(TEXE) fuzzoomtest ./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 # Do extra testing but not aeverything. fulltestonly: testfixture$(TEXE) sqlite3$(TEXE) ./testfixture$(TEXE) $(TOP)/test/full.test +# Fuzz testing +fuzztest: fuzzershell$(TEXE) + ./fuzzershell$(TEXE) $(TOP)/test/fuzzdata1.txt $(TOP)/test/fuzzdata2.txt + +fuzzoomtest: fuzzershell$(TEXE) + ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt --oom + # This is the common case. Run many tests but not those that take # a really long time. # -test: testfixture$(TEXE) sqlite3$(TEXE) +test: testfixture$(TEXE) sqlite3$(TEXE) fuzztest ./testfixture$(TEXE) $(TOP)/test/veryquick.test # Run a test using valgrind. This can take a really long time # because valgrind is so much slower than a native machine. # -valgrindtest: testfixture$(TEXE) sqlite3$(TEXE) +valgrindtest: testfixture$(TEXE) sqlite3$(TEXE) fuzzershell$(TEXE) + valgrind -v ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind # A very fast test that checks basic sanity. The name comes from # the 60s-era electronics testing: "Turn it on and see if smoke # comes out." # -smoketest: testfixture$(TEXE) +smoketest: testfixture$(TEXE) fuzzershell$(TEXE) ./testfixture$(TEXE) $(TOP)/test/main.test -sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl +sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl echo "#define TCLSH 2" > $@ - cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@ + echo "#define SQLITE_ENABLE_DBSTAT_VTAB" >> $@ + cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@ echo "static const char *tclsh_main_loop(void){" >> $@ echo "static const char *zMainloop = " >> $@ $(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@ @@ -995,7 +1026,7 @@ LogEst$(TEXE): $(TOP)/tool/logest.c sqlite3.h wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.c $(LTLINK) -o $@ $(TOP)/test/wordcount.c sqlite3.c $(TLIBS) -speedtest1$(TEXE): $(TOP)/test/wordcount.c sqlite3.lo +speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS) # This target will fail if the SQLite amalgamation contains any exported @@ -1047,7 +1078,7 @@ install: sqlite3$(BEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_instal $(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(pkgconfigdir) pkgIndex.tcl: - echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3.so sqlite3]' > $@ + echo 'package ifneeded sqlite3 $(RELEASE) [list load $(TCLLIBDIR)/libtclsqlite3$(SHLIB_SUFFIX) sqlite3]' > $@ tcl_install: lib_install libtclsqlite3.la pkgIndex.tcl $(INSTALL) -d $(DESTDIR)$(TCLLIBDIR) $(LTINSTALL) libtclsqlite3.la $(DESTDIR)$(TCLLIBDIR) diff --git a/Makefile.msc b/Makefile.msc index 4ebe9fd..df39851 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -22,14 +22,28 @@ USE_AMALGAMATION = 1 USE_FULLWARN = 0 !ENDIF +# Set this non-0 to use "stdcall" calling convention for the core library +# and shell executable. +# +!IFNDEF USE_STDCALL +USE_STDCALL = 0 +!ENDIF + +# Set this non-0 to have the shell executable link against the core dynamic +# link library. +# +!IFNDEF DYNAMIC_SHELL +DYNAMIC_SHELL = 0 +!ENDIF + # If necessary, create a list of harmless compiler warnings to disable when -# compiling the build tools. For the SQLite source code itself, warnings, +# compiling the various tools. For the SQLite source code itself, warnings, # if any, will be disabled from within it. # !IFNDEF NO_WARN !IF $(USE_FULLWARN)!=0 -NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4152 -wd4189 -wd4206 -wd4210 -NO_WARN = $(NO_WARN) -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706 +NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 +NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706 !ENDIF !ENDIF @@ -59,6 +73,12 @@ USE_ICU = 0 USE_CRT_DLL = 0 !ENDIF +# Set this non-0 to link to the RPCRT4 library. +# +!IFNDEF USE_RPCRT4_LIB +USE_RPCRT4_LIB = 0 +!ENDIF + # Set this non-0 to generate assembly code listings for the source code # files. # @@ -95,6 +115,14 @@ USE_RC = 1 FOR_WINRT = 0 !ENDIF +# Set this non-0 to compile binaries suitable for the UAP environment. +# This setting does not apply to any binaries that require Tcl to operate +# properly (i.e. the text fixture, etc). +# +!IFNDEF FOR_UAP +FOR_UAP = 0 +!ENDIF + # Set this non-0 to skip attempting to look for and/or link with the Tcl # runtime library. # @@ -120,6 +148,13 @@ MEMDEBUG = 0 WIN32HEAP = 0 !ENDIF +# Set this to non-0 to enable OSTRACE() macros, which can be useful when +# debugging. +# +!IFNDEF OSTRACE +OSTRACE = 0 +!ENDIF + # Set this to one of the following values to enable various debugging # features. Each level includes the debugging options from the previous # levels. Currently, the recognized values for DEBUG are: @@ -250,9 +285,9 @@ NSDKLIBPATH = $(NSDKLIBPATH:\\=\) # will run on the platform that is doing the build. # !IF $(USE_FULLWARN)!=0 -BCC = $(NCC) -W4 +BCC = $(NCC) -nologo -W4 !ELSE -BCC = $(NCC) -W3 +BCC = $(NCC) -nologo -W3 !ENDIF # Check if assembly code listings should be generated for the source @@ -268,6 +303,11 @@ BCC = $(BCC) -FAcs # !IF $(USE_NATIVE_LIBPATHS)!=0 NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)" + +!IFDEF NUCRTLIBPATH +NUCRTLIBPATH = $(NUCRTLIBPATH:\\=\) +NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)" +!ENDIF !ENDIF # C compiler and options for use in building executables that @@ -275,14 +315,106 @@ NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)" # same unless your are cross-compiling.) # !IF $(USE_FULLWARN)!=0 -TCC = $(CC) -W4 -DINCLUDE_MSVC_H=1 +TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 !ELSE -TCC = $(CC) -W3 +TCC = $(CC) -nologo -W3 !ENDIF TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src +# Check if we want to use the "stdcall" calling convention when compiling. +# This is not supported by the compilers for non-x86 platforms. It should +# also be noted here that building any target with these "stdcall" options +# will most likely fail if the Tcl library is also required. This is due +# to how the Tcl library functions are declared and exported (i.e. without +# an explicit calling convention, which results in "cdecl"). +# +!IF $(USE_STDCALL)!=0 +!IF "$(PLATFORM)"=="x86" +CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +!ELSE +!IFNDEF PLATFORM +CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +!ELSE +CORE_CCONV_OPTS = +SHELL_CCONV_OPTS = +!ENDIF +!ENDIF +!ELSE +CORE_CCONV_OPTS = +SHELL_CCONV_OPTS = +!ENDIF + +# These are additional compiler options used for the core library. +# +!IFNDEF CORE_COMPILE_OPTS +!IF $(DYNAMIC_SHELL)!=0 +CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport) +!ELSE +CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) +!ENDIF +!ENDIF + +# These are the additional targets that the core library should depend on +# when linking. +# +!IFNDEF CORE_LINK_DEP +!IF $(DYNAMIC_SHELL)!=0 +CORE_LINK_DEP = +!ELSE +CORE_LINK_DEP = sqlite3.def +!ENDIF +!ENDIF + +# These are additional linker options used for the core library. +# +!IFNDEF CORE_LINK_OPTS +!IF $(DYNAMIC_SHELL)!=0 +CORE_LINK_OPTS = +!ELSE +CORE_LINK_OPTS = /DEF:sqlite3.def +!ENDIF +!ENDIF + +# These are additional compiler options used for the shell executable. +# +!IFNDEF SHELL_COMPILE_OPTS +!IF $(DYNAMIC_SHELL)!=0 +SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport) +!ELSE +SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) +!ENDIF +!ENDIF + +# This is the core library that the shell executable should depend on. +# +!IFNDEF SHELL_CORE_DEP +!IF $(DYNAMIC_SHELL)!=0 +SHELL_CORE_DEP = sqlite3.dll +!ELSE +SHELL_CORE_DEP = libsqlite3.lib +!ENDIF +!ENDIF + +# This is the core library that the shell executable should link with. +# +!IFNDEF SHELL_CORE_LIB +!IF $(DYNAMIC_SHELL)!=0 +SHELL_CORE_LIB = sqlite3.lib +!ELSE +SHELL_CORE_LIB = libsqlite3.lib +!ENDIF +!ENDIF + +# These are additional linker options used for the shell executable. +# +!IFNDEF SHELL_LINK_OPTS +SHELL_LINK_OPTS = $(SHELL_CORE_LIB) +!ENDIF + # Check if assembly code listings should be generated for the source # code files to be compiled. # @@ -341,11 +473,13 @@ RCC = $(RCC) -I$(TOP)\ext\rtree # options are necessary in order to allow debugging symbols to # work correctly with Visual Studio when using the amalgamation. # +!IFNDEF MKSQLITE3C_ARGS !IF $(DEBUG)>1 MKSQLITE3C_ARGS = --linemacros !ELSE MKSQLITE3C_ARGS = !ENDIF +!ENDIF # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and @@ -367,9 +501,9 @@ TCC = $(TCC) -DSQLITE_DEBUG RCC = $(RCC) -DSQLITE_DEBUG !ENDIF -!IF $(DEBUG)>4 -TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1 -RCC = $(RCC) -DSQLITE_DEBUG_OS_TRACE=1 +!IF $(DEBUG)>4 || $(OSTRACE)!=0 +TCC = $(TCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1 +RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1 !ENDIF !IF $(DEBUG)>5 @@ -501,6 +635,12 @@ RCC = $(RCC) -DSQLITE_TEMP_STORE=1 # REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100 +# If we are linking to the RPCRT4 library, enable features that need it. +# +!IF $(USE_RPCRT4_LIB)!=0 +REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_WIN32_USE_UUID=1 +!ENDIF + # Add the required and optional SQLite compilation options into the command # lines used to invoke the MSVC code and resource compilers. # @@ -564,13 +704,22 @@ LTRCOMPILE = $(RCC) -r LTLIB = lib.exe LTLINK = $(TCC) -Fe$@ +# If requested, link to the RPCRT4 library. +# +!IF $(USE_RPCRT4_LIB)!=0 +LTLINK = $(LTLINK) rpcrt4.lib +!ENDIF + # If a platform was set, force the linker to target that. # Note that the vcvars*.bat family of batch files typically # set this for you. Otherwise, the linker will attempt # to deduce the binary type based on the object files. !IFDEF PLATFORM -LTLINKOPTS = /MACHINE:$(PLATFORM) -LTLIBOPTS = /MACHINE:$(PLATFORM) +LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM) +LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM) +!ELSE +LTLINKOPTS = /NOLOGO +LTLIBOPTS = /NOLOGO !ENDIF # When compiling for use in the WinRT environment, the following @@ -579,7 +728,7 @@ LTLIBOPTS = /MACHINE:$(PLATFORM) # !IF $(FOR_WINRT)!=0 LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER -!IF "$(VISUALSTUDIOVERSION)"=="12.0" +!IF "$(VISUALSTUDIOVERSION)"=="12.0" || "$(VISUALSTUDIOVERSION)"=="14.0" !IFNDEF STORELIBPATH !IF "$(PLATFORM)"=="x86" STORELIBPATH = $(CRTLIBPATH)\store @@ -623,6 +772,16 @@ LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelH LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib !ENDIF +# When compiling for UAP, some extra linker options are also required. +# +!IF $(FOR_UAP)!=0 +LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib +LTLINKOPTS = $(LTLINKOPTS) mincore.lib +!IFDEF PSDKLIBPATH +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)" +!ENDIF +!ENDIF + # If either debugging or symbols are enabled, enable PDBs. # !IF $(DEBUG)>1 || $(SYMBOLS)!=0 @@ -656,7 +815,7 @@ NAWK = gawk.exe # 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 complete.lo ctime.lo date.lo delete.lo \ + callback.lo complete.lo ctime.lo date.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 \ fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \ @@ -696,7 +855,7 @@ LIBRESOBJS = # All of the source code files. # -SRC = \ +SRC1 = \ $(TOP)\src\alter.c \ $(TOP)\src\analyze.c \ $(TOP)\src\attach.c \ @@ -712,6 +871,7 @@ SRC = \ $(TOP)\src\complete.c \ $(TOP)\src\ctime.c \ $(TOP)\src\date.c \ + $(TOP)\src\dbstat.c \ $(TOP)\src\delete.c \ $(TOP)\src\expr.c \ $(TOP)\src\fault.c \ @@ -746,7 +906,8 @@ SRC = \ $(TOP)\src\os_setup.h \ $(TOP)\src\os_unix.c \ $(TOP)\src\os_win.c \ - $(TOP)\src\os_win.h \ + $(TOP)\src\os_win.h +SRC2 = \ $(TOP)\src\pager.c \ $(TOP)\src\pager.h \ $(TOP)\src\parse.y \ @@ -754,6 +915,7 @@ SRC = \ $(TOP)\src\pcache.h \ $(TOP)\src\pcache1.c \ $(TOP)\src\pragma.c \ + $(TOP)\src\pragma.h \ $(TOP)\src\prepare.c \ $(TOP)\src\printf.c \ $(TOP)\src\random.c \ @@ -785,6 +947,7 @@ SRC = \ $(TOP)\src\vdbetrace.c \ $(TOP)\src\vdbeInt.h \ $(TOP)\src\vtab.c \ + $(TOP)\src\vxworks.h \ $(TOP)\src\wal.c \ $(TOP)\src\wal.h \ $(TOP)\src\walker.c \ @@ -793,15 +956,14 @@ SRC = \ # Source code for extensions # -SRC = $(SRC) \ +SRC3 = \ $(TOP)\ext\fts1\fts1.c \ $(TOP)\ext\fts1\fts1.h \ $(TOP)\ext\fts1\fts1_hash.c \ $(TOP)\ext\fts1\fts1_hash.h \ $(TOP)\ext\fts1\fts1_porter.c \ $(TOP)\ext\fts1\fts1_tokenizer.h \ - $(TOP)\ext\fts1\fts1_tokenizer1.c -SRC = $(SRC) \ + $(TOP)\ext\fts1\fts1_tokenizer1.c \ $(TOP)\ext\fts2\fts2.c \ $(TOP)\ext\fts2\fts2.h \ $(TOP)\ext\fts2\fts2_hash.c \ @@ -811,7 +973,7 @@ SRC = $(SRC) \ $(TOP)\ext\fts2\fts2_tokenizer.h \ $(TOP)\ext\fts2\fts2_tokenizer.c \ $(TOP)\ext\fts2\fts2_tokenizer1.c -SRC = $(SRC) \ +SRC4 = \ $(TOP)\ext\fts3\fts3.c \ $(TOP)\ext\fts3\fts3.h \ $(TOP)\ext\fts3\fts3Int.h \ @@ -828,18 +990,16 @@ SRC = $(SRC) \ $(TOP)\ext\fts3\fts3_tokenize_vtab.c \ $(TOP)\ext\fts3\fts3_unicode.c \ $(TOP)\ext\fts3\fts3_unicode2.c \ - $(TOP)\ext\fts3\fts3_write.c -SRC = $(SRC) \ + $(TOP)\ext\fts3\fts3_write.c \ $(TOP)\ext\icu\sqliteicu.h \ - $(TOP)\ext\icu\icu.c -SRC = $(SRC) \ + $(TOP)\ext\icu\icu.c \ $(TOP)\ext\rtree\rtree.h \ $(TOP)\ext\rtree\rtree.c # Generated source code files # -SRC = $(SRC) \ +SRC5 = \ keywordhash.h \ opcodes.c \ opcodes.h \ @@ -847,6 +1007,10 @@ SRC = $(SRC) \ parse.h \ sqlite3.h +# All source code files. +# +SRC = $(SRC1) $(SRC2) $(SRC3) $(SRC4) $(SRC5) + # Source code to the test files. # TESTSRC = \ @@ -885,7 +1049,6 @@ TESTSRC = \ $(TOP)\src\test_server.c \ $(TOP)\src\test_superlock.c \ $(TOP)\src\test_syscall.c \ - $(TOP)\src\test_stat.c \ $(TOP)\src\test_tclvar.c \ $(TOP)\src\test_thread.c \ $(TOP)\src\test_vfs.c \ @@ -920,6 +1083,7 @@ TESTSRC2 = \ $(TOP)\src\build.c \ $(TOP)\src\ctime.c \ $(TOP)\src\date.c \ + $(TOP)\src\dbstat.c \ $(TOP)\src\expr.c \ $(TOP)\src\func.c \ $(TOP)\src\insert.c \ @@ -976,12 +1140,14 @@ HDR = \ $(TOP)\src\pager.h \ $(TOP)\src\pcache.h \ parse.h \ + $(TOP)\src\pragma.h \ sqlite3.h \ $(TOP)\src\sqlite3ext.h \ $(TOP)\src\sqliteInt.h \ $(TOP)\src\sqliteLimit.h \ $(TOP)\src\vdbe.h \ $(TOP)\src\vdbeInt.h \ + $(TOP)\src\vxworks.h \ $(TOP)\src\whereInt.h # Header files used by extensions @@ -1017,13 +1183,33 @@ libsqlite3.lib: $(LIBOBJ) libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS) -sqlite3.exe: $(TOP)\src\shell.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h - $(LTLINK) $(READLINE_FLAGS) $(TOP)\src\shell.c \ - /link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) +sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h + $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \ + /link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) -mptester.exe: $(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h - $(LTLINK) $(TOP)\mptest\mptest.c \ - /link $(LTLINKOPTS) $(LTLIBPATHS) libsqlite3.lib $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) +sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h + $(LTLINK) $(TOP)\tool\sqldiff.c sqlite3.c + +fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h + $(LTLINK) $(TOP)\tool\fuzzershell.c sqlite3.c + +mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h + $(LTLINK) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \ + /link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) + +MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20 +MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20 + +mptest: mptester.exe + del /Q mptest.db 2>NUL + $(MPTEST1) --journalmode DELETE + $(MPTEST2) --journalmode WAL + $(MPTEST1) --journalmode WAL + $(MPTEST2) --journalmode PERSIST + $(MPTEST1) --journalmode PERSIST + $(MPTEST2) --journalmode TRUNCATE + $(MPTEST1) --journalmode TRUNCATE + $(MPTEST2) --journalmode DELETE # This target creates a directory named "tsrc" and fills it with # copies of all of the C source code and header files needed to @@ -1032,10 +1218,14 @@ mptester.exe: $(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h # all that automatic generation. # .target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl - -rmdir /S/Q tsrc + -rmdir /Q/S tsrc 2>NUL -mkdir tsrc - for %i in ($(SRC)) do copy /Y %i tsrc - del /Q tsrc\sqlite.h.in tsrc\parse.y + for %i in ($(SRC1)) do copy /Y %i tsrc + for %i in ($(SRC2)) do copy /Y %i tsrc + for %i in ($(SRC3)) do copy /Y %i tsrc + for %i in ($(SRC4)) do copy /Y %i tsrc + for %i in ($(SRC5)) do copy /Y %i tsrc + del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new move vdbe.new tsrc\vdbe.c echo > .target_source @@ -1060,7 +1250,7 @@ SQLITE3C = sqlite3.c # Rule to build the amalgamation # sqlite3.lo: $(SQLITE3C) - $(LTCOMPILE) -c $(SQLITE3C) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C) # Rules to build the LEMON compiler generator # @@ -1078,10 +1268,10 @@ lemon.exe: $(TOP)\tool\lemon.c lempar.c # opcodes.lo # parse.lo: parse.c $(HDR) - $(LTCOMPILE) -c parse.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c parse.c opcodes.lo: opcodes.c - $(LTCOMPILE) -c opcodes.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c opcodes.c # Rule to build the Win32 resources object file. # @@ -1099,223 +1289,226 @@ $(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(HDR) # Rules to build individual *.lo files from files in the src directory. # alter.lo: $(TOP)\src\alter.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\alter.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\alter.c analyze.lo: $(TOP)\src\analyze.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\analyze.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\analyze.c attach.lo: $(TOP)\src\attach.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\attach.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\attach.c auth.lo: $(TOP)\src\auth.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\auth.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\auth.c backup.lo: $(TOP)\src\backup.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\backup.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\backup.c bitvec.lo: $(TOP)\src\bitvec.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\bitvec.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\bitvec.c btmutex.lo: $(TOP)\src\btmutex.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\btmutex.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\btmutex.c btree.lo: $(TOP)\src\btree.c $(HDR) $(TOP)\src\pager.h - $(LTCOMPILE) -c $(TOP)\src\btree.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\btree.c build.lo: $(TOP)\src\build.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\build.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\build.c callback.lo: $(TOP)\src\callback.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\callback.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\callback.c complete.lo: $(TOP)\src\complete.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\complete.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\complete.c ctime.lo: $(TOP)\src\ctime.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\ctime.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\ctime.c date.lo: $(TOP)\src\date.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\date.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c + +dbstat.lo: $(TOP)\src\date.c $(HDR) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbstat.c delete.lo: $(TOP)\src\delete.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\delete.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\delete.c expr.lo: $(TOP)\src\expr.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\expr.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\expr.c fault.lo: $(TOP)\src\fault.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\fault.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\fault.c fkey.lo: $(TOP)\src\fkey.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\fkey.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\fkey.c func.lo: $(TOP)\src\func.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\func.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\func.c global.lo: $(TOP)\src\global.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\global.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\global.c hash.lo: $(TOP)\src\hash.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\hash.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\hash.c insert.lo: $(TOP)\src\insert.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\insert.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\insert.c journal.lo: $(TOP)\src\journal.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\journal.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\journal.c legacy.lo: $(TOP)\src\legacy.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\legacy.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\legacy.c loadext.lo: $(TOP)\src\loadext.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\loadext.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\loadext.c main.lo: $(TOP)\src\main.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\main.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\main.c malloc.lo: $(TOP)\src\malloc.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\malloc.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\malloc.c mem0.lo: $(TOP)\src\mem0.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mem0.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem0.c mem1.lo: $(TOP)\src\mem1.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mem1.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem1.c mem2.lo: $(TOP)\src\mem2.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mem2.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem2.c mem3.lo: $(TOP)\src\mem3.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mem3.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem3.c mem5.lo: $(TOP)\src\mem5.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mem5.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mem5.c memjournal.lo: $(TOP)\src\memjournal.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\memjournal.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\memjournal.c mutex.lo: $(TOP)\src\mutex.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mutex.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex.c mutex_noop.lo: $(TOP)\src\mutex_noop.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mutex_noop.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_noop.c mutex_unix.lo: $(TOP)\src\mutex_unix.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mutex_unix.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_unix.c mutex_w32.lo: $(TOP)\src\mutex_w32.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\mutex_w32.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\mutex_w32.c notify.lo: $(TOP)\src\notify.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\notify.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\notify.c pager.lo: $(TOP)\src\pager.c $(HDR) $(TOP)\src\pager.h - $(LTCOMPILE) -c $(TOP)\src\pager.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pager.c pcache.lo: $(TOP)\src\pcache.c $(HDR) $(TOP)\src\pcache.h - $(LTCOMPILE) -c $(TOP)\src\pcache.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pcache.c pcache1.lo: $(TOP)\src\pcache1.c $(HDR) $(TOP)\src\pcache.h - $(LTCOMPILE) -c $(TOP)\src\pcache1.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pcache1.c os.lo: $(TOP)\src\os.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\os.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os.c os_unix.lo: $(TOP)\src\os_unix.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\os_unix.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_unix.c os_win.lo: $(TOP)\src\os_win.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\os_win.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\os_win.c pragma.lo: $(TOP)\src\pragma.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\pragma.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\pragma.c prepare.lo: $(TOP)\src\prepare.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\prepare.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\prepare.c printf.lo: $(TOP)\src\printf.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\printf.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\printf.c random.lo: $(TOP)\src\random.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\random.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\random.c resolve.lo: $(TOP)\src\resolve.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\resolve.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\resolve.c rowset.lo: $(TOP)\src\rowset.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\rowset.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\rowset.c select.lo: $(TOP)\src\select.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\select.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\select.c status.lo: $(TOP)\src\status.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\status.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\status.c table.lo: $(TOP)\src\table.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\table.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\table.c threads.lo: $(TOP)\src\threads.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\threads.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\threads.c tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR) - $(LTCOMPILE) -c $(TOP)\src\tokenize.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\tokenize.c trigger.lo: $(TOP)\src\trigger.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\trigger.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c update.lo: $(TOP)\src\update.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\update.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\update.c utf.lo: $(TOP)\src\utf.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\utf.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\utf.c util.lo: $(TOP)\src\util.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\util.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\util.c vacuum.lo: $(TOP)\src\vacuum.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vacuum.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vacuum.c vdbe.lo: $(TOP)\src\vdbe.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vdbe.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbe.c vdbeapi.lo: $(TOP)\src\vdbeapi.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vdbeapi.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeapi.c vdbeaux.lo: $(TOP)\src\vdbeaux.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vdbeaux.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeaux.c vdbeblob.lo: $(TOP)\src\vdbeblob.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vdbeblob.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbeblob.c vdbemem.lo: $(TOP)\src\vdbemem.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vdbemem.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbemem.c vdbesort.lo: $(TOP)\src\vdbesort.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vdbesort.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbesort.c vdbetrace.lo: $(TOP)\src\vdbetrace.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vdbetrace.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vdbetrace.c vtab.lo: $(TOP)\src\vtab.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\vtab.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\vtab.c wal.lo: $(TOP)\src\wal.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\wal.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wal.c walker.lo: $(TOP)\src\walker.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\walker.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\walker.c where.lo: $(TOP)\src\where.c $(HDR) - $(LTCOMPILE) -c $(TOP)\src\where.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\where.c tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) - $(LTCOMPILE) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c + $(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) - $(LTCOMPILE) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c + $(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c -tclsqlite3.exe: tclsqlite-shell.lo libsqlite3.lib $(LIBRESOBJS) - $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ libsqlite3.lib tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(LIBRESOBJS) + $(LTLINK) $(SQLITE3C) /link $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS) # Rules to build opcodes.c and opcodes.h # @@ -1330,7 +1523,7 @@ opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\mkopcodeh.awk parse.h: parse.c parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk - del /Q parse.y parse.h parse.h.temp + del /Q parse.y parse.h parse.h.temp 2>NUL copy $(TOP)\src\parse.y . .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y move parse.h parse.h.temp @@ -1351,67 +1544,67 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe # Rules to build the extension objects. # icu.lo: $(TOP)\ext\icu\icu.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\icu\icu.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\icu\icu.c fts2.lo: $(TOP)\ext\fts2\fts2.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2.c fts2_hash.lo: $(TOP)\ext\fts2\fts2_hash.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_hash.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_hash.c fts2_icu.lo: $(TOP)\ext\fts2\fts2_icu.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_icu.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_icu.c fts2_porter.lo: $(TOP)\ext\fts2\fts2_porter.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_porter.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_porter.c fts2_tokenizer.lo: $(TOP)\ext\fts2\fts2_tokenizer.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer.c fts2_tokenizer1.lo: $(TOP)\ext\fts2\fts2_tokenizer1.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer1.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts2\fts2_tokenizer1.c fts3.lo: $(TOP)\ext\fts3\fts3.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3.c fts3_aux.lo: $(TOP)\ext\fts3\fts3_aux.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_aux.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_aux.c fts3_expr.lo: $(TOP)\ext\fts3\fts3_expr.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_expr.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_expr.c fts3_hash.lo: $(TOP)\ext\fts3\fts3_hash.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_hash.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_hash.c fts3_icu.lo: $(TOP)\ext\fts3\fts3_icu.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_icu.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_icu.c fts3_snippet.lo: $(TOP)\ext\fts3\fts3_snippet.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_snippet.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_snippet.c fts3_porter.lo: $(TOP)\ext\fts3\fts3_porter.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_porter.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_porter.c fts3_tokenizer.lo: $(TOP)\ext\fts3\fts3_tokenizer.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer.c fts3_tokenizer1.lo: $(TOP)\ext\fts3\fts3_tokenizer1.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenizer1.c fts3_tokenize_vtab.lo: $(TOP)\ext\fts3\fts3_tokenize_vtab.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenize_vtab.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_tokenize_vtab.c fts3_unicode.lo: $(TOP)\ext\fts3\fts3_unicode.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode.c fts3_unicode2.lo: $(TOP)\ext\fts3\fts3_unicode2.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_unicode2.c fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\fts3\fts3_write.c rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR) - $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c # Rules to build the 'testfixture' application. @@ -1425,7 +1618,7 @@ TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN) -TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) libsqlite3.lib +TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) $(SHELL_CORE_DEP) TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C) !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) @@ -1442,100 +1635,108 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR) extensiontest: testfixture.exe testloadext.dll .\testfixture.exe $(TOP)\test\loadext.test -fulltest: testfixture.exe sqlite3.exe +fulltest: testfixture.exe sqlite3.exe fuzztest .\testfixture.exe $(TOP)\test\all.test -soaktest: testfixture.exe sqlite3.exe +soaktest: testfixture.exe sqlite3.exe fuzzoomtest .\testfixture.exe $(TOP)\test\all.test -soak=1 -fulltestonly: testfixture.exe sqlite3.exe +fulltestonly: testfixture.exe sqlite3.exe fuzztest .\testfixture.exe $(TOP)\test\full.test queryplantest: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\permutations.test queryplanner -test: testfixture.exe sqlite3.exe +fuzztest: fuzzershell.exe + .\fuzzershell.exe $(TOP)\test\fuzzdata1.txt $(TOP)\test\fuzzdata2.txt + +fuzzoomtest: fuzzershell.exe + .\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt --oom + +test: testfixture.exe sqlite3.exe fuzztest .\testfixture.exe $(TOP)\test\veryquick.test -sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl - copy $(SQLITE3C) + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@ +smoketest: testfixture.exe + .\testfixture.exe $(TOP)\test\main.test + +sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl + copy $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@ echo static const char *tclsh_main_loop(void){ >> $@ echo static const char *zMainloop = >> $@ $(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@ echo ; return zMainloop; } >> $@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS) - $(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \ + $(LTLINK) $(NO_WARN) -DBUILD_sqlite -DSQLITE_ENABLE_DBSTAT_VTAB -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \ /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) testloadext.lo: $(TOP)\src\test_loadext.c - $(LTCOMPILE) -c $(TOP)\src\test_loadext.c + $(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c testloadext.dll: testloadext.lo $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) - $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\tool\showdb.c $(SQLITE3C) showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) - $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\tool\showstat4.c $(SQLITE3C) showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) - $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\tool\showjournal.c $(SQLITE3C) showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) - $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\tool\showwal.c $(SQLITE3C) fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) - $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) - $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\tool\rollback-test.c $(SQLITE3C) LogEst.exe: $(TOP)\tool\logest.c sqlite3.h - $(LTLINK) -Fe$@ $(TOP)\tool\LogEst.c + $(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) - $(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\test\wordcount.c $(SQLITE3C) speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) - $(LTLINK) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ + $(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ $(TOP)\test\speedtest1.c $(SQLITE3C) clean: - del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib - del /Q *.cod *.da *.bb *.bbg gmon.out - del /Q sqlite3.h opcodes.c opcodes.h - del /Q lemon.* lempar.c parse.* - del /Q mkkeywordhash.* keywordhash.h - del /Q notasharedlib.* - -rmdir /Q/S .deps - -rmdir /Q/S .libs - -rmdir /Q/S quota2a - -rmdir /Q/S quota2b - -rmdir /Q/S quota2c - -rmdir /Q/S tsrc - del /Q .target_source - del /Q tclsqlite3.exe tclsqlite3.exp - del /Q testloadext.dll testloadext.exp - del /Q testfixture.exe testfixture.exp test.db - del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe - del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe - del /Q wordcount.exe - del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def - del /Q sqlite3.c sqlite3-*.c - del /Q sqlite3rc.h - del /Q shell.c sqlite3ext.h - del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c - del /Q sqlite-*-output.vsix - del /Q mptester.exe + del /Q *.exp *.lo *.ilk *.lib *.obj *.pdb 2>NUL + del /Q *.cod *.da *.bb *.bbg gmon.out 2>NUL + del /Q sqlite3.h opcodes.c opcodes.h 2>NUL + del /Q lemon.* lempar.c parse.* 2>NUL + del /Q mkkeywordhash.* keywordhash.h 2>NUL + del /Q notasharedlib.* 2>NUL + -rmdir /Q/S .deps 2>NUL + -rmdir /Q/S .libs 2>NUL + -rmdir /Q/S quota2a 2>NUL + -rmdir /Q/S quota2b 2>NUL + -rmdir /Q/S quota2c 2>NUL + -rmdir /Q/S tsrc 2>NUL + del /Q .target_source 2>NUL + del /Q tclsqlite3.exe 2>NUL + del /Q testloadext.dll 2>NUL + del /Q testfixture.exe test.db 2>NUL + del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL + del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL + del /Q mptester.exe wordcount.exe 2>NUL + del /Q sqlite3.exe sqlite3.dll sqlite3.def 2>NUL + del /Q sqlite3.c sqlite3-*.c 2>NUL + del /Q sqlite3rc.h 2>NUL + del /Q shell.c sqlite3ext.h 2>NUL + del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL + del /Q sqlite-*-output.vsix 2>NUL # Dynamic link library section. # @@ -1547,5 +1748,5 @@ sqlite3.def: libsqlite3.lib | $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \ | sort >> sqlite3.def -sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) sqlite3.def - $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) + $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) diff --git a/VERSION b/VERSION index 4982c85..ff280e4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.8.8.3 +3.8.10.2 diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am index 6fc4f33..88bc23d 100644 --- a/autoconf/Makefile.am +++ b/autoconf/Makefile.am @@ -7,8 +7,7 @@ libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 bin_PROGRAMS = sqlite3 sqlite3_SOURCES = shell.c sqlite3.h -sqlite3_LDADD = $(top_builddir)/libsqlite3.la @READLINE_LIBS@ -sqlite3_DEPENDENCIES = $(top_builddir)/libsqlite3.la +sqlite3_LDADD = sqlite3.$(OBJEXT) @READLINE_LIBS@ include_HEADERS = sqlite3.h sqlite3ext.h diff --git a/configure b/configure index 5c8a189..c73b820 100755 --- a/configure +++ b/configure @@ -1,18 +1,20 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.62 for sqlite 3.8.8.3. +# Generated by GNU Autoconf 2.69 for sqlite 3.8.10.2. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# # -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which @@ -20,23 +22,15 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; esac - fi - - -# PATH needs CR -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - as_nl=' ' export as_nl @@ -44,7 +38,13 @@ export as_nl as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else @@ -55,7 +55,7 @@ else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; - case $arg in + case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; @@ -78,13 +78,6 @@ if test "${PATH_SEPARATOR+set}" != set; then } fi -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - # IFS # We need space, tab and new line, in precisely that order. Quoting is @@ -94,15 +87,16 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. -case $0 in +as_myself= +case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done IFS=$as_save_IFS ;; @@ -114,12 +108,16 @@ if test "x$as_myself" = x; then fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - { (exit 1); exit 1; } + exit 1 fi -# Work around bugs in pre-3.0 UWIN ksh. -for as_var in ENV MAIL MAILPATH -do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' @@ -131,7 +129,293 @@ export LC_ALL LANGUAGE=C export LANGUAGE -# Required to use basename. +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr @@ -145,8 +429,12 @@ else as_basename=false fi +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi -# Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ @@ -166,295 +454,19 @@ $as_echo X/"$0" | } s/.*/./; q'` -# CDPATH. -$as_unset CDPATH +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits -if test "x$CONFIG_SHELL" = x; then - if (eval ":") 2>/dev/null; then - as_have_required=yes -else - as_have_required=no -fi - - if test $as_have_required = yes && (eval ": -(as_func_return () { - (exit \$1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = \"\$1\" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test \$exitcode = 0) || { (exit 1); exit 1; } - -( - as_lineno_1=\$LINENO - as_lineno_2=\$LINENO - test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && - test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } -") 2> /dev/null; then - : -else - as_candidate_shells= - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - case $as_dir in - /*) - for as_base in sh bash ksh sh5; do - as_candidate_shells="$as_candidate_shells $as_dir/$as_base" - done;; - esac -done -IFS=$as_save_IFS - - - for as_shell in $as_candidate_shells $SHELL; do - # Try only shells that exist, to save several forks. - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { ("$as_shell") 2> /dev/null <<\_ASEOF -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - -: -_ASEOF -}; then - CONFIG_SHELL=$as_shell - as_have_required=yes - if { "$as_shell" 2> /dev/null <<\_ASEOF -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - -: -(as_func_return () { - (exit $1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = "$1" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test $exitcode = 0) || { (exit 1); exit 1; } - -( - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } - -_ASEOF -}; then - break -fi - -fi - - done - - if test "x$CONFIG_SHELL" != x; then - for as_var in BASH_ENV ENV - do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - done - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} -fi - - - if test $as_have_required = no; then - echo This script requires a shell more modern than all the - echo shells that I found on your system. Please install a - echo modern shell, or manually run the script under such a - echo shell if you do have one. - { (exit 1); exit 1; } -fi - - -fi - -fi - - - -(eval "as_func_return () { - (exit \$1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = \"\$1\" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test \$exitcode = 0") || { - echo No shell found that supports shell functions. - echo Please tell bug-autoconf@gnu.org about your system, - echo including any error possibly output before this message. - echo This can help us improve future autoconf versions. - echo Configuration will now proceed without shell functions. -} - - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line after each line using $LINENO; the second 'sed' - # does the real work. The second script uses 'N' to pair each - # line-number line with the line containing $LINENO, and appends - # trailing '-' during substitution so that $LINENO is not a special - # case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # scripts with optimization help from Paolo Bonzini. Blame Lee - # E. McMahon (1931-1989) for sed's syntax. :-) + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= @@ -471,9 +483,12 @@ test \$exitcode = 0") || { s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). @@ -482,29 +497,18 @@ test \$exitcode = 0") || { exit } - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in +case `echo -n x` in #((((( -n*) - case `echo 'x\c'` in + case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. - *) ECHO_C='\c';; + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then @@ -519,49 +523,29 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then - as_mkdir_p=: + as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -571,7 +555,6 @@ as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} @@ -720,10 +703,11 @@ fi -exec 7<&0 &1 +test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` @@ -738,14 +722,14 @@ cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.8.8.3' -PACKAGE_STRING='sqlite 3.8.8.3' +PACKAGE_VERSION='3.8.10.2' +PACKAGE_STRING='sqlite 3.8.10.2' PACKAGE_BUGREPORT='' +PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ @@ -783,118 +767,120 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL -PATH_SEPARATOR -PACKAGE_NAME -PACKAGE_TARNAME -PACKAGE_VERSION -PACKAGE_STRING -PACKAGE_BUGREPORT -exec_prefix -prefix -program_transform_name -bindir -sbindir -libexecdir -datarootdir -datadir -sysconfdir -sharedstatedir -localstatedir -includedir -oldincludedir -docdir -infodir -htmldir -dvidir -pdfdir -psdir -libdir -localedir -mandir -DEFS -ECHO_C -ECHO_N -ECHO_T -LIBS -build_alias -host_alias -target_alias -LIBTOOL -build -build_cpu -build_vendor -build_os -host -host_cpu -host_vendor -host_os -CC -CFLAGS -LDFLAGS -CPPFLAGS -ac_ct_CC -EXEEXT -OBJEXT -SED -GREP -EGREP -FGREP -LD -DUMPBIN -ac_ct_DUMPBIN -NM -LN_S -OBJDUMP -AR -STRIP -RANLIB -lt_ECHO -DSYMUTIL -NMEDIT -LIPO -OTOOL -OTOOL64 -CPP -INSTALL_PROGRAM -INSTALL_SCRIPT -INSTALL_DATA -AWK -TCLSH_CMD -TCLLIBDIR -program_prefix -VERSION -RELEASE -VERSION_NUMBER -BUILD_CC -SQLITE_THREADSAFE -ALLOWRELEASE -TEMP_STORE -BUILD_EXEEXT -SQLITE_OS_UNIX -SQLITE_OS_WIN -TARGET_EXEEXT -TCL_VERSION -TCL_BIN_DIR -TCL_SRC_DIR -TCL_INCLUDE_SPEC -TCL_LIB_FILE -TCL_LIB_FLAG -TCL_LIB_SPEC -TCL_STUB_LIB_FILE -TCL_STUB_LIB_FLAG -TCL_STUB_LIB_SPEC -HAVE_TCL -TARGET_READLINE_LIBS -TARGET_READLINE_INC -TARGET_HAVE_READLINE -TARGET_DEBUG -USE_AMALGAMATION -OPT_FEATURE_FLAGS -USE_GCOV -BUILD_CFLAGS +ac_subst_vars='LTLIBOBJS LIBOBJS -LTLIBOBJS' +BUILD_CFLAGS +USE_GCOV +OPT_FEATURE_FLAGS +USE_AMALGAMATION +TARGET_DEBUG +TARGET_HAVE_READLINE +TARGET_READLINE_INC +TARGET_READLINE_LIBS +HAVE_TCL +TCL_SHLIB_SUFFIX +TCL_STUB_LIB_SPEC +TCL_STUB_LIB_FLAG +TCL_STUB_LIB_FILE +TCL_LIB_SPEC +TCL_LIB_FLAG +TCL_LIB_FILE +TCL_INCLUDE_SPEC +TCL_SRC_DIR +TCL_BIN_DIR +TCL_VERSION +TARGET_EXEEXT +SQLITE_OS_WIN +SQLITE_OS_UNIX +BUILD_EXEEXT +TEMP_STORE +ALLOWRELEASE +SQLITE_THREADSAFE +BUILD_CC +VERSION_NUMBER +RELEASE +VERSION +program_prefix +TCLLIBDIR +TCLSH_CMD +AWK +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +lt_ECHO +RANLIB +STRIP +AR +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking @@ -990,8 +976,9 @@ do fi case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -1036,8 +1023,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1063,8 +1049,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1268,8 +1253,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1285,8 +1269,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1316,17 +1299,17 @@ do | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) { $as_echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; @@ -1335,7 +1318,7 @@ Try \`$0 --help' for more information." >&2 $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -1343,16 +1326,14 @@ done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { $as_echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) { $as_echo "$as_me: error: Unrecognized options: $ac_unrecognized_opts" >&2 - { (exit 1); exit 1; }; } ;; - *) $as_echo "$as_me: WARNING: Unrecognized options: $ac_unrecognized_opts" >&2 ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1374,8 +1355,7 @@ do [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -1389,8 +1369,6 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1405,11 +1383,9 @@ test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - { $as_echo "$as_me: error: Working directory cannot be determined" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - { $as_echo "$as_me: error: pwd does not report name of working directory" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. @@ -1448,13 +1424,11 @@ else fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2 - { (exit 1); exit 1; }; } + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then @@ -1480,7 +1454,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.8.8.3 to adapt to many kinds of systems. +\`configure' configures sqlite 3.8.10.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1494,7 +1468,7 @@ Configuration: --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages + -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files @@ -1545,7 +1519,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.8.8.3:";; + short | recursive ) echo "Configuration of sqlite 3.8.10.2:";; esac cat <<\_ACEOF @@ -1589,7 +1563,7 @@ Some influential environment variables: LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor TCLLIBDIR Where to install tcl plugin @@ -1597,6 +1571,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. +Report bugs to the package provider. _ACEOF ac_status=$? fi @@ -1659,22 +1634,427 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.8.8.3 -generated by GNU Autoconf 2.62 +sqlite configure 3.8.10.2 +generated by GNU Autoconf 2.69 -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.8.8.3, which was -generated by GNU Autoconf 2.62. Invocation command line was +It was created by sqlite $as_me 3.8.10.2, which was +generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -1710,8 +2090,8 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" -done + $as_echo "PATH: $as_dir" + done IFS=$as_save_IFS } >&5 @@ -1748,9 +2128,9 @@ do ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" + as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else @@ -1766,13 +2146,13 @@ do -* ) ac_must_keep_next=true ;; esac fi - ac_configure_args="$ac_configure_args '$ac_arg'" + as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there @@ -1784,11 +2164,9 @@ trap 'exit_status=$? { echo - cat <<\_ASBOX -## ---------------- ## + $as_echo "## ---------------- ## ## Cache variables. ## -## ---------------- ## -_ASBOX +## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( @@ -1797,13 +2175,13 @@ _ASBOX case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -$as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) $as_unset $ac_var ;; + *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done @@ -1822,11 +2200,9 @@ $as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; ) echo - cat <<\_ASBOX -## ----------------- ## + $as_echo "## ----------------- ## ## Output variables. ## -## ----------------- ## -_ASBOX +## ----------------- ##" echo for ac_var in $ac_subst_vars do @@ -1839,11 +2215,9 @@ _ASBOX echo if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## + $as_echo "## ------------------- ## ## File substitutions. ## -## ------------------- ## -_ASBOX +## ------------------- ##" echo for ac_var in $ac_subst_files do @@ -1857,11 +2231,9 @@ _ASBOX fi if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## + $as_echo "## ----------- ## ## confdefs.h. ## -## ----------- ## -_ASBOX +## ----------- ##" echo cat confdefs.h echo @@ -1875,46 +2247,53 @@ _ASBOX exit $exit_status ' 0 for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h +$as_echo "/* confdefs.h */" > confdefs.h + # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - ac_site_file1=$CONFIG_SITE + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site @@ -1925,19 +2304,23 @@ fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue - if test -r "$ac_site_file"; then - { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5 + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; @@ -1945,7 +2328,7 @@ $as_echo "$as_me: loading cache $cache_file" >&6;} esac fi else - { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi @@ -1960,11 +2343,11 @@ for ac_var in $ac_precious_vars; do eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) - { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) - { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; @@ -1974,17 +2357,17 @@ $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else - { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi - { $as_echo "$as_me:$LINENO: former value: \`$ac_old_val'" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:$LINENO: current value: \`$ac_new_val'" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac @@ -1996,41 +2379,20 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then - { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -$as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi - - - - - - - - - - - - - - - - - - - - - - - - +## -------------------- ## +## Main body of script. ## +## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -2042,15 +2404,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu sqlite_version_sanity_check=`cat $srcdir/VERSION | tr -d '\n'` if test "$PACKAGE_VERSION" != "$sqlite_version_sanity_check" ; then -{ { $as_echo "$as_me:$LINENO: error: configure script is out of date: +as_fn_error $? "configure script is out of date: configure \$PACKAGE_VERSION = $PACKAGE_VERSION top level VERSION file = $sqlite_version_sanity_check -please regen with autoconf" >&5 -$as_echo "$as_me: error: configure script is out of date: - configure \$PACKAGE_VERSION = $PACKAGE_VERSION - top level VERSION file = $sqlite_version_sanity_check -please regen with autoconf" >&2;} - { (exit 1); exit 1; }; } +please regen with autoconf" "$LINENO" 5 fi ######### @@ -2058,7 +2415,7 @@ fi # case `pwd` in *\ * | *\ *) - { $as_echo "$as_me:$LINENO: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac @@ -2098,9 +2455,7 @@ for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do fi done if test -z "$ac_aux_dir"; then - { { $as_echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 -$as_echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -2114,35 +2469,27 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - { { $as_echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 -$as_echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 -{ $as_echo "$as_me:$LINENO: checking build system type" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } -if test "${ac_cv_build+set}" = set; then +if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && - { { $as_echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -$as_echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 -$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; -*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 -$as_echo "$as_me: error: invalid value of canonical build" >&2;} - { (exit 1); exit 1; }; };; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' @@ -2158,28 +2505,24 @@ IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac -{ $as_echo "$as_me:$LINENO: checking host system type" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } -if test "${ac_cv_host+set}" = set; then +if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 -$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; -*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 -$as_echo "$as_me: error: invalid value of canonical host" >&2;} - { (exit 1); exit 1; }; };; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' @@ -2203,9 +2546,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2216,24 +2559,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:$LINENO: result: $CC" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -2243,9 +2586,9 @@ if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2256,24 +2599,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -2282,12 +2625,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC @@ -2300,9 +2639,9 @@ if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2313,24 +2652,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:$LINENO: result: $CC" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -2340,9 +2679,9 @@ fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2354,18 +2693,18 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then @@ -2384,10 +2723,10 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:$LINENO: result: $CC" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -2399,9 +2738,9 @@ if test -z "$CC"; then do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2412,24 +2751,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - { $as_echo "$as_me:$LINENO: result: $CC" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -2443,9 +2782,9 @@ if test -z "$CC"; then do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2456,24 +2795,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -2486,12 +2825,8 @@ done else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC @@ -2501,55 +2836,37 @@ fi fi -test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. -$as_echo "$as_me:$LINENO: checking for C compiler version" >&5 +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 -{ (ac_try="$ac_compiler --version >&5" +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compiler --version >&5") 2>&5 +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -v >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compiler -v >&5") 2>&5 - ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -V >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compiler -V >&5") 2>&5 - ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2565,8 +2882,8 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -{ $as_echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: @@ -2582,17 +2899,17 @@ do done rm -f $ac_rmfiles -if { (ac_try="$ac_link_default" +if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, @@ -2609,7 +2926,7 @@ do # certainly right. break;; *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi @@ -2628,80 +2945,41 @@ test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi - -{ $as_echo "$as_me:$LINENO: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } -if test -z "$ac_file"; then - $as_echo "$as_me: failed program was:" >&5 +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext - -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -{ $as_echo "$as_me:$LINENO: result: yes" >&5 +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -{ $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -{ $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } -if { (ac_try="$ac_link" +if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with @@ -2716,30 +2994,83 @@ for ac_file in conftest.exe conftest conftest.*; do esac done else - { { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } fi - -rm -f conftest$ac_cv_exeext -{ $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT -{ $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5 +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then +if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2751,17 +3082,17 @@ main () } _ACEOF rm -f conftest.o conftest.obj -if { (ac_try="$ac_compile" +if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in @@ -2774,29 +3105,23 @@ else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } fi - rm -f conftest.$ac_cv_objext conftest.$ac_ext fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT -{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2810,37 +3135,16 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then +if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_compiler_gnu=no + ac_compiler_gnu=no fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes @@ -2849,20 +3153,16 @@ else fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2873,35 +3173,11 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - CFLAGS="" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2912,36 +3188,12 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_c_try_compile "$LINENO"; then : - ac_c_werror_flag=$ac_save_c_werror_flag +else + ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2952,42 +3204,17 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS @@ -3004,23 +3231,18 @@ else CFLAGS= fi fi -{ $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include -#include -#include +struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); @@ -3072,32 +3294,9 @@ for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then + if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done @@ -3108,17 +3307,19 @@ fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) - { $as_echo "$as_me:$LINENO: result: none needed" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) - { $as_echo "$as_me:$LINENO: result: unsupported" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac +if test "x$ac_cv_prog_cc_c89" != xno; then : +fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -3126,9 +3327,9 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } -if test "${ac_cv_path_SED+set}" = set; then +if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ @@ -3136,7 +3337,7 @@ else ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed - $as_unset ac_script || ac_script= + { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST @@ -3145,10 +3346,10 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_prog in sed gsed; do + for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue + as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in @@ -3165,7 +3366,7 @@ case `"$ac_path_SED" --version 2>&1` in $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` + as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" @@ -3180,19 +3381,17 @@ esac $ac_path_SED_found && break 3 done done -done + done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then - { { $as_echo "$as_me:$LINENO: error: no acceptable sed could be found in \$PATH" >&5 -$as_echo "$as_me: error: no acceptable sed could be found in \$PATH" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_SED" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed @@ -3210,9 +3409,9 @@ Xsed="$SED -e 1s/^X//" -{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then +if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then @@ -3223,10 +3422,10 @@ for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do + for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in @@ -3243,7 +3442,7 @@ case `"$ac_path_GREP" --version 2>&1` in $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` + as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" @@ -3258,26 +3457,24 @@ esac $ac_path_GREP_found && break 3 done done -done + done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then - { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" -{ $as_echo "$as_me:$LINENO: checking for egrep" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then +if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 @@ -3291,10 +3488,10 @@ for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do + for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in @@ -3311,7 +3508,7 @@ case `"$ac_path_EGREP" --version 2>&1` in $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` + as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" @@ -3326,12 +3523,10 @@ esac $ac_path_EGREP_found && break 3 done done -done + done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then - { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP @@ -3339,14 +3534,14 @@ fi fi fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" -{ $as_echo "$as_me:$LINENO: checking for fgrep" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } -if test "${ac_cv_path_FGREP+set}" = set; then +if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 @@ -3360,10 +3555,10 @@ for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_prog in fgrep; do + for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue + as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in @@ -3380,7 +3575,7 @@ case `"$ac_path_FGREP" --version 2>&1` in $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` + as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" @@ -3395,12 +3590,10 @@ esac $ac_path_FGREP_found && break 3 done done -done + done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then - { { $as_echo "$as_me:$LINENO: error: no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -$as_echo "$as_me: error: no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP @@ -3408,7 +3601,7 @@ fi fi fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_FGREP" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" @@ -3434,7 +3627,7 @@ test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. -if test "${with_gnu_ld+set}" = set; then +if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no @@ -3443,7 +3636,7 @@ fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. - { $as_echo "$as_me:$LINENO: checking for ld used by $CC" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) @@ -3473,13 +3666,13 @@ $as_echo_n "checking for ld used by $CC... " >&6; } ;; esac elif test "$with_gnu_ld" = yes; then - { $as_echo "$as_me:$LINENO: checking for GNU ld" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else - { $as_echo "$as_me:$LINENO: checking for non-GNU ld" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi -if test "${lt_cv_path_LD+set}" = set; then +if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then @@ -3510,18 +3703,16 @@ fi LD="$lt_cv_path_LD" if test -n "$LD"; then - { $as_echo "$as_me:$LINENO: result: $LD" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 $as_echo "$LD" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi -test -z "$LD" && { { $as_echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 -$as_echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} - { (exit 1); exit 1; }; } -{ $as_echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if test "${lt_cv_prog_gnu_ld+set}" = set; then +if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. @@ -3534,7 +3725,7 @@ case `$LD -v 2>&1 &5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld @@ -3546,9 +3737,9 @@ with_gnu_ld=$lt_cv_prog_gnu_ld -{ $as_echo "$as_me:$LINENO: checking for BSD- or MS-compatible name lister (nm)" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } -if test "${lt_cv_path_NM+set}" = set; then +if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then @@ -3595,7 +3786,7 @@ else : ${lt_cv_path_NM=no} fi fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" @@ -3606,9 +3797,9 @@ else do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_DUMPBIN+set}" = set; then +if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then @@ -3619,24 +3810,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then - { $as_echo "$as_me:$LINENO: result: $DUMPBIN" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -3650,9 +3841,9 @@ if test -z "$DUMPBIN"; then do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then @@ -3663,24 +3854,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_DUMPBIN" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -3693,12 +3884,8 @@ done else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN @@ -3717,44 +3904,44 @@ test -z "$NM" && NM=nm -{ $as_echo "$as_me:$LINENO: checking the name lister ($NM) interface" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } -if test "${lt_cv_nm_interface+set}" = set; then +if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:3727: $ac_compile\"" >&5) + (eval echo "\"\$as_me:3914: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:3730: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:3917: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:3733: output\"" >&5) + (eval echo "\"\$as_me:3920: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_nm_interface" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } -{ $as_echo "$as_me:$LINENO: checking whether ln -s works" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then - { $as_echo "$as_me:$LINENO: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else - { $as_echo "$as_me:$LINENO: result: no, using $LN_S" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments -{ $as_echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } -if test "${lt_cv_sys_max_cmd_len+set}" = set; then +if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 @@ -3872,10 +4059,10 @@ else fi if test -n $lt_cv_sys_max_cmd_len ; then - { $as_echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else - { $as_echo "$as_me:$LINENO: result: none" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len @@ -3889,7 +4076,7 @@ max_cmd_len=$lt_cv_sys_max_cmd_len : ${MV="mv -f"} : ${RM="rm -f"} -{ $as_echo "$as_me:$LINENO: checking whether the shell understands some XSI constructs" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no @@ -3899,17 +4086,17 @@ xsi_shell=no && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes -{ $as_echo "$as_me:$LINENO: result: $xsi_shell" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } -{ $as_echo "$as_me:$LINENO: checking whether the shell understands \"+=\"" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes -{ $as_echo "$as_me:$LINENO: result: $lt_shell_append" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } @@ -3944,14 +4131,14 @@ esac -{ $as_echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } -if test "${lt_cv_ld_reload_flag+set}" = set; then +if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in @@ -3980,9 +4167,9 @@ esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OBJDUMP+set}" = set; then +if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then @@ -3993,24 +4180,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then - { $as_echo "$as_me:$LINENO: result: $OBJDUMP" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -4020,9 +4207,9 @@ if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then @@ -4033,24 +4220,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -4059,12 +4246,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP @@ -4083,9 +4266,9 @@ test -z "$OBJDUMP" && OBJDUMP=objdump -{ $as_echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } -if test "${lt_cv_deplibs_check_method+set}" = set; then +if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' @@ -4279,7 +4462,7 @@ tpf*) esac fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method @@ -4299,9 +4482,9 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AR+set}" = set; then +if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then @@ -4312,24 +4495,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then - { $as_echo "$as_me:$LINENO: result: $AR" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -4339,9 +4522,9 @@ if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_AR+set}" = set; then +if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then @@ -4352,24 +4535,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -4378,12 +4561,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR @@ -4408,9 +4587,9 @@ test -z "$AR_FLAGS" && AR_FLAGS=cru if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then +if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then @@ -4421,24 +4600,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then - { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -4448,9 +4627,9 @@ if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then @@ -4461,24 +4640,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -4487,12 +4666,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP @@ -4511,9 +4686,9 @@ test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RANLIB+set}" = set; then +if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then @@ -4524,24 +4699,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then - { $as_echo "$as_me:$LINENO: result: $RANLIB" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -4551,9 +4726,9 @@ if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then @@ -4564,24 +4739,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -4590,12 +4765,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB @@ -4672,9 +4843,9 @@ compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. -{ $as_echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } -if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then +if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else @@ -4790,18 +4961,18 @@ void nm_test_func(void){} int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm - if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s "$nlist"; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" @@ -4854,11 +5025,11 @@ _LT_EOF lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext}; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" @@ -4892,10 +5063,10 @@ if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - { $as_echo "$as_me:$LINENO: result: failed" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else - { $as_echo "$as_me:$LINENO: result: ok" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi @@ -4922,7 +5093,7 @@ fi # Check whether --enable-libtool-lock was given. -if test "${enable_libtool_lock+set}" = set; then +if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi @@ -4934,11 +5105,11 @@ case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" @@ -4952,12 +5123,12 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 4955 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + echo '#line 5126 "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) @@ -4991,11 +5162,11 @@ x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in @@ -5044,9 +5215,9 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" - { $as_echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } -if test "${lt_cv_cc_needs_belf+set}" = set; then +if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c @@ -5055,11 +5226,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -5070,38 +5237,13 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - lt_cv_cc_needs_belf=no + lt_cv_cc_needs_belf=no fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -5109,7 +5251,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf @@ -5119,11 +5261,11 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in @@ -5149,9 +5291,9 @@ need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_DSYMUTIL+set}" = set; then +if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then @@ -5162,24 +5304,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then - { $as_echo "$as_me:$LINENO: result: $DSYMUTIL" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5189,9 +5331,9 @@ if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then @@ -5202,24 +5344,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_DSYMUTIL" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5228,12 +5370,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL @@ -5245,9 +5383,9 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_NMEDIT+set}" = set; then +if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then @@ -5258,24 +5396,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then - { $as_echo "$as_me:$LINENO: result: $NMEDIT" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5285,9 +5423,9 @@ if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then @@ -5298,24 +5436,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_NMEDIT" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5324,12 +5462,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT @@ -5341,9 +5475,9 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_LIPO+set}" = set; then +if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then @@ -5354,24 +5488,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then - { $as_echo "$as_me:$LINENO: result: $LIPO" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5381,9 +5515,9 @@ if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then @@ -5394,24 +5528,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_LIPO" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5420,12 +5554,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO @@ -5437,9 +5567,9 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OTOOL+set}" = set; then +if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then @@ -5450,24 +5580,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then - { $as_echo "$as_me:$LINENO: result: $OTOOL" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5477,9 +5607,9 @@ if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then @@ -5490,24 +5620,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_OTOOL" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5516,12 +5646,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL @@ -5533,9 +5659,9 @@ fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OTOOL64+set}" = set; then +if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then @@ -5546,24 +5672,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then - { $as_echo "$as_me:$LINENO: result: $OTOOL64" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5573,9 +5699,9 @@ if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then @@ -5586,24 +5712,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then - { $as_echo "$as_me:$LINENO: result: $ac_ct_OTOOL64" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -5612,12 +5738,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 @@ -5652,9 +5774,9 @@ fi - { $as_echo "$as_me:$LINENO: checking for -single_module linker flag" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } -if test "${lt_cv_apple_cc_single_mod+set}" = set; then +if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no @@ -5679,22 +5801,18 @@ else rm -f conftest.* fi fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_apple_cc_single_mod" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } - { $as_echo "$as_me:$LINENO: checking for -exported_symbols_list linker flag" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } -if test "${lt_cv_ld_exported_symbols_list+set}" = set; then +if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -5705,42 +5823,17 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - lt_cv_ld_exported_symbols_list=no + lt_cv_ld_exported_symbols_list=no fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_ld_exported_symbols_list" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } case $host_os in rhapsody* | darwin1.[012]) @@ -5782,14 +5875,14 @@ ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then + if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded @@ -5804,11 +5897,7 @@ do # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include @@ -5817,78 +5906,34 @@ cat >>conftest.$ac_ext <<_ACEOF #endif Syntax error _ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_c_try_cpp "$LINENO"; then : +else # Broken: fails on valid input. continue fi - -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then +if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - # Passes both tests. ac_preproc_ok=: break fi - -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : break fi @@ -5900,7 +5945,7 @@ fi else ac_cv_prog_CPP=$CPP fi -{ $as_echo "$as_me:$LINENO: result: $CPP" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes @@ -5911,11 +5956,7 @@ do # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include @@ -5924,85 +5965,40 @@ cat >>conftest.$ac_ext <<_ACEOF #endif Syntax error _ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_c_try_cpp "$LINENO"; then : +else # Broken: fails on valid input. continue fi - -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then +if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - # Passes both tests. ac_preproc_ok=: break fi - -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + else - { { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c @@ -6012,16 +6008,12 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include @@ -6036,48 +6028,23 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_header_stdc=no + ac_cv_header_stdc=no fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : + $EGREP "memchr" >/dev/null 2>&1; then : + else ac_cv_header_stdc=no fi @@ -6087,18 +6054,14 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : + $EGREP "free" >/dev/null 2>&1; then : + else ac_cv_header_stdc=no fi @@ -6108,14 +6071,10 @@ fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then + if test "$cross_compiling" = yes; then : : else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include @@ -6142,117 +6101,33 @@ main () return 0; } _ACEOF -rm -f conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : +if ac_fn_c_try_run "$LINENO"; then : + else - $as_echo "$as_me: program exited with status $ac_status" >&5 -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no + ac_cv_header_stdc=no fi -rm -rf conftest.dSYM -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi - fi fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF +$as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h -do -as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 -$as_echo_n "checking for $ac_header... " >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - $as_echo_n "(cached) " >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - eval "$as_ac_Header=yes" -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_Header=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -ac_res=`eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` - { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test `eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` = yes; then +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -6262,61 +6137,13 @@ fi done - for ac_header in dlfcn.h -do -as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 -$as_echo_n "checking for $ac_header... " >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - $as_echo_n "(cached) " >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - eval "$as_ac_Header=yes" -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_Header=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -ac_res=`eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` - { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test `eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` = yes; then +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define HAVE_DLFCN_H 1 _ACEOF fi @@ -6336,7 +6163,7 @@ done # Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then +if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; @@ -6367,7 +6194,7 @@ fi # Check whether --enable-static was given. -if test "${enable_static+set}" = set; then +if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; @@ -6399,7 +6226,7 @@ fi # Check whether --with-pic was given. -if test "${with_pic+set}" = set; then +if test "${with_pic+set}" = set; then : withval=$with_pic; pic_mode="$withval" else pic_mode=default @@ -6415,7 +6242,7 @@ test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. -if test "${enable_fast_install+set}" = set; then +if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; @@ -6496,9 +6323,9 @@ if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi -{ $as_echo "$as_me:$LINENO: checking for objdir" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } -if test "${lt_cv_objdir+set}" = set; then +if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null @@ -6511,7 +6338,7 @@ else fi rmdir .libs 2>/dev/null fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir @@ -6604,9 +6431,9 @@ test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then - { $as_echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then +if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in @@ -6657,10 +6484,10 @@ fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -6670,9 +6497,9 @@ fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then - { $as_echo "$as_me:$LINENO: checking for file" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then +if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in @@ -6723,10 +6550,10 @@ fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then - { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -6803,9 +6630,9 @@ lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' - { $as_echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no @@ -6821,11 +6648,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6824: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6651: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6828: \$? = $ac_status" >&5 + echo "$as_me:6655: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -6838,7 +6665,7 @@ else $RM conftest* fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then @@ -6858,7 +6685,7 @@ fi lt_prog_compiler_pic= lt_prog_compiler_static= -{ $as_echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then @@ -7130,7 +6957,7 @@ case $host_os in lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac -{ $as_echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 $as_echo "$lt_prog_compiler_pic" >&6; } @@ -7142,9 +6969,9 @@ $as_echo "$lt_prog_compiler_pic" >&6; } # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then - { $as_echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } -if test "${lt_cv_prog_compiler_pic_works+set}" = set; then +if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no @@ -7160,11 +6987,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7163: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6990: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7167: \$? = $ac_status" >&5 + echo "$as_me:6994: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7177,7 +7004,7 @@ else $RM conftest* fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then @@ -7201,9 +7028,9 @@ fi # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" -{ $as_echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if test "${lt_cv_prog_compiler_static_works+set}" = set; then +if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no @@ -7229,7 +7056,7 @@ else LDFLAGS="$save_LDFLAGS" fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then @@ -7244,9 +7071,9 @@ fi - { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if test "${lt_cv_prog_compiler_c_o+set}" = set; then +if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no @@ -7265,11 +7092,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7268: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7095: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7272: \$? = $ac_status" >&5 + echo "$as_me:7099: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -7291,7 +7118,7 @@ else $RM conftest* fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } @@ -7299,9 +7126,9 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; } - { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if test "${lt_cv_prog_compiler_c_o+set}" = set; then +if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no @@ -7320,11 +7147,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7323: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7150: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7327: \$? = $ac_status" >&5 + echo "$as_me:7154: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -7346,7 +7173,7 @@ else $RM conftest* fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } @@ -7355,7 +7182,7 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user - { $as_echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* @@ -7363,10 +7190,10 @@ $as_echo_n "checking if we can lock with hard links... " >&6; } touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no - { $as_echo "$as_me:$LINENO: result: $hard_links" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then - { $as_echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi @@ -7379,7 +7206,7 @@ fi - { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= @@ -7821,11 +7648,7 @@ _LT_EOF allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7836,27 +7659,7 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { @@ -7870,16 +7673,9 @@ aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpat if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" @@ -7892,11 +7688,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi else # Determine the default libpath from the value encoded in an # empty executable. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7907,27 +7699,7 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { @@ -7941,16 +7713,9 @@ aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpat if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" @@ -8162,42 +7927,16 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - cat >conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ int foo(void) {} _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' @@ -8453,7 +8192,7 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ fi fi -{ $as_echo "$as_me:$LINENO: result: $ld_shlibs" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no @@ -8490,16 +8229,16 @@ x|xyes) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. - { $as_echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } 2>conftest.err; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext @@ -8513,11 +8252,11 @@ $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= - if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } then archive_cmds_need_lc=no else @@ -8528,7 +8267,7 @@ $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } cat conftest.err 1>&5 fi $RM conftest* - { $as_echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 $as_echo "$archive_cmds_need_lc" >&6; } ;; esac @@ -8692,7 +8431,7 @@ esac - { $as_echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then @@ -9127,11 +8866,7 @@ linux* | k*bsd*-gnu) save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -9142,41 +8877,13 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then - if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : shlibpath_overrides_runpath=yes fi - -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir @@ -9388,7 +9095,7 @@ uts4*) dynamic_linker=no ;; esac -{ $as_echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no @@ -9490,7 +9197,7 @@ fi - { $as_echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || @@ -9515,7 +9222,7 @@ else # directories. hardcode_action=unsupported fi -{ $as_echo "$as_me:$LINENO: result: $hardcode_action" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || @@ -9560,18 +9267,14 @@ else darwin*) # if libdl is installed we need to link against it - { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then +if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -9589,43 +9292,18 @@ return dlopen (); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dl_dlopen=no + ac_cv_lib_dl_dlopen=no fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test $ac_cv_lib_dl_dlopen = yes; then +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else @@ -9638,106 +9316,18 @@ fi ;; *) - { $as_echo "$as_me:$LINENO: checking for shl_load" >&5 -$as_echo_n "checking for shl_load... " >&6; } -if test "${ac_cv_func_shl_load+set}" = set; then - $as_echo_n "(cached) " >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_shl_load || defined __stub___shl_load -choke me -#endif - -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then - ac_cv_func_shl_load=yes -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_func_shl_load=no -fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -$as_echo "$ac_cv_func_shl_load" >&6; } -if test $ac_cv_func_shl_load = yes; then + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else - { $as_echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } -if test "${ac_cv_lib_dld_shl_load+set}" = set; then +if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -9755,145 +9345,32 @@ return shl_load (); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dld_shl_load=no + ac_cv_lib_dld_shl_load=no fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } -if test $ac_cv_lib_dld_shl_load = yes; then +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else - { $as_echo "$as_me:$LINENO: checking for dlopen" >&5 -$as_echo_n "checking for dlopen... " >&6; } -if test "${ac_cv_func_dlopen+set}" = set; then - $as_echo_n "(cached) " >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define dlopen to an innocuous variant, in case declares dlopen. - For example, HP-UX 11i declares gettimeofday. */ -#define dlopen innocuous_dlopen - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char dlopen (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef dlopen - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_dlopen || defined __stub___dlopen -choke me -#endif - -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then - ac_cv_func_dlopen=yes -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_func_dlopen=no -fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 -$as_echo "$ac_cv_func_dlopen" >&6; } -if test $ac_cv_func_dlopen = yes; then + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else - { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then +if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -9911,57 +9388,28 @@ return dlopen (); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dl_dlopen=no + ac_cv_lib_dl_dlopen=no fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test $ac_cv_lib_dl_dlopen = yes; then +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else - { $as_echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } -if test "${ac_cv_lib_svld_dlopen+set}" = set; then +if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -9979,57 +9427,28 @@ return dlopen (); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_svld_dlopen=no + ac_cv_lib_svld_dlopen=no fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } -if test $ac_cv_lib_svld_dlopen = yes; then +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else - { $as_echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } -if test "${ac_cv_lib_dld_dld_link+set}" = set; then +if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -10047,43 +9466,18 @@ return dld_link (); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dld_dld_link=no + ac_cv_lib_dld_dld_link=no fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } -if test $ac_cv_lib_dld_dld_link = yes; then +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi @@ -10122,9 +9516,9 @@ fi save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" - { $as_echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } -if test "${lt_cv_dlopen_self+set}" = set; then +if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : @@ -10133,7 +9527,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10136 "configure" +#line 9530 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10192,11 +9586,11 @@ int main () return status; } _LT_EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -10213,14 +9607,14 @@ rm -fr conftest* fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - { $as_echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } -if test "${lt_cv_dlopen_self_static+set}" = set; then +if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : @@ -10229,7 +9623,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10232 "configure" +#line 9626 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10288,11 +9682,11 @@ int main () return status; } _LT_EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -10309,7 +9703,7 @@ rm -fr conftest* fi -{ $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi @@ -10348,12 +9742,12 @@ fi striplib= old_striplib= -{ $as_echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" - { $as_echo "$as_me:$LINENO: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough @@ -10362,15 +9756,15 @@ else if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" - { $as_echo "$as_me:$LINENO: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac @@ -10388,12 +9782,12 @@ fi # Report which library types will actually be built - { $as_echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } - { $as_echo "$as_me:$LINENO: result: $can_build_shared" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } - { $as_echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no @@ -10414,14 +9808,14 @@ $as_echo_n "checking whether to build shared libraries... " >&6; } fi ;; esac - { $as_echo "$as_me:$LINENO: result: $enable_shared" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } - { $as_echo "$as_me:$LINENO: checking whether to build static libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes - { $as_echo "$as_me:$LINENO: result: $enable_static" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } @@ -10470,10 +9864,10 @@ CC="$lt_save_CC" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then +if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -10481,11 +9875,11 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. @@ -10493,7 +9887,7 @@ case $as_dir/ in # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. @@ -10522,7 +9916,7 @@ case $as_dir/ in ;; esac -done + done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir @@ -10538,7 +9932,7 @@ fi INSTALL=$ac_install_sh fi fi -{ $as_echo "$as_me:$LINENO: result: $INSTALL" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. @@ -10553,9 +9947,9 @@ for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AWK+set}" = set; then +if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then @@ -10566,24 +9960,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then - { $as_echo "$as_me:$LINENO: result: $AWK" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -10596,15 +9990,15 @@ done # Enable large file support (if special flags are necessary) # # Check whether --enable-largefile was given. -if test "${enable_largefile+set}" = set; then +if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then - { $as_echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } -if test "${ac_cv_sys_largefile_CC+set}" = set; then +if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no @@ -10613,11 +10007,7 @@ else while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. @@ -10636,60 +10026,14 @@ main () return 0; } _ACEOF - rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then + if ac_fn_c_try_compile "$LINENO"; then : break -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" - rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then + if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - rm -f core conftest.err conftest.$ac_objext break done @@ -10697,23 +10041,19 @@ rm -f core conftest.err conftest.$ac_objext rm -f conftest.$ac_ext fi fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 $as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi - { $as_echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } -if test "${ac_cv_sys_file_offset_bits+set}" = set; then +if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. @@ -10732,38 +10072,11 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include @@ -10783,38 +10096,15 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; @@ -10826,17 +10116,13 @@ _ACEOF esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then - { $as_echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } -if test "${ac_cv_sys_large_files+set}" = set; then +if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. @@ -10855,38 +10141,11 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include @@ -10906,38 +10165,15 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; @@ -10949,106 +10185,15 @@ _ACEOF esac rm -rf conftest* fi + + fi ######### # Check for needed/wanted data types -{ $as_echo "$as_me:$LINENO: checking for int8_t" >&5 -$as_echo_n "checking for int8_t... " >&6; } -if test "${ac_cv_type_int8_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_int8_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (int8_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((int8_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_int8_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_int8_t" >&5 -$as_echo "$ac_cv_type_int8_t" >&6; } -if test $ac_cv_type_int8_t = yes; then +ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" +if test "x$ac_cv_type_int8_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT8_T 1 @@ -11056,101 +10201,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for int16_t" >&5 -$as_echo_n "checking for int16_t... " >&6; } -if test "${ac_cv_type_int16_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_int16_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (int16_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((int16_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_int16_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_int16_t" >&5 -$as_echo "$ac_cv_type_int16_t" >&6; } -if test $ac_cv_type_int16_t = yes; then +ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" +if test "x$ac_cv_type_int16_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT16_T 1 @@ -11158,101 +10210,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for int32_t" >&5 -$as_echo_n "checking for int32_t... " >&6; } -if test "${ac_cv_type_int32_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_int32_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (int32_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((int32_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_int32_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_int32_t" >&5 -$as_echo "$ac_cv_type_int32_t" >&6; } -if test $ac_cv_type_int32_t = yes; then +ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" +if test "x$ac_cv_type_int32_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT32_T 1 @@ -11260,101 +10219,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for int64_t" >&5 -$as_echo_n "checking for int64_t... " >&6; } -if test "${ac_cv_type_int64_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_int64_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (int64_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((int64_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_int64_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_int64_t" >&5 -$as_echo "$ac_cv_type_int64_t" >&6; } -if test $ac_cv_type_int64_t = yes; then +ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" +if test "x$ac_cv_type_int64_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT64_T 1 @@ -11362,101 +10228,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for intptr_t" >&5 -$as_echo_n "checking for intptr_t... " >&6; } -if test "${ac_cv_type_intptr_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_intptr_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (intptr_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((intptr_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_intptr_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_intptr_t" >&5 -$as_echo "$ac_cv_type_intptr_t" >&6; } -if test $ac_cv_type_intptr_t = yes; then +ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default" +if test "x$ac_cv_type_intptr_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INTPTR_T 1 @@ -11464,101 +10237,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for uint8_t" >&5 -$as_echo_n "checking for uint8_t... " >&6; } -if test "${ac_cv_type_uint8_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_uint8_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (uint8_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((uint8_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_uint8_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uint8_t" >&5 -$as_echo "$ac_cv_type_uint8_t" >&6; } -if test $ac_cv_type_uint8_t = yes; then +ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default" +if test "x$ac_cv_type_uint8_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT8_T 1 @@ -11566,101 +10246,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for uint16_t" >&5 -$as_echo_n "checking for uint16_t... " >&6; } -if test "${ac_cv_type_uint16_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_uint16_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (uint16_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((uint16_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_uint16_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uint16_t" >&5 -$as_echo "$ac_cv_type_uint16_t" >&6; } -if test $ac_cv_type_uint16_t = yes; then +ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default" +if test "x$ac_cv_type_uint16_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT16_T 1 @@ -11668,101 +10255,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for uint32_t" >&5 -$as_echo_n "checking for uint32_t... " >&6; } -if test "${ac_cv_type_uint32_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_uint32_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (uint32_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((uint32_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_uint32_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uint32_t" >&5 -$as_echo "$ac_cv_type_uint32_t" >&6; } -if test $ac_cv_type_uint32_t = yes; then +ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default" +if test "x$ac_cv_type_uint32_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT32_T 1 @@ -11770,101 +10264,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for uint64_t" >&5 -$as_echo_n "checking for uint64_t... " >&6; } -if test "${ac_cv_type_uint64_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_uint64_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (uint64_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((uint64_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_uint64_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uint64_t" >&5 -$as_echo "$ac_cv_type_uint64_t" >&6; } -if test $ac_cv_type_uint64_t = yes; then +ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" +if test "x$ac_cv_type_uint64_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT64_T 1 @@ -11872,101 +10273,8 @@ _ACEOF fi -{ $as_echo "$as_me:$LINENO: checking for uintptr_t" >&5 -$as_echo_n "checking for uintptr_t... " >&6; } -if test "${ac_cv_type_uintptr_t+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_type_uintptr_t=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof (uintptr_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if (sizeof ((uintptr_t))) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_uintptr_t=yes -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5 -$as_echo "$ac_cv_type_uintptr_t" >&6; } -if test $ac_cv_type_uintptr_t = yes; then +ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default" +if test "x$ac_cv_type_uintptr_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINTPTR_T 1 @@ -11978,147 +10286,11 @@ fi ######### # Check for needed/wanted headers - - - - - for ac_header in sys/types.h stdlib.h stdint.h inttypes.h malloc.h -do -as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 -$as_echo_n "checking for $ac_header... " >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - $as_echo_n "(cached) " >&6 -fi -ac_res=`eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` - { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 -$as_echo_n "checking $ac_header usability... " >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_header_compiler=yes -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 -$as_echo_n "checking $ac_header presence... " >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - - ;; -esac -{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 -$as_echo_n "checking for $ac_header... " >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - $as_echo_n "(cached) " >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -ac_res=`eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` - { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - -fi -if test `eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` = yes; then +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -12131,107 +10303,11 @@ done ######### # Figure out whether or not we have these functions # - - - - - - - - - for ac_func in fdatasync gmtime_r isnan localtime_r localtime_s malloc_usable_size strchrnul usleep utime -do -as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 -$as_echo_n "checking for $ac_func... " >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - $as_echo_n "(cached) " >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then - eval "$as_ac_var=yes" -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval 'as_val=${'$as_ac_var'} - $as_echo "$as_val"'` - { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test `eval 'as_val=${'$as_ac_var'} - $as_echo "$as_val"'` = yes; then +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -12254,9 +10330,9 @@ for ac_prog in tclsh8.6 tclsh8.5 tclsh do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_TCLSH_CMD+set}" = set; then +if ${ac_cv_prog_TCLSH_CMD+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$TCLSH_CMD"; then @@ -12267,24 +10343,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_TCLSH_CMD="$ac_prog" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi TCLSH_CMD=$ac_cv_prog_TCLSH_CMD if test -n "$TCLSH_CMD"; then - { $as_echo "$as_me:$LINENO: result: $TCLSH_CMD" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_CMD" >&5 $as_echo "$TCLSH_CMD" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -12322,17 +10398,17 @@ fi VERSION=`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'` -{ $as_echo "$as_me:$LINENO: Version set to $VERSION" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: Version set to $VERSION" >&5 $as_echo "$as_me: Version set to $VERSION" >&6;} RELEASE=`cat $srcdir/VERSION` -{ $as_echo "$as_me:$LINENO: Release set to $RELEASE" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: Release set to $RELEASE" >&5 $as_echo "$as_me: Release set to $RELEASE" >&6;} VERSION_NUMBER=`cat $srcdir/VERSION \ | sed 's/[^0-9]/ /g' \ | awk '{printf "%d%03d%03d",$1,$2,$3}'` -{ $as_echo "$as_me:$LINENO: Version number set to $VERSION_NUMBER" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: Version number set to $VERSION_NUMBER" >&5 $as_echo "$as_me: Version number set to $VERSION_NUMBER" >&6;} @@ -12349,9 +10425,9 @@ else do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_BUILD_CC+set}" = set; then +if ${ac_cv_prog_BUILD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$BUILD_CC"; then @@ -12362,24 +10438,24 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_BUILD_CC="$ac_prog" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done IFS=$as_save_IFS fi fi BUILD_CC=$ac_cv_prog_BUILD_CC if test -n "$BUILD_CC"; then - { $as_echo "$as_me:$LINENO: result: $BUILD_CC" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 $as_echo "$BUILD_CC" >&6; } else - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi @@ -12398,37 +10474,33 @@ fi # Do we want to support multithreaded use of sqlite # # Check whether --enable-threadsafe was given. -if test "${enable_threadsafe+set}" = set; then +if test "${enable_threadsafe+set}" = set; then : enableval=$enable_threadsafe; else enable_threadsafe=yes fi -{ $as_echo "$as_me:$LINENO: checking whether to support threadsafe operation" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support threadsafe operation" >&5 $as_echo_n "checking whether to support threadsafe operation... " >&6; } if test "$enable_threadsafe" = "no"; then SQLITE_THREADSAFE=0 - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else SQLITE_THREADSAFE=1 - { $as_echo "$as_me:$LINENO: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi if test "$SQLITE_THREADSAFE" = "1"; then - { $as_echo "$as_me:$LINENO: checking for library containing pthread_create" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 $as_echo_n "checking for library containing pthread_create... " >&6; } -if test "${ac_cv_search_pthread_create+set}" = set; then +if ${ac_cv_search_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -12453,54 +10525,27 @@ for ac_lib in '' pthread; do ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pthread_create=$ac_res -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext - if test "${ac_cv_search_pthread_create+set}" = set; then +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_pthread_create+:} false; then : break fi done -if test "${ac_cv_search_pthread_create+set}" = set; then - : +if ${ac_cv_search_pthread_create+:} false; then : + else ac_cv_search_pthread_create=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_pthread_create" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5 $as_echo "$ac_cv_search_pthread_create" >&6; } ac_res=$ac_cv_search_pthread_create -if test "$ac_res" != no; then +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi @@ -12511,21 +10556,21 @@ fi # Do we want to support release # # Check whether --enable-releasemode was given. -if test "${enable_releasemode+set}" = set; then +if test "${enable_releasemode+set}" = set; then : enableval=$enable_releasemode; else enable_releasemode=no fi -{ $as_echo "$as_me:$LINENO: checking whether to support shared library linked as release mode or not" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support shared library linked as release mode or not" >&5 $as_echo_n "checking whether to support shared library linked as release mode or not... " >&6; } if test "$enable_releasemode" = "no"; then ALLOWRELEASE="" - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else ALLOWRELEASE="-release `cat $srcdir/VERSION`" - { $as_echo "$as_me:$LINENO: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi @@ -12534,38 +10579,38 @@ fi # Do we want temporary databases in memory # # Check whether --enable-tempstore was given. -if test "${enable_tempstore+set}" = set; then +if test "${enable_tempstore+set}" = set; then : enableval=$enable_tempstore; else enable_tempstore=no fi -{ $as_echo "$as_me:$LINENO: checking whether to use an in-ram database for temporary tables" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use an in-ram database for temporary tables" >&5 $as_echo_n "checking whether to use an in-ram database for temporary tables... " >&6; } case "$enable_tempstore" in never ) TEMP_STORE=0 - { $as_echo "$as_me:$LINENO: result: never" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: never" >&5 $as_echo "never" >&6; } ;; no ) TEMP_STORE=1 - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; yes ) TEMP_STORE=2 - { $as_echo "$as_me:$LINENO: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ;; always ) TEMP_STORE=3 - { $as_echo "$as_me:$LINENO: result: always" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: always" >&5 $as_echo "always" >&6; } ;; * ) TEMP_STORE=1 - { $as_echo "$as_me:$LINENO: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac @@ -12577,53 +10622,17 @@ esac # the CYGWIN environment. So check for that special case and handle # things accordingly. # -{ $as_echo "$as_me:$LINENO: checking if executables have the .exe suffix" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if executables have the .exe suffix" >&5 $as_echo_n "checking if executables have the .exe suffix... " >&6; } if test "$config_BUILD_EXEEXT" = ".exe"; then CYGWIN=yes - { $as_echo "$as_me:$LINENO: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else - { $as_echo "$as_me:$LINENO: result: unknown" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 $as_echo "unknown" >&6; } fi if test "$CYGWIN" != "yes"; then - { $as_echo "$as_me:$LINENO: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if test "${ac_cv_host+set}" = set; then - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 -$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} - { (exit 1); exit 1; }; } -fi - -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 -$as_echo "$as_me: error: invalid value of canonical host" >&2;} - { (exit 1); exit 1; }; };; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - case $host_os in *cygwin* ) CYGWIN=yes;; @@ -12665,7 +10674,7 @@ fi # minor changes to accomodate systems that do not have TCL installed. # # Check whether --enable-tcl was given. -if test "${enable_tcl+set}" = set; then +if test "${enable_tcl+set}" = set; then : enableval=$enable_tcl; use_tcl=$enableval else use_tcl=yes @@ -12674,13 +10683,13 @@ fi if test "${use_tcl}" = "yes" ; then # Check whether --with-tcl was given. -if test "${with_tcl+set}" = set; then +if test "${with_tcl+set}" = set; then : withval=$with_tcl; with_tclconfig=${withval} fi - { $as_echo "$as_me:$LINENO: checking for Tcl configuration" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 $as_echo_n "checking for Tcl configuration... " >&6; } - if test "${ac_cv_c_tclconfig+set}" = set; then + if ${ac_cv_c_tclconfig+:} false; then : $as_echo_n "(cached) " >&6 else @@ -12689,9 +10698,7 @@ else if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)` else - { { $as_echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 -$as_echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 fi fi @@ -12766,25 +10773,25 @@ fi if test x"${ac_cv_c_tclconfig}" = x ; then use_tcl=no - { $as_echo "$as_me:$LINENO: WARNING: Can't find Tcl configuration definitions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find Tcl configuration definitions" >&5 $as_echo "$as_me: WARNING: Can't find Tcl configuration definitions" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&5 $as_echo "$as_me: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&5 $as_echo "$as_me: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&2;} else TCL_BIN_DIR=${ac_cv_c_tclconfig} - { $as_echo "$as_me:$LINENO: result: found $TCL_BIN_DIR/tclConfig.sh" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $TCL_BIN_DIR/tclConfig.sh" >&5 $as_echo "found $TCL_BIN_DIR/tclConfig.sh" >&6; } - { $as_echo "$as_me:$LINENO: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5 $as_echo_n "checking for existence of $TCL_BIN_DIR/tclConfig.sh... " >&6; } if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then - { $as_echo "$as_me:$LINENO: result: loading" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 $as_echo "loading" >&6; } . $TCL_BIN_DIR/tclConfig.sh else - { $as_echo "$as_me:$LINENO: result: file not found" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: file not found" >&5 $as_echo "file not found" >&6; } fi @@ -12827,6 +10834,7 @@ $as_echo "file not found" >&6; } + fi fi if test "${use_tcl}" = "no" ; then @@ -12844,7 +10852,7 @@ TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 # Check whether --enable-readline was given. -if test "${enable_readline+set}" = set; then +if test "${enable_readline+set}" = set; then : enableval=$enable_readline; with_readline=$enableval else with_readline=auto @@ -12856,7 +10864,7 @@ if test x"$with_readline" != xno; then # Check whether --with-readline-lib was given. -if test "${with_readline_lib+set}" = set; then +if test "${with_readline_lib+set}" = set; then : withval=$with_readline_lib; with_readline_lib=$withval else with_readline_lib="auto" @@ -12865,17 +10873,13 @@ fi if test "x$with_readline_lib" = xauto; then save_LIBS="$LIBS" LIBS="" - { $as_echo "$as_me:$LINENO: checking for library containing tgetent" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tgetent" >&5 $as_echo_n "checking for library containing tgetent... " >&6; } -if test "${ac_cv_search_tgetent+set}" = set; then +if ${ac_cv_search_tgetent+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -12900,72 +10904,41 @@ for ac_lib in '' readline ncurses curses termcap; do ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_tgetent=$ac_res -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext - if test "${ac_cv_search_tgetent+set}" = set; then +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_tgetent+:} false; then : break fi done -if test "${ac_cv_search_tgetent+set}" = set; then - : +if ${ac_cv_search_tgetent+:} false; then : + else ac_cv_search_tgetent=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_tgetent" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_tgetent" >&5 $as_echo "$ac_cv_search_tgetent" >&6; } ac_res=$ac_cv_search_tgetent -if test "$ac_res" != no; then +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" term_LIBS="$LIBS" else term_LIBS="" fi - { $as_echo "$as_me:$LINENO: checking for readline in -lreadline" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } -if test "${ac_cv_lib_readline_readline+set}" = set; then +if ${ac_cv_lib_readline_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -12983,43 +10956,18 @@ return readline (); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_readline=yes else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_readline_readline=no + ac_cv_lib_readline_readline=no fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 $as_echo "$ac_cv_lib_readline_readline" >&6; } -if test $ac_cv_lib_readline_readline = yes; then +if test "x$ac_cv_lib_readline_readline" = xyes; then : TARGET_READLINE_LIBS="-lreadline" else found="no" @@ -13033,141 +10981,15 @@ fi # Check whether --with-readline-inc was given. -if test "${with_readline_inc+set}" = set; then +if test "${with_readline_inc+set}" = set; then : withval=$with_readline_inc; with_readline_inc=$withval else with_readline_inc="auto" fi if test "x$with_readline_inc" = xauto; then - if test "${ac_cv_header_readline_h+set}" = set; then - { $as_echo "$as_me:$LINENO: checking for readline.h" >&5 -$as_echo_n "checking for readline.h... " >&6; } -if test "${ac_cv_header_readline_h+set}" = set; then - $as_echo_n "(cached) " >&6 -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_readline_h" >&5 -$as_echo "$ac_cv_header_readline_h" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:$LINENO: checking readline.h usability" >&5 -$as_echo_n "checking readline.h usability... " >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_header_compiler=yes -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:$LINENO: checking readline.h presence" >&5 -$as_echo_n "checking readline.h presence... " >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { $as_echo "$as_me:$LINENO: WARNING: readline.h: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: readline.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: readline.h: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: readline.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { $as_echo "$as_me:$LINENO: WARNING: readline.h: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: readline.h: present but cannot be compiled" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: readline.h: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: readline.h: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: readline.h: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: readline.h: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: readline.h: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: readline.h: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: readline.h: proceeding with the preprocessor's result" >&5 -$as_echo "$as_me: WARNING: readline.h: proceeding with the preprocessor's result" >&2;} - { $as_echo "$as_me:$LINENO: WARNING: readline.h: in the future, the compiler will take precedence" >&5 -$as_echo "$as_me: WARNING: readline.h: in the future, the compiler will take precedence" >&2;} - - ;; -esac -{ $as_echo "$as_me:$LINENO: checking for readline.h" >&5 -$as_echo_n "checking for readline.h... " >&6; } -if test "${ac_cv_header_readline_h+set}" = set; then - $as_echo_n "(cached) " >&6 -else - ac_cv_header_readline_h=$ac_header_preproc -fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_readline_h" >&5 -$as_echo "$ac_cv_header_readline_h" >&6; } - -fi -if test $ac_cv_header_readline_h = yes; then + ac_fn_c_check_header_mongrel "$LINENO" "readline.h" "ac_cv_header_readline_h" "$ac_includes_default" +if test "x$ac_cv_header_readline_h" = xyes; then : found="yes" else @@ -13176,27 +10998,23 @@ else for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do for subdir in include include/readline; do as_ac_File=`$as_echo "ac_cv_file_$dir/$subdir/readline.h" | $as_tr_sh` -{ $as_echo "$as_me:$LINENO: checking for $dir/$subdir/readline.h" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $dir/$subdir/readline.h" >&5 $as_echo_n "checking for $dir/$subdir/readline.h... " >&6; } -if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then +if eval \${$as_ac_File+:} false; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && - { { $as_echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5 -$as_echo "$as_me: error: cannot check for file existence when cross compiling" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "$dir/$subdir/readline.h"; then eval "$as_ac_File=yes" else eval "$as_ac_File=no" fi fi -ac_res=`eval 'as_val=${'$as_ac_File'} - $as_echo "$as_val"'` - { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test `eval 'as_val=${'$as_ac_File'} - $as_echo "$as_val"'` = yes; then +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : found=yes fi @@ -13233,17 +11051,13 @@ fi # Figure out what C libraries are required to compile programs # that use "fdatasync()" function. # -{ $as_echo "$as_me:$LINENO: checking for library containing fdatasync" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5 $as_echo_n "checking for library containing fdatasync... " >&6; } -if test "${ac_cv_search_fdatasync+set}" = set; then +if ${ac_cv_search_fdatasync+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -13268,54 +11082,27 @@ for ac_lib in '' rt; do ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_fdatasync=$ac_res -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext - if test "${ac_cv_search_fdatasync+set}" = set; then +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_fdatasync+:} false; then : break fi done -if test "${ac_cv_search_fdatasync+set}" = set; then - : +if ${ac_cv_search_fdatasync+:} false; then : + else ac_cv_search_fdatasync=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_fdatasync" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fdatasync" >&5 $as_echo "$ac_cv_search_fdatasync" >&6; } ac_res=$ac_cv_search_fdatasync -if test "$ac_res" != no; then +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi @@ -13324,7 +11111,7 @@ fi ######### # check for debug enabled # Check whether --enable-debug was given. -if test "${enable_debug+set}" = set; then +if test "${enable_debug+set}" = set; then : enableval=$enable_debug; use_debug=$enableval else use_debug=no @@ -13340,7 +11127,7 @@ fi ######### # See whether we should use the amalgamation to build # Check whether --enable-amalgamation was given. -if test "${enable_amalgamation+set}" = set; then +if test "${enable_amalgamation+set}" = set; then : enableval=$enable_amalgamation; use_amalgamation=$enableval else use_amalgamation=yes @@ -13354,7 +11141,7 @@ fi ######### # See whether we should allow loadable extensions # Check whether --enable-load-extension was given. -if test "${enable_load_extension+set}" = set; then +if test "${enable_load_extension+set}" = set; then : enableval=$enable_load_extension; use_loadextension=$enableval else use_loadextension=yes @@ -13362,17 +11149,13 @@ fi if test "${use_loadextension}" = "yes" ; then OPT_FEATURE_FLAGS="" - { $as_echo "$as_me:$LINENO: checking for library containing dlopen" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } -if test "${ac_cv_search_dlopen+set}" = set; then +if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. @@ -13397,54 +11180,27 @@ for ac_lib in '' dl; do ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi - rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then + if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext - if test "${ac_cv_search_dlopen+set}" = set; then +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : break fi done -if test "${ac_cv_search_dlopen+set}" = set; then - : +if ${ac_cv_search_dlopen+:} false; then : + else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_dlopen" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen -if test "$ac_res" != no; then +if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi @@ -13507,7 +11263,7 @@ BUILD_CFLAGS=$ac_temp_BUILD_CFLAGS ######### # See whether we should use GCOV # Check whether --enable-gcov was given. -if test "${enable_gcov+set}" = set; then +if test "${enable_gcov+set}" = set; then : enableval=$enable_gcov; use_gcov=$enableval else use_gcov=no @@ -13559,13 +11315,13 @@ _ACEOF case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -$as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) $as_unset $ac_var ;; + *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done @@ -13573,8 +11329,8 @@ $as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" @@ -13596,12 +11352,23 @@ $as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && - { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5 + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else - { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi @@ -13615,14 +11382,15 @@ DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= +U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. - ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs @@ -13630,13 +11398,14 @@ LTLIBOBJS=$ac_ltlibobjs -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. @@ -13646,17 +11415,18 @@ cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 debug=false ac_cs_recheck=false ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which @@ -13664,23 +11434,15 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; esac - fi - - -# PATH needs CR -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - as_nl=' ' export as_nl @@ -13688,7 +11450,13 @@ export as_nl as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else @@ -13699,7 +11467,7 @@ else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; - case $arg in + case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; @@ -13722,13 +11490,6 @@ if test "${PATH_SEPARATOR+set}" != set; then } fi -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - # IFS # We need space, tab and new line, in precisely that order. Quoting is @@ -13738,15 +11499,16 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. -case $0 in +as_myself= +case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done IFS=$as_save_IFS ;; @@ -13758,12 +11520,16 @@ if test "x$as_myself" = x; then fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - { (exit 1); exit 1; } + exit 1 fi -# Work around bugs in pre-3.0 UWIN ksh. -for as_var in ENV MAIL MAILPATH -do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' @@ -13775,7 +11541,89 @@ export LC_ALL LANGUAGE=C export LANGUAGE -# Required to use basename. +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr @@ -13789,8 +11637,12 @@ else as_basename=false fi +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi -# Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ @@ -13810,76 +11662,25 @@ $as_echo X/"$0" | } s/.*/./; q'` -# CDPATH. -$as_unset CDPATH - - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line after each line using $LINENO; the second 'sed' - # does the real work. The second script uses 'N' to pair each - # line-number line with the line containing $LINENO, and appends - # trailing '-' during substitution so that $LINENO is not a special - # case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # scripts with optimization help from Paolo Bonzini. Blame Lee - # E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in +case `echo -n x` in #((((( -n*) - case `echo 'x\c'` in + case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. - *) ECHO_C='\c';; + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then @@ -13894,49 +11695,85 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then - as_mkdir_p=: + as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -13946,13 +11783,19 @@ as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 -# Save the log message, to keep $[0] and so on meaningful, and to +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.8.8.3, which was -generated by GNU Autoconf 2.62. Invocation command line was +This file was extended by sqlite $as_me 3.8.10.2, which was +generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -13965,6 +11808,15 @@ on `(hostname || uname -n) 2>/dev/null | sed 1q` _ACEOF +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" @@ -13975,19 +11827,22 @@ _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. -Usage: $0 [OPTIONS] [FILE]... +Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit - -q, --quiet do not print progress messages + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] + --file=FILE[:TEMPLATE] instantiate the configuration file FILE - --header=FILE[:TEMPLATE] + --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: @@ -13999,16 +11854,17 @@ $config_headers Configuration commands: $config_commands -Report bugs to ." +Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sqlite config.status 3.8.8.3 -configured by $0, generated by GNU Autoconf 2.62, - with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" +sqlite config.status 3.8.10.2 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" -Copyright (C) 2008 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -14025,11 +11881,16 @@ ac_need_defaults=: while test $# != 0 do case $1 in - --*=*) + --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; *) ac_option=$1 ac_optarg=$2 @@ -14043,27 +11904,29 @@ do ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; esac - CONFIG_FILES="$CONFIG_FILES '$ac_optarg'" + as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac - CONFIG_HEADERS="$CONFIG_HEADERS '$ac_optarg'" + as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header - { $as_echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; };; + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ @@ -14071,11 +11934,10 @@ Try \`$0 --help' for more information." >&2 ac_cs_silent=: ;; # This is an error. - -*) { $as_echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } ;; + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; - *) ac_config_targets="$ac_config_targets $1" + *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac @@ -14092,7 +11954,7 @@ fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' @@ -14385,9 +12247,7 @@ do "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "sqlite3.pc") CONFIG_FILES="$CONFIG_FILES sqlite3.pc" ;; - *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -14410,26 +12270,24 @@ fi # after its creation but before its name has been assigned to `$tmp'. $debug || { - tmp= + tmp= ac_tmp= trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 + trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || -{ - $as_echo "$as_me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -14437,7 +12295,13 @@ $debug || if test -n "$CONFIG_FILES"; then -ac_cr=' ' +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' @@ -14445,7 +12309,7 @@ else ac_cs_awk_cr=$ac_cr fi -echo 'BEGIN {' >"$tmp/subs1.awk" && +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF @@ -14454,23 +12318,18 @@ _ACEOF echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || - { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 -$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} - { (exit 1); exit 1; }; } -ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || - { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 -$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` = $ac_delim_num; then + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then - { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 -$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -14478,7 +12337,7 @@ done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h @@ -14492,7 +12351,7 @@ s/'"$ac_delim"'$// t delim :nl h -s/\(.\{148\}\).*/\1/ +s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p @@ -14506,7 +12365,7 @@ s/.\{148\}// t nl :delim h -s/\(.\{148\}\).*/\1/ +s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p @@ -14526,7 +12385,7 @@ t delim rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" @@ -14558,23 +12417,29 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5 -$as_echo "$as_me: error: could not setup config files machinery" >&2;} - { (exit 1); exit 1; }; } +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// s/^[^=]*=[ ]*$// }' fi @@ -14586,7 +12451,7 @@ fi # test -n "$CONFIG_FILES" # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then -cat >"$tmp/defines.awk" <<\_ACAWK || +cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF @@ -14598,13 +12463,11 @@ _ACEOF # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do - ac_t=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_t"; then + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then break elif $ac_last_try; then - { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_HEADERS" >&5 -$as_echo "$as_me: error: could not make $CONFIG_HEADERS" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -14670,9 +12533,9 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 } split(mac1, mac2, "(") #) macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". - prefix = substr(line, 1, index(line, defundef) - 1) print prefix "define", macro P[macro] D[macro] next } else { @@ -14680,7 +12543,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { - print "/*", line, "*/" + print "/*", prefix defundef, macro, "*/" next } } @@ -14689,9 +12552,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - { { $as_echo "$as_me:$LINENO: error: could not setup config headers machinery" >&5 -$as_echo "$as_me: error: could not setup config headers machinery" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" @@ -14704,9 +12565,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 -$as_echo "$as_me: error: Invalid tag $ac_tag." >&2;} - { (exit 1); exit 1; }; };; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -14725,7 +12584,7 @@ $as_echo "$as_me: error: Invalid tag $ac_tag." >&2;} for ac_f do case $ac_f in - -) ac_f="$tmp/stdin";; + -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. @@ -14734,12 +12593,10 @@ $as_echo "$as_me: error: Invalid tag $ac_tag." >&2;} [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 -$as_echo "$as_me: error: cannot find input file: $ac_f" >&2;} - { (exit 1); exit 1; }; };; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - ac_file_inputs="$ac_file_inputs '$ac_f'" + as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't @@ -14750,7 +12607,7 @@ $as_echo "$as_me: error: cannot find input file: $ac_f" >&2;} `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:$LINENO: creating $ac_file" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. @@ -14762,10 +12619,8 @@ $as_echo "$as_me: creating $ac_file" >&6;} esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 -$as_echo "$as_me: error: could not create $ac_file" >&2;} - { (exit 1); exit 1; }; } ;; + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -14793,47 +12648,7 @@ $as_echo X"$ac_file" | q } s/.*/./; q'` - { as_dir="$ac_dir" - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 -$as_echo "$as_me: error: cannot create directory $as_dir" >&2;} - { (exit 1); exit 1; }; }; } + as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in @@ -14885,7 +12700,6 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= - ac_sed_dataroot=' /datarootdir/ { p @@ -14895,12 +12709,11 @@ ac_sed_dataroot=' /@docdir@/p /@infodir@/p /@localedir@/p -/@mandir@/p -' +/@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 @@ -14910,7 +12723,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; + s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF @@ -14937,27 +12750,24 @@ s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 -$as_echo "$as_me: error: could not create $ac_file" >&2;} - { (exit 1); exit 1; }; } +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} +which seems to be undefined. Please make sure it is defined" >&2;} - rm -f "$tmp/stdin" + rm -f "$ac_tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ - || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 -$as_echo "$as_me: error: could not create $ac_file" >&2;} - { (exit 1); exit 1; }; } + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # @@ -14966,31 +12776,25 @@ $as_echo "$as_me: error: could not create $ac_file" >&2;} if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" - } >"$tmp/config.h" \ - || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 -$as_echo "$as_me: error: could not create $ac_file" >&2;} - { (exit 1); exit 1; }; } - if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then - { $as_echo "$as_me:$LINENO: $ac_file is unchanged" >&5 + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" - mv "$tmp/config.h" "$ac_file" \ - || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 -$as_echo "$as_me: error: could not create $ac_file" >&2;} - { (exit 1); exit 1; }; } + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ - || { { $as_echo "$as_me:$LINENO: error: could not create -" >&5 -$as_echo "$as_me: error: could not create -" >&2;} - { (exit 1); exit 1; }; } + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; - :C) { $as_echo "$as_me:$LINENO: executing $ac_file commands" >&5 + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac @@ -15637,15 +13441,12 @@ _LT_EOF done # for ac_tag -{ (exit 0); exit 0; } +as_fn_exit 0 _ACEOF -chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || - { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. @@ -15666,10 +13467,10 @@ if test "$no_create" != yes; then exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } + $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:$LINENO: WARNING: Unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: Unrecognized options: $ac_unrecognized_opts" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi diff --git a/configure.ac b/configure.ac index 00ecf45..6a11888 100644 --- a/configure.ac +++ b/configure.ac @@ -430,6 +430,7 @@ if test "${use_tcl}" = "yes" ; then AC_SUBST(TCL_STUB_LIB_FILE) AC_SUBST(TCL_STUB_LIB_FLAG) AC_SUBST(TCL_STUB_LIB_SPEC) + AC_SUBST(TCL_SHLIB_SUFFIX) fi fi if test "${use_tcl}" = "no" ; then diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index ec9f0d3..e7958d9 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -313,6 +313,13 @@ static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **); +#ifndef SQLITE_AMALGAMATION +# if defined(SQLITE_DEBUG) +int sqlite3Fts3Always(int b) { assert( b ); return b; } +int sqlite3Fts3Never(int b) { assert( !b ); return b; } +# endif +#endif + /* ** Write a 64-bit variable-length integer to memory starting at p[0]. ** The length of data written will be between 1 and FTS3_VARINT_MAX bytes. @@ -422,7 +429,7 @@ void sqlite3Fts3Dequote(char *z){ /* If the first byte was a '[', then the close-quote character is a ']' */ if( quote=='[' ) quote = ']'; - while( ALWAYS(z[iIn]) ){ + while( z[iIn] ){ if( z[iIn]==quote ){ if( z[iIn+1]!=quote ) break; z[iOut++] = quote; @@ -501,6 +508,17 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ return SQLITE_OK; } +/* +** Write an error message into *pzErr +*/ +void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){ + va_list ap; + sqlite3_free(*pzErr); + va_start(ap, zFormat); + *pzErr = sqlite3_vmprintf(zFormat, ap); + va_end(ap); +} + /* ** Construct one or more SQL statements from the format string given ** and then evaluate those statements. The success code is written @@ -910,11 +928,16 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){ ** This function is used when parsing the "prefix=" FTS4 parameter. */ static int fts3GobbleInt(const char **pp, int *pnOut){ + const int MAX_NPREFIX = 10000000; const char *p; /* Iterator pointer */ int nInt = 0; /* Output value */ for(p=*pp; p[0]>='0' && p[0]<='9'; p++){ nInt = nInt * 10 + (p[0] - '0'); + if( nInt>MAX_NPREFIX ){ + nInt = 0; + break; + } } if( p==*pp ) return SQLITE_ERROR; *pnOut = nInt; @@ -957,7 +980,6 @@ static int fts3PrefixParameter( aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex); *apIndex = aIndex; - *pnIndex = nIndex; if( !aIndex ){ return SQLITE_NOMEM; } @@ -967,13 +989,20 @@ static int fts3PrefixParameter( const char *p = zParam; int i; for(i=1; i=0 ); + if( nPrefix==0 ){ + nIndex--; + i--; + }else{ + aIndex[i].nPrefix = nPrefix; + } p++; } } + *pnIndex = nIndex; return SQLITE_OK; } @@ -1008,7 +1037,8 @@ static int fts3ContentColumns( const char *zTbl, /* Name of content table */ const char ***pazCol, /* OUT: Malloc'd array of column names */ int *pnCol, /* OUT: Size of array *pazCol */ - int *pnStr /* OUT: Bytes of string content */ + int *pnStr, /* OUT: Bytes of string content */ + char **pzErr /* OUT: error message */ ){ int rc = SQLITE_OK; /* Return code */ char *zSql; /* "SELECT *" statement on zTbl */ @@ -1019,6 +1049,9 @@ static int fts3ContentColumns( rc = SQLITE_NOMEM; }else{ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db)); + } } sqlite3_free(zSql); @@ -1097,7 +1130,7 @@ static int fts3InitVtab( const char **aCol; /* Array of column names */ sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */ - int nIndex; /* Size of aIndex[] array */ + int nIndex = 0; /* Size of aIndex[] array */ struct Fts3Index *aIndex = 0; /* Array of indexes for this table */ /* The results of parsing supported FTS4 key=value options: */ @@ -1185,13 +1218,13 @@ static int fts3InitVtab( } } if( iOpt==SizeofArray(aFts4Opt) ){ - *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z); + sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z); rc = SQLITE_ERROR; }else{ switch( iOpt ){ case 0: /* MATCHINFO */ if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){ - *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal); + sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal); rc = SQLITE_ERROR; } bNoDocsize = 1; @@ -1219,7 +1252,7 @@ static int fts3InitVtab( if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3)) && (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4)) ){ - *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal); + sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal); rc = SQLITE_ERROR; } bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); @@ -1270,7 +1303,7 @@ static int fts3InitVtab( if( nCol==0 ){ sqlite3_free((void*)aCol); aCol = 0; - rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); + rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); /* If a languageid= option was specified, remove the language id ** column from the aCol[] array. */ @@ -1305,7 +1338,7 @@ static int fts3InitVtab( rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex); if( rc==SQLITE_ERROR ){ assert( zPrefix ); - *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix); + sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix); } if( rc!=SQLITE_OK ) goto fts3_init_out; @@ -1387,7 +1420,7 @@ static int fts3InitVtab( } for(i=0; izReadExprlist = fts3ReadExprList(p, zUncompress, &rc); p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc); @@ -2491,26 +2524,33 @@ static int fts3DoclistOrMerge( ** ** The right-hand input doclist is overwritten by this function. */ -static void fts3DoclistPhraseMerge( +static int fts3DoclistPhraseMerge( int bDescDoclist, /* True if arguments are desc */ int nDist, /* Distance from left to right (1=adjacent) */ char *aLeft, int nLeft, /* Left doclist */ - char *aRight, int *pnRight /* IN/OUT: Right/output doclist */ + char **paRight, int *pnRight /* IN/OUT: Right/output doclist */ ){ sqlite3_int64 i1 = 0; sqlite3_int64 i2 = 0; sqlite3_int64 iPrev = 0; + char *aRight = *paRight; char *pEnd1 = &aLeft[nLeft]; char *pEnd2 = &aRight[*pnRight]; char *p1 = aLeft; char *p2 = aRight; char *p; int bFirstOut = 0; - char *aOut = aRight; + char *aOut; assert( nDist>0 ); - + if( bDescDoclist ){ + aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX); + if( aOut==0 ) return SQLITE_NOMEM; + }else{ + aOut = aRight; + } p = aOut; + fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1); fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2); @@ -2539,6 +2579,12 @@ static void fts3DoclistPhraseMerge( } *pnRight = (int)(p - aOut); + if( bDescDoclist ){ + sqlite3_free(aRight); + *paRight = aOut; + } + + return SQLITE_OK; } /* @@ -2663,8 +2709,22 @@ static int fts3TermSelectMerge( ){ if( pTS->aaOutput[0]==0 ){ /* If this is the first term selected, copy the doclist to the output - ** buffer using memcpy(). */ - pTS->aaOutput[0] = sqlite3_malloc(nDoclist); + ** buffer using memcpy(). + ** + ** Add FTS3_VARINT_MAX bytes of unused space to the end of the + ** allocation. This is so as to ensure that the buffer is big enough + ** to hold the current doclist AND'd with any other doclist. If the + ** doclists are stored in order=ASC order, this padding would not be + ** required (since the size of [doclistA AND doclistB] is always less + ** than or equal to the size of [doclistA] in that case). But this is + ** not true for order=DESC. For example, a doclist containing (1, -1) + ** may be smaller than (-1), as in the first example the -1 may be stored + ** as a single-byte delta, whereas in the second it must be stored as a + ** FTS3_VARINT_MAX byte varint. + ** + ** Similar padding is added in the fts3DoclistOrMerge() function. + */ + pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); pTS->anOutput[0] = nDoclist; if( pTS->aaOutput[0] ){ memcpy(pTS->aaOutput[0], aDoclist, nDoclist); @@ -2761,7 +2821,7 @@ static int fts3SegReaderCursor( ** calls out here. */ if( iLevel<0 && p->aIndex ){ Fts3SegReader *pSeg = 0; - rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg); + rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg); if( rc==SQLITE_OK && pSeg ){ rc = fts3SegReaderCursorAppend(pCsr, pSeg); } @@ -3164,10 +3224,17 @@ static int fts3FilterMethod( ** row by docid. */ if( eSearch==FTS3_FULLSCAN_SEARCH ){ - zSql = sqlite3_mprintf( - "SELECT %s ORDER BY rowid %s", - p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") - ); + if( pDocidGe || pDocidLe ){ + zSql = sqlite3_mprintf( + "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s", + p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid, + (pCsr->bDesc ? "DESC" : "ASC") + ); + }else{ + zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s", + p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC") + ); + } if( zSql ){ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0); sqlite3_free(zSql); @@ -3403,11 +3470,31 @@ static void fts3ReversePoslist(char *pStart, char **ppPoslist){ char *p = &(*ppPoslist)[-2]; char c = 0; + /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */ while( p>pStart && (c=*p--)==0 ); + + /* Search backwards for a varint with value zero (the end of the previous + ** poslist). This is an 0x00 byte preceded by some byte that does not + ** have the 0x80 bit set. */ while( p>pStart && (*p & 0x80) | c ){ c = *p--; } - if( p>pStart ){ p = &p[2]; } + assert( p==pStart || c==0 ); + + /* At this point p points to that preceding byte without the 0x80 bit + ** set. So to find the start of the poslist, skip forward 2 bytes then + ** over a varint. + ** + ** Normally. The other case is that p==pStart and the poslist to return + ** is the first in the doclist. In this case do not skip forward 2 bytes. + ** The second part of the if condition (c==0 && *ppPoslist>&p[2]) + ** is required for cases where the first byte of a doclist and the + ** doclist is empty. For example, if the first docid is 10, a doclist + ** that begins with: + ** + ** 0x0A 0x00 + */ + if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; } while( *p++&0x80 ); *ppPoslist = p; } @@ -3478,6 +3565,8 @@ static void fts3SnippetFunc( } if( !zEllipsis || !zEnd || !zStart ){ sqlite3_result_error_nomem(pContext); + }else if( nToken==0 ){ + sqlite3_result_text(pContext, "", -1, SQLITE_STATIC); }else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){ sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken); } @@ -3913,14 +4002,17 @@ static void fts3EvalAllocateReaders( ** This function assumes that pList points to a buffer allocated using ** sqlite3_malloc(). This function takes responsibility for eventually ** freeing the buffer. +** +** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs. */ -static void fts3EvalPhraseMergeToken( +static int fts3EvalPhraseMergeToken( Fts3Table *pTab, /* FTS Table pointer */ Fts3Phrase *p, /* Phrase to merge pList/nList into */ int iToken, /* Token pList/nList corresponds to */ char *pList, /* Pointer to doclist */ int nList /* Number of bytes in pList */ ){ + int rc = SQLITE_OK; assert( iToken!=p->iDoclistToken ); if( pList==0 ){ @@ -3959,13 +4051,16 @@ static void fts3EvalPhraseMergeToken( nDiff = p->iDoclistToken - iToken; } - fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight); + rc = fts3DoclistPhraseMerge( + pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight + ); sqlite3_free(pLeft); p->doclist.aAll = pRight; p->doclist.nAll = nRight; } if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken; + return rc; } /* @@ -3991,7 +4086,7 @@ static int fts3EvalPhraseLoad( char *pThis = 0; rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis); if( rc==SQLITE_OK ){ - fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); + rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis); } } assert( pToken->pSegcsr==0 ); @@ -4533,12 +4628,14 @@ static void fts3EvalStartReaders( ){ if( pExpr && SQLITE_OK==*pRc ){ if( pExpr->eType==FTSQUERY_PHRASE ){ - int i; int nToken = pExpr->pPhrase->nToken; - for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; + if( nToken ){ + int i; + for(i=0; ipPhrase->aToken[i].pDeferred==0 ) break; + } + pExpr->bDeferred = (i==nToken); } - pExpr->bDeferred = (i==nToken); *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase); }else{ fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc); @@ -4793,9 +4890,13 @@ static int fts3EvalSelectDeferred( char *pList = 0; rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList); assert( rc==SQLITE_OK || pList==0 ); + if( rc==SQLITE_OK ){ + rc = fts3EvalPhraseMergeToken( + pTab, pTC->pPhrase, pTC->iToken,pList,nList + ); + } if( rc==SQLITE_OK ){ int nCount; - fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList); nCount = fts3DoclistCountDocids( pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll ); @@ -5656,7 +5757,6 @@ int sqlite3Fts3EvalPhrasePoslist( if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ int rc = SQLITE_OK; int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ - int iMul; /* +1 if csr dir matches index dir, else -1 */ int bOr = 0; u8 bEof = 0; u8 bTreeEof = 0; @@ -5698,7 +5798,8 @@ int sqlite3Fts3EvalPhrasePoslist( pIter = pPhrase->pOrPoslist; iDocid = pPhrase->iOrDocid; if( pCsr->bDesc==bDescDoclist ){ - bEof = (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll)); + bEof = !pPhrase->doclist.nAll || + (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll)); while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ sqlite3Fts3DoclistNext( bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index 1b8b7bd..0748d91 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -134,6 +134,11 @@ SQLITE_EXTENSION_INIT3 #ifdef SQLITE_COVERAGE_TEST # define ALWAYS(x) (1) # define NEVER(X) (0) +#elif defined(SQLITE_DEBUG) +# define ALWAYS(x) sqlite3Fts3Always((x)!=0) +# define NEVER(x) sqlite3Fts3Never((x)!=0) +int sqlite3Fts3Always(int b); +int sqlite3Fts3Never(int b); #else # define ALWAYS(x) (x) # define NEVER(x) (x) @@ -534,6 +539,7 @@ int sqlite3Fts3Incrmerge(Fts3Table*,int,int); ) /* fts3.c */ +void sqlite3Fts3ErrMsg(char**,const char*,...); int sqlite3Fts3PutVarint(char *, sqlite3_int64); int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); int sqlite3Fts3GetVarint32(const char *, int *); diff --git a/ext/fts3/fts3_aux.c b/ext/fts3/fts3_aux.c index c68b1a9..f85a48a 100644 --- a/ext/fts3/fts3_aux.c +++ b/ext/fts3/fts3_aux.c @@ -116,7 +116,7 @@ static int fts3auxConnectMethod( return SQLITE_OK; bad_args: - *pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor"); + sqlite3Fts3ErrMsg(pzErr, "invalid arguments to fts4aux constructor"); return SQLITE_ERROR; } diff --git a/ext/fts3/fts3_expr.c b/ext/fts3/fts3_expr.c index 2ba786c..d7cabd9 100644 --- a/ext/fts3/fts3_expr.c +++ b/ext/fts3/fts3_expr.c @@ -1022,13 +1022,13 @@ int sqlite3Fts3ExprParse( sqlite3Fts3ExprFree(*ppExpr); *ppExpr = 0; if( rc==SQLITE_TOOBIG ){ - *pzErr = sqlite3_mprintf( + sqlite3Fts3ErrMsg(pzErr, "FTS expression tree is too large (maximum depth %d)", SQLITE_FTS3_MAX_EXPR_DEPTH ); rc = SQLITE_ERROR; }else if( rc==SQLITE_ERROR ){ - *pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z); + sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z); } } diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c index 93ee86f..6abb169 100644 --- a/ext/fts3/fts3_snippet.c +++ b/ext/fts3/fts3_snippet.c @@ -27,6 +27,7 @@ #define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */ #define FTS3_MATCHINFO_LCS 's' /* nCol values */ #define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ +#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */ /* ** The default value for the second argument to matchinfo(). @@ -682,8 +683,12 @@ static int fts3SnippetText( ** required. They are required if (a) this is not the first fragment, ** or (b) this fragment does not begin at position 0 of its column. */ - if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){ - rc = fts3StringAppend(pOut, zEllipsis, -1); + if( rc==SQLITE_OK ){ + if( iPos>0 || iFragment>0 ){ + rc = fts3StringAppend(pOut, zEllipsis, -1); + }else if( iBegin ){ + rc = fts3StringAppend(pOut, zDoc, iBegin); + } } if( rc!=SQLITE_OK || iCurrentpCursor->base.pVtab; + int rc = SQLITE_OK; + int iStart = iPhrase * p->nCol; + Fts3Expr *pEof; /* Ancestor node already at EOF */ + + /* This must be a phrase */ + assert( pExpr->pPhrase ); + + /* Initialize all output integers to zero. */ + memset(&p->aMatchinfo[iStart], 0, sizeof(u32) * p->nCol); + + /* Check if this or any parent node is at EOF. If so, then all output + ** values are zero. */ + for(pEof=pExpr; pEof && pEof->bEof==0; pEof=pEof->pParent); + + if( pEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){ + Fts3Phrase *pPhrase = pExpr->pPhrase; + char *pIter = pPhrase->doclist.pList; + int iCol = 0; + + while( 1 ){ + int nHit = fts3ColumnlistCount(&pIter); + if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){ + p->aMatchinfo[iStart + iCol] = (u32)nHit; + } + assert( *pIter==0x00 || *pIter==0x01 ); + if( *pIter!=0x01 ) break; + pIter++; + pIter += fts3GetVarint32(pIter, &iCol); + } + } + + return rc; +} + static int fts3MatchinfoCheck( Fts3Table *pTab, char cArg, @@ -817,10 +867,11 @@ static int fts3MatchinfoCheck( || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) || (cArg==FTS3_MATCHINFO_LCS) || (cArg==FTS3_MATCHINFO_HITS) + || (cArg==FTS3_MATCHINFO_LHITS) ){ return SQLITE_OK; } - *pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg); + sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg); return SQLITE_ERROR; } @@ -840,6 +891,10 @@ static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ nVal = pInfo->nCol; break; + case FTS3_MATCHINFO_LHITS: + nVal = pInfo->nCol * pInfo->nPhrase; + break; + default: assert( cArg==FTS3_MATCHINFO_HITS ); nVal = pInfo->nCol * pInfo->nPhrase * 3; @@ -1094,6 +1149,10 @@ static int fts3MatchinfoValues( } break; + case FTS3_MATCHINFO_LHITS: + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLHitsCb, (void*)pInfo); + break; + default: { Fts3Expr *pExpr; assert( zArg[i]==FTS3_MATCHINFO_HITS ); @@ -1249,7 +1308,7 @@ void sqlite3Fts3Snippet( */ for(iRead=0; iReadnColumn; iRead++){ SnippetFragment sF = {0, 0, 0, 0}; - int iS; + int iS = 0; if( iCol>=0 && iRead!=iCol ) continue; /* Find the best snippet of nFToken tokens in column iRead. */ diff --git a/ext/fts3/fts3_term.c b/ext/fts3/fts3_term.c index c49d5cb..7edd072 100644 --- a/ext/fts3/fts3_term.c +++ b/ext/fts3/fts3_term.c @@ -81,7 +81,7 @@ static int fts3termConnectMethod( /* The user should specify a single argument - the name of an fts3 table. */ if( argc!=4 ){ - *pzErr = sqlite3_mprintf( + sqlite3Fts3ErrMsg(pzErr, "wrong number of arguments to fts4term constructor" ); return SQLITE_ERROR; diff --git a/ext/fts3/fts3_tokenize_vtab.c b/ext/fts3/fts3_tokenize_vtab.c index fb99f8b..dfeddfe 100644 --- a/ext/fts3/fts3_tokenize_vtab.c +++ b/ext/fts3/fts3_tokenize_vtab.c @@ -85,7 +85,7 @@ static int fts3tokQueryTokenizer( p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); if( !p ){ - *pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName); + sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName); return SQLITE_ERROR; } diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c index 04f8446..64cfe07 100644 --- a/ext/fts3/fts3_tokenizer.c +++ b/ext/fts3/fts3_tokenizer.c @@ -69,7 +69,7 @@ static void scalarFunc( if( argc==2 ){ void *pOld; int n = sqlite3_value_bytes(argv[1]); - if( n!=sizeof(pPtr) ){ + if( zName==0 || n!=sizeof(pPtr) ){ sqlite3_result_error(context, "argument type mismatch", -1); return; } @@ -80,7 +80,9 @@ static void scalarFunc( return; } }else{ - pPtr = sqlite3Fts3HashFind(pHash, zName, nName); + if( zName ){ + pPtr = sqlite3Fts3HashFind(pHash, zName, nName); + } if( !pPtr ){ char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); sqlite3_result_error(context, zErr, -1); @@ -161,12 +163,16 @@ int sqlite3Fts3InitTokenizer( zEnd = &zCopy[strlen(zCopy)]; z = (char *)sqlite3Fts3NextToken(zCopy, &n); + if( z==0 ){ + assert( n==0 ); + z = zCopy; + } z[n] = '\0'; sqlite3Fts3Dequote(z); m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1); if( !m ){ - *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z); + sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z); rc = SQLITE_ERROR; }else{ char const **aArg = 0; @@ -189,7 +195,7 @@ int sqlite3Fts3InitTokenizer( rc = m->xCreate(iArg, aArg, ppTok); assert( rc!=SQLITE_OK || *ppTok ); if( rc!=SQLITE_OK ){ - *pzErr = sqlite3_mprintf("unknown tokenizer"); + sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer"); }else{ (*ppTok)->pModule = m; } @@ -273,9 +279,9 @@ static void testFunc( p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); if( !p ){ - char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); + char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName); + sqlite3_result_error(context, zErr2, -1); + sqlite3_free(zErr2); return; } diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 09294bc..4cd2aeb 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -326,7 +326,7 @@ static int fts3SqlStmt( /* 25 */ "", /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", -/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", +/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'", /* This statement is used to determine which level to read the input from ** when performing an incremental merge. It returns the absolute level number @@ -1625,7 +1625,10 @@ int sqlite3Fts3SegReaderNew( ** an array of pending terms by term. This occurs as part of flushing ** the contents of the pending-terms hash table to the database. */ -static int fts3CompareElemByTerm(const void *lhs, const void *rhs){ +static int SQLITE_CDECL fts3CompareElemByTerm( + const void *lhs, + const void *rhs +){ char *z1 = fts3HashKey(*(Fts3HashElem **)lhs); char *z2 = fts3HashKey(*(Fts3HashElem **)rhs); int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs); @@ -3441,7 +3444,8 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ int rc2; - sqlite3_bind_int(pAllLangid, 1, p->nIndex); + sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); + sqlite3_bind_int(pAllLangid, 2, p->nIndex); while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ int i; int iLangid = sqlite3_column_int(pAllLangid, 0); @@ -4773,7 +4777,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ pHint->n = i; i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); i += fts3GetVarint32(&pHint->a[i], pnInput); - if( i!=nHint ) return SQLITE_CORRUPT_VTAB; + if( i!=nHint ) return FTS_CORRUPT_VTAB; return SQLITE_OK; } @@ -5141,7 +5145,8 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ int rc2; - sqlite3_bind_int(pAllLangid, 1, p->nIndex); + sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid); + sqlite3_bind_int(pAllLangid, 2, p->nIndex); while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ int iLangid = sqlite3_column_int(pAllLangid, 0); int i; @@ -5154,7 +5159,6 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ } /* This block calculates the checksum according to the %_content table */ - rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); if( rc==SQLITE_OK ){ sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; sqlite3_stmt *pStmt = 0; @@ -5251,7 +5255,7 @@ static int fts3DoIntegrityCheck( int rc; int bOk = 0; rc = fts3IntegrityCheck(p, &bOk); - if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB; + if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; return rc; } diff --git a/ext/fts3/tool/fts3view.c b/ext/fts3/tool/fts3view.c index 3dc1ba8..6dada35 100644 --- a/ext/fts3/tool/fts3view.c +++ b/ext/fts3/tool/fts3view.c @@ -504,7 +504,7 @@ static void showSegdirMap(sqlite3 *db, const char *zTab){ sqlite3_column_int64(pStmt,5)); printf(" root %9s\n", rtag); if( iLEnd>iStart ){ - sqlite3_int64 iLower, iPrev, iX; + sqlite3_int64 iLower, iPrev = 0, iX; if( iLEnd+1<=iEnd ){ sqlite3_bind_int64(pStmt2, 1, iLEnd+1); sqlite3_bind_int64(pStmt2, 2, iEnd); @@ -548,7 +548,7 @@ static void decodeSegment( const unsigned char *aData, /* Content to print */ int nData /* Number of bytes of content */ ){ - sqlite3_int64 iChild; + sqlite3_int64 iChild = 0; sqlite3_int64 iPrefix; sqlite3_int64 nTerm; sqlite3_int64 n; diff --git a/ext/misc/amatch.c b/ext/misc/amatch.c index 98c0143..d08ef57 100644 --- a/ext/misc/amatch.c +++ b/ext/misc/amatch.c @@ -998,6 +998,23 @@ static void amatchWriteCost(amatch_word *pWord){ pWord->zCost[8] = 0; } +/* Circumvent compiler warnings about the use of strcpy() by supplying +** our own implementation. +*/ +#if defined(__OpenBSD__) +static void amatchStrcpy(char *dest, const char *src){ + while( (*(dest++) = *(src++))!=0 ){} +} +static void amatchStrcat(char *dest, const char *src){ + while( *dest ) dest++; + amatchStrcpy(dest, src); +} +#else +# define amatchStrcpy strcpy +# define amatchStrcat strcat +#endif + + /* ** Add a new amatch_word object to the queue. ** @@ -1073,7 +1090,7 @@ static void amatchAddWord( assert( pOther==0 ); (void)pOther; pWord->sWord.zKey = pWord->zWord; pWord->sWord.pWord = pWord; - strcpy(pWord->zWord, pCur->zBuf); + amatchStrcpy(pWord->zWord, pCur->zBuf); pOther = amatchAvlInsert(&pCur->pWord, &pWord->sWord); assert( pOther==0 ); (void)pOther; #ifdef AMATCH_TRACE_1 @@ -1083,6 +1100,7 @@ static void amatchAddWord( #endif } + /* ** Advance a cursor to its next row of output */ @@ -1148,7 +1166,7 @@ static int amatchNext(sqlite3_vtab_cursor *cur){ zBuf = sqlite3_realloc(zBuf, nBuf); if( zBuf==0 ) return SQLITE_NOMEM; } - strcpy(zBuf, pWord->zWord+2); + amatchStrcpy(zBuf, pWord->zWord+2); zNext[0] = 0; zNextIn[0] = pCur->zInput[pWord->nMatch]; if( zNextIn[0] ){ @@ -1163,7 +1181,7 @@ static int amatchNext(sqlite3_vtab_cursor *cur){ if( zNextIn[0] && zNextIn[0]!='*' ){ sqlite3_reset(p->pVCheck); - strcat(zBuf, zNextIn); + amatchStrcat(zBuf, zNextIn); sqlite3_bind_text(p->pVCheck, 1, zBuf, nWord+nNextIn, SQLITE_STATIC); rc = sqlite3_step(p->pVCheck); if( rc==SQLITE_ROW ){ @@ -1176,13 +1194,13 @@ static int amatchNext(sqlite3_vtab_cursor *cur){ } while( 1 ){ - strcpy(zBuf+nWord, zNext); + amatchStrcpy(zBuf+nWord, zNext); sqlite3_reset(p->pVCheck); sqlite3_bind_text(p->pVCheck, 1, zBuf, -1, SQLITE_TRANSIENT); rc = sqlite3_step(p->pVCheck); if( rc!=SQLITE_ROW ) break; zW = (const char*)sqlite3_column_text(p->pVCheck, 0); - strcpy(zBuf+nWord, zNext); + amatchStrcpy(zBuf+nWord, zNext); if( strncmp(zW, zBuf, nWord)!=0 ) break; if( (zNextIn[0]=='*' && zNextIn[1]==0) || (zNextIn[0]==0 && zW[nWord]==0) diff --git a/ext/misc/compress.c b/ext/misc/compress.c index a405911..bf38d4c 100644 --- a/ext/misc/compress.c +++ b/ext/misc/compress.c @@ -38,6 +38,7 @@ static void compressFunc( unsigned int nIn; unsigned long int nOut; unsigned char x[8]; + int rc; int i, j; pIn = sqlite3_value_blob(argv[0]); @@ -50,8 +51,12 @@ static void compressFunc( for(i=0; i<4 && x[i]==0; i++){} for(j=0; i<=4; i++, j++) pOut[j] = x[i]; pOut[j-1] |= 0x80; - compress(&pOut[j], &nOut, pIn, nIn); - sqlite3_result_blob(context, pOut, nOut+j, sqlite3_free); + rc = compress(&pOut[j], &nOut, pIn, nIn); + if( rc==Z_OK ){ + sqlite3_result_blob(context, pOut, nOut+j, sqlite3_free); + }else{ + sqlite3_free(pOut); + } } /* @@ -82,6 +87,8 @@ static void uncompressFunc( rc = uncompress(pOut, &nOut, &pIn[i], nIn-i); if( rc==Z_OK ){ sqlite3_result_blob(context, pOut, nOut, sqlite3_free); + }else{ + sqlite3_free(pOut); } } diff --git a/ext/misc/fuzzer.c b/ext/misc/fuzzer.c index dc03161..3ed4b0a 100644 --- a/ext/misc/fuzzer.c +++ b/ext/misc/fuzzer.c @@ -876,7 +876,7 @@ static fuzzer_stem *fuzzerNewStem( if( pNew==0 ) return 0; memset(pNew, 0, sizeof(*pNew)); pNew->zBasis = (char*)&pNew[1]; - pNew->nBasis = (int)strlen(zWord); + pNew->nBasis = (fuzzer_len)strlen(zWord); memcpy(pNew->zBasis, zWord, pNew->nBasis+1); pRule = pCur->pVtab->pRule; while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){ diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 201d3cf..5e63c18 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -2820,11 +2820,19 @@ static int rtreeUpdate( if( nData>1 ){ int ii; - /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */ - assert( nData==(pRtree->nDim*2 + 3) ); + /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. + ** + ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared + ** with "column" that are interpreted as table constraints. + ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5)); + ** This problem was discovered after years of use, so we silently ignore + ** these kinds of misdeclared tables to avoid breaking any legacy. + */ + assert( nData<=(pRtree->nDim*2 + 3) ); + #ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ + for(ii=0; iicell.aCoord[ii+1].f ){ @@ -2835,7 +2843,7 @@ static int rtreeUpdate( }else #endif { - for(ii=0; ii<(pRtree->nDim*2); ii+=2){ + for(ii=0; iicell.aCoord[ii+1].i ){ diff --git a/ext/rtree/rtree9.test b/ext/rtree/rtree9.test index 6479516..571341b 100644 --- a/ext/rtree/rtree9.test +++ b/ext/rtree/rtree9.test @@ -87,7 +87,6 @@ do_catchsql_test rtree9-4.3 { # register_circle_geom db -breakpoint do_execsql_test rtree9-5.1 { CREATE VIRTUAL TABLE rt2 USING rtree(id, xmin, xmax, ymin, ymax); diff --git a/main.mk b/main.mk index 429945b..7ac6868 100644 --- a/main.mk +++ b/main.mk @@ -53,7 +53,7 @@ TCCX += -I$(TOP)/ext/async -I$(TOP)/ext/userauth LIBOBJ+= vdbe.o parse.o \ alter.o analyze.o attach.o auth.o \ backup.o bitvec.o btmutex.o btree.o build.o \ - callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \ + callback.o complete.o ctime.o date.o dbstat.o delete.o expr.o fault.o fkey.o \ fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \ fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \ fts3_tokenize_vtab.o \ @@ -91,6 +91,7 @@ SRC = \ $(TOP)/src/complete.c \ $(TOP)/src/ctime.c \ $(TOP)/src/date.c \ + $(TOP)/src/dbstat.c \ $(TOP)/src/delete.c \ $(TOP)/src/expr.c \ $(TOP)/src/fault.c \ @@ -133,6 +134,7 @@ SRC = \ $(TOP)/src/pcache.h \ $(TOP)/src/pcache1.c \ $(TOP)/src/pragma.c \ + $(TOP)/src/pragma.h \ $(TOP)/src/prepare.c \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ @@ -164,6 +166,7 @@ SRC = \ $(TOP)/src/vdbetrace.c \ $(TOP)/src/vdbeInt.h \ $(TOP)/src/vtab.c \ + $(TOP)/src/vxworks.h \ $(TOP)/src/wal.c \ $(TOP)/src/wal.h \ $(TOP)/src/walker.c \ @@ -268,7 +271,6 @@ TESTSRC = \ $(TOP)/src/test_rtree.c \ $(TOP)/src/test_schema.c \ $(TOP)/src/test_server.c \ - $(TOP)/src/test_stat.c \ $(TOP)/src/test_sqllog.c \ $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ @@ -304,6 +306,7 @@ TESTSRC2 = \ $(TOP)/src/btree.c \ $(TOP)/src/build.c \ $(TOP)/src/date.c \ + $(TOP)/src/dbstat.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ @@ -356,12 +359,14 @@ HDR = \ $(TOP)/src/pager.h \ $(TOP)/src/pcache.h \ parse.h \ + $(TOP)/src/pragma.h \ sqlite3.h \ $(TOP)/src/sqlite3ext.h \ $(TOP)/src/sqliteInt.h \ $(TOP)/src/sqliteLimit.h \ $(TOP)/src/vdbe.h \ $(TOP)/src/vdbeInt.h \ + $(TOP)/src/vxworks.h \ $(TOP)/src/whereInt.h # Header files used by extensions @@ -400,10 +405,31 @@ sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h $(TOP)/src/shell.c \ libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) +sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h + $(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \ + $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB) + +fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h + $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\ + $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) $(THREADLIB) + mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c $(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \ $(TLIBS) $(THREADLIB) +MPTEST1=./mptester$(EXE) mptest.db $(TOP)/mptest/crash01.test --repeat 20 +MPTEST2=./mptester$(EXE) mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20 +mptest: mptester$(EXE) + rm -f mptest.db + $(MPTEST1) --journalmode DELETE + $(MPTEST2) --journalmode WAL + $(MPTEST1) --journalmode WAL + $(MPTEST2) --journalmode PERSIST + $(MPTEST1) --journalmode PERSIST + $(MPTEST2) --journalmode TRUNCATE + $(MPTEST1) --journalmode TRUNCATE + $(MPTEST2) --journalmode DELETE + sqlite3.o: sqlite3.c $(TCCX) -I. -c sqlite3.c @@ -576,9 +602,10 @@ tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a $(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \ $(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB) -sqlite3_analyzer.c: sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl +sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl echo "#define TCLSH 2" > $@ - cat sqlite3.c $(TOP)/src/test_stat.c $(TOP)/src/tclsqlite.c >> $@ + echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@ + cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@ echo "static const char *tclsh_main_loop(void){" >> $@ echo "static const char *zMainloop = " >> $@ $(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@ @@ -608,21 +635,34 @@ fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \ -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) -fulltest: testfixture$(EXE) sqlite3$(EXE) +fulltest: testfixture$(EXE) sqlite3$(EXE) fuzztest ./testfixture$(EXE) $(TOP)/test/all.test -soaktest: testfixture$(EXE) sqlite3$(EXE) +soaktest: testfixture$(EXE) sqlite3$(EXE) fuzzoomtest ./testfixture$(EXE) $(TOP)/test/all.test -soak=1 -fulltestonly: testfixture$(EXE) sqlite3$(EXE) +fulltestonly: testfixture$(EXE) sqlite3$(EXE) fuzztest ./testfixture$(EXE) $(TOP)/test/full.test queryplantest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner -test: testfixture$(EXE) sqlite3$(EXE) +fuzztest: fuzzershell$(EXE) + ./fuzzershell$(EXE) $(TOP)/test/fuzzdata1.txt $(TOP)/test/fuzzdata2.txt + +fuzzoomtest: fuzzershell$(EXE) + ./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt --oom + +test: testfixture$(EXE) sqlite3$(EXE) fuzztest ./testfixture$(EXE) $(TOP)/test/veryquick.test +# Run a test using valgrind. This can take a really long time +# because valgrind is so much slower than a native machine. +# +valgrindtest: testfixture$(EXE) sqlite3$(EXE) fuzzershell$(EXE) + valgrind -v ./fuzzershell$(EXE) -f $(TOP)/test/fuzzdata1.txt + OMIT_MISUSE=1 valgrind -v ./testfixture$(EXE) $(TOP)/test/permutations.test valgrind + # The next two rules are used to support the "threadtest" target. Building # threadtest runs a few thread-safety tests that are implemented in C. This # target is invoked by the releasetest.tcl script. diff --git a/manifest b/manifest index 828d587..ec3af6b 100644 --- a/manifest +++ b/manifest @@ -1,19 +1,19 @@ -C Version\s3.8.8.3 -D 2015-02-25T13:29:11.692 +C Version\s3.8.10.2 +D 2015-05-20T18:17:19.154 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610 +F Makefile.in 08728ecbeddca339c77bfd564d3484b523dffdb1 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc 4c057774e6138b9023fc16ec05639ddd3329b152 +F Makefile.msc c6241f7fa2912427410ef15429c8ab5601e19a71 F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866 -F VERSION 0de46a30a2d0a7a6a686fd35186fbad0ac06ff71 +F VERSION 527b4c5a3d1a29e3b16162473d0903b569c6d7cb F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 -F autoconf/Makefile.am 8fc2972d92769cf20ab8e4a73ea901b84d69bf44 +F autoconf/Makefile.am 4012e106208c7b86ba54d06e9ed400b59a4dee6b F autoconf/README 14458f1046c118efa721aadec5f227e876d3cd38 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/config.guess 94cc57e2a3fdb9c235b362ace86d77e89d188cad x @@ -38,8 +38,8 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 42b71ad3fe21c9e88fa59e8458ca1a6bc72eb0c0 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure 444b4cd66ec94631b2b624cf24d01142c9aac0ae x -F configure.ac 6a8d145aea6d81f0b90013340780e43ed74fd5f4 +F configure 17b518102f77344a1709422da84afebb57f0fcfe x +F configure.ac 0b775d383c536bbaafc1e46dd3cbb81a7ea11aeb F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 @@ -78,40 +78,40 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c 845f20440dacac6e09f5c7735205609b9a86536b +F ext/fts3/fts3.c 2fb98467f4b670c8934cdd97d1ba3ffa7382764c F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe -F ext/fts3/fts3Int.h 394858c12a17740f7a1f6bd372c4606d4425a8d1 -F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365 -F ext/fts3/fts3_expr.c 40123785eaa3ebd4c45c9b23407cc44ac0c49905 +F ext/fts3/fts3Int.h 59ecaa2d7af0da44c70b6aeaebdcfc070d14abab +F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 +F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60 F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5 F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009 -F ext/fts3/fts3_snippet.c 55c126e07158b2a705f52dee2cdc57208d3e999a -F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763 +F ext/fts3/fts3_snippet.c 40a96ba78e90aba7d7d6d014a18049bb218060fd +F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7 F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038 -F ext/fts3/fts3_tokenize_vtab.c becc661223db7898b213f9e8a23d75bac02408c9 -F ext/fts3/fts3_tokenizer.c bbdc731bc91338050675c6d1da9ab82147391e16 +F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860 +F ext/fts3/fts3_tokenizer.c 50e7a69a549ac5882cc1971ee43f66aaabc11395 F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145 F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057 -F ext/fts3/fts3_write.c 9b3a32cbecf40a1f41cb08c00df8c066c23c7a25 +F ext/fts3/fts3_write.c 4f005f78592a1447ca96c8475ef5342ab7dbe02a F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9 F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100 -F ext/fts3/tool/fts3view.c 3986531f2fc0ceca0c89c31ec7d0589b6adb19d6 +F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7 F ext/fts3/unicode/mkunicode.tcl a2567f9d6ad6779879a2e394c120ad8718557e65 F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 F ext/icu/icu.c d415ccf984defeb9df2c0e1afcfaa2f6dc05eacb F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 -F ext/misc/amatch.c 17ba78dc9b33601a40d2a7bc54c748b6f3eb7176 +F ext/misc/amatch.c 27b9b601fb1453084e18a3432ea0240d7af8decb F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012 -F ext/misc/compress.c 76e45655f4046e756064ab10c62e18f2eb846b9f +F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83 F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f -F ext/misc/fuzzer.c e3e18f47252c151b5553d7e806f38e757d37c4cc +F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767 F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 @@ -124,7 +124,7 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 14e6239434d4e3f65d3e90320713f26aa24e167f +F ext/rtree/rtree.c 0c207fd8b814a35537d96681cbf57436e200b75e F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e F ext/rtree/rtree1.test 541bbcab74613907fea08b2ecdcdd5b7aa724cc9 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba @@ -134,7 +134,7 @@ F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196 F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971 F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a -F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34 +F ext/rtree/rtree9.test b5eb13849545dfd271a54ff16784cb00d8792aea F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06 @@ -152,192 +152,195 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk e392561ffe17fc4dad945eef852400d5bf2911a0 +F main.mk f012feb95fc4acfb583f89b6f9d1dc6253a8f08d F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea -F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5 +F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 -F mptest/crash01.test cce8e306d8596d5a2e497e27112dae1f6e5e3538 +F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421 F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8 -F mptest/mptest.c 24c5f72415df2eab7088ef8c9f99f163aed590c8 -F mptest/multiwrite01.test 499ad0310da8dff8e8f98d2e272fc2a8aa741b2e +F mptest/mptest.c fca59f0a922e03f95ed17c44b1515ed37a841c81 +F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb -F src/analyze.c 91540f835163d5369ccbae78e2e6c74d0dd53c1d -F src/attach.c 7f6b3fafa2290b407e4a94dcf1afda7ec0fe394b +F src/alter.c 8f6dc4a6ddc1ebc0ed5cc470c4e57ff0d1605e90 +F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b +F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 -F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea -F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb -F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5 -F src/btree.c 4c098bb6e8678e4596983862abf78f7a0fcb807e -F src/btree.h 94277c1d30c0b75705974bcc8b0c05e79c03d474 -F src/btreeInt.h a3d0ae1d511365e1a2b76ad10960dbe55c286f34 -F src/build.c f5cfd7b32216f695b995bbc7c1a395f6d451d11f +F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3 +F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d +F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 +F src/btree.c 30a80340481098d699398cba3536c895373b2e2c +F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 +F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4 +F src/build.c 61b47073f79f31e80a05db9ce13c5ca81bf8f74e F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 -F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463 -F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887 +F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575 +F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac -F src/delete.c bd1a91ddd247ce13004075251e0b7fe2bf9925ef -F src/expr.c 7be80f7dc337329a24df45c2f3bdb2ea3b64c90e +F src/dbstat.c db36fbd268f778ea1cdb8b0c1eb9828c1f10bf70 +F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e +F src/expr.c 3fb2ab3ab69d15b4b75ae53fceb4e317f64cb306 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12 -F src/func.c 6d3c4ebd72aa7923ce9b110a7dc15f9b8c548430 -F src/global.c 12561d70a1b25f67b21154622bb1723426724f75 +F src/fkey.c c9b63a217d86582c22121699a47f22f524608869 +F src/func.c 5b8b8e77a0fb644eaf8947d413804622e32692b6 +F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c 5b9243a33726008cc4132897d2be371db12a13be +F src/insert.c 8176ba5bad8fcef643558ca5708f33ed05a4035a F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770 -F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660 -F src/main.c 341fcc5601a8ca84389fa32bcf5a857f65af8dd0 -F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab +F src/loadext.c 29255bbe1cfb2ce9bbff2526a5ecfddcb49b9271 +F src/main.c 331fda6b255ae6a08e6ade89f0ac1d158691f3c6 +F src/malloc.c 6a370b83d54e4bbf6f94021221c2a311cff26a18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987 F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534 F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85 -F src/msvc.h e78002098966e39b2fd9915bd70b7bc3ec8398b7 +F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495 F src/mutex.c 19bf9acba69ca2f367c3761080f8a9f0cf4670a8 F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 -F src/mutex_noop.c f3f09fd7a2eb4287cfc799753ffc30380e7b71a1 -F src/mutex_unix.c 551e2f25f0fa0ee8fd7a43f50fc3d8be00e95dde -F src/mutex_w32.c df48fe07562a45c5c927c45b8d5873a27f98bbb0 +F src/mutex_noop.c 529bab0743c3321c940f32c3464de494fd38cfa9 +F src/mutex_unix.c 5cf676464bd19e0a866297515d146e8bf1669dfb +F src/mutex_w32.c 61660ada28d8308ad190f444c2170c4f2a590c2f F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7 F src/os.c 8fd25588eeba74068d41102d26810e216999b6c8 F src/os.h 3e57a24e2794a94d3cf2342c6d9a884888cd96bf -F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04 +F src/os_common.h abdb9a191a367793268fe553d25bab894e986a0e F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa -F src/os_unix.c aefeaf915aaef9f81aa2645e0d5d06fa1bd83beb -F src/os_win.c 91d3d08e33ec0258d180d4c8255492f47d15e007 -F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21 -F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c +F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc +F src/os_win.c 2da99cf07da7db6bcb1974013abfd89ec74749b3 +F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca +F src/pager.c 97110085b1321298412f1e5c37bddb95b36d9208 F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77 -F src/parse.y c5d0d964f9ac023e8154cad512e54b0b6058e086 -F src/pcache.c d210cf90d04365a74f85d21374dded65af67b0cb +F src/parse.y c4e0387bc88c8e21e5ba653e2578959a1f3cdbc7 +F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4 F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8 -F src/pcache1.c 1e77432b40b7d3288327d9cdf399dcdfd2b6d3bf -F src/pragma.c ba149bbbc90783f84815636c509ced8eac11bbcf -F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9 -F src/printf.c ea82bcb1b83273b4c67177c233c1f78c81fc42f9 +F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9 +F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7 +F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f +F src/prepare.c 1fffbdcd6f8a0173a8f70d71f22528f4c0e1e3d3 +F src/printf.c 54dd6dce95454fadffa3ebf7717c5f6c06250d1d F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 -F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada +F src/resolve.c 99eabf7eff0bfa65b75939b46caa82e2b2133f28 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c a4e8fda24c8eab2682a058bdda0d5d68cfe3919c -F src/shell.c ee1a80bf2b0e9e0c2b93db8f0f82b841289b2641 -F src/sqlite.h.in 9dfc99d6533d36d6a549c4f3f01cacc8be956ada +F src/select.c 1b0bfc7d59e48c26b895a6b719157111a617d9e3 +F src/shell.c 07dda7cd692911d2f22269953418d049f2e2c0ee +F src/sqlite.h.in ca27603a36fcacdaac5a19d8ee35aaff8ce8516f F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d -F src/sqliteInt.h eaf210295b551d4e40e622aec1b2261c0b28f844 -F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d -F src/status.c 81712116e826b0089bb221b018929536b2b5406f -F src/table.c e7a09215315a978057fb42c640f890160dbcc45e -F src/tclsqlite.c 0bbb44543175ef2033d39780a233f98bf354eff9 -F src/test1.c 093d8b5b54b829dcfebae3181d4406edcc935d90 +F src/sqliteInt.h 20d9c59fd82774503b8953acfbcc6ecbdd9ee6aa +F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 +F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 +F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e +F src/tclsqlite.c d4fa052d3fbb655150d4ca8eedc70384b98bfef3 +F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585 F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d -F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c -F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df +F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622 +F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1 F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723 -F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2 -F src/test8.c df8dd4c99c1dd2225cb2a6f334299cddc5dcf1f1 +F src/test7.c 9c89a4f1ed6bb13af0ed805b8d782bd83fcd57e3 +F src/test8.c 610e3d523018ca63b08081795e76794a2121ec38 F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60 F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8 F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12 -F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e -F src/test_blob.c 1f2e3e25255b731c4fcf15ee7990d06347cb6c09 +F src/test_backup.c 2e6e6a081870150f20c526a2e9d0d29cda47d803 +F src/test_blob.c e5a7a81d61a780da79101aeb1e60d300af169e07 F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f -F src/test_config.c e7b2e1634324d746aa5e1c7e0929470e8be27953 -F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9 +F src/test_config.c c2d3ff6c129d50183900c7eff14158ff7e9b3f03 +F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f -F src/test_func.c 14e543ae4d905ee31dc322b2f8d31bfac1769d45 +F src/test_func.c f1ac201465472e76a73e2f3695c3553c63e7322a F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32 -F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834 +F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5 F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202 F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4 -F src/test_malloc.c b9495384e74923aefde8311de974bf9b0f5ba570 -F src/test_multiplex.c 72c0ad1e97af3d6d19975bbd81813072b40c7290 +F src/test_malloc.c 208f09a4e21defa496bc1094fcfadea19385a112 +F src/test_multiplex.c 9fefd23f6cc3fa9bf0748a5e453167e7b9f193ce F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3 F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f -F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25 -F src/test_osinst.c 3d0340bc31a9f3d8a3547e0272373e80f78dde25 +F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10 +F src/test_osinst.c 5423dc1d355f594371f27dd292ca54bd320b8196 F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_quota.c 180813f43683be5725458fc1ff13ac455d8e722d F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d -F src/test_rtree.c fdd8d29ca5165c7857987a2ba263fac5c69e231f +F src/test_rtree.c bfe6f4386517f70054311109f3528adffec34485 F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091 F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe -F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e -F src/test_stat.c 9898687a6c2beca733b0dd6fe19163d987826d31 -F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd +F src/test_sqllog.c b690c12933f50ff46491e0d56a251f84ae16e914 +F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9 F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa -F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb -F src/test_vfs.c 8ee7be45fe773a150b4015ef957da960179ee43a +F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9 +F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 -F src/threads.c 2fb3ea4d70d5acf68b539c2489b4adace61cc01b -F src/tokenize.c e00458c9938072b0ea711c850b8dcf4ddcb5fe18 -F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f +F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481 +F src/tokenize.c b15511a2396641792f386ceb440d1d922972a78e +F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c -F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e -F src/vacuum.c 9b30ec729337dd012ed88d4c292922c8ef9cf00c -F src/vdbe.c ddfc977981cd6324668aa6b114045eb1c677421a -F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 -F src/vdbeInt.h 9bb69ff2447c34b6ccc58b34ec35b615f86ead78 -F src/vdbeapi.c 4bc511a46b9839392ae0e90844a71dc96d9dbd71 -F src/vdbeaux.c f06d38c71d7f533348c09869d69fd1b647042a5b -F src/vdbeblob.c 4af4bfb71f6df7778397b4a0ebc1879793276778 -F src/vdbemem.c 31d8eabb0cd78bfeab4e5124c7363c3e9e54db9f -F src/vdbesort.c 6d64c5448b64851b99931ede980addc3af70d5e2 -F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 -F src/vtab.c c08ec66f45919eaa726bf88aa53eb08379d607f9 -F src/wal.c 39303f2c9db02a4e422cd8eb2c8760420c6a51fe +F src/util.c a6431c92803b975b7322724a7b433e538d243539 +F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 +F src/vdbe.c 163e045d58ec5ff5384020e48b12ea49950c2922 +F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d +F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0 +F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 +F src/vdbeaux.c 03591cca98ec50e1493043f0ff7abbece0b9c83d +F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 +F src/vdbemem.c 7bfbeef0978a2e1a05d979641fdbf7c189b7ddf4 +F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b +F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 +F src/vtab.c c535e80259ebe616467181a83a4263555b97c694 +F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb +F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 -F src/where.c 88509f19a64a36e1c22a1dbdac74ee1a62d99dc3 -F src/whereInt.h d3633e9b592103241b74b0ec76185f3e5b8b62e0 +F src/where.c 85fff9c40569ccb79c3177419b339e7d7df566cb +F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783 -F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2 +F test/alter.test 2facdddf08d0d48e75dc6cc312cd2b030f4835dd F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f -F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4 -F test/analyze3.test bf41f0f680dd1e0d44eed5e769531e93a5320275 +F test/analyze.test 3eb35a4af972f98422e5dc0586501b17d103d321 +F test/analyze3.test 0f0ee6135b293a0e5af471a8423b80b688469d71 F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213 F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82 -F test/analyze9.test 72795c8113604b5dcd47a1498a61d6d7fb5d041a +F test/analyze9.test 3dd9e203fad353ec8027b18a6d9a92af59f4e727 F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594 F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d +F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2 F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7 F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0 F test/atof1.test 08a61df9365c341f334a65f4348897312d8f3db7 -F test/attach.test 0d112b7713611fdf0340260192749737135fda5f +F test/attach.test 437107943f14d131cf5efc2ae5305a94d7cb1d58 F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27 F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c @@ -346,7 +349,7 @@ F test/auth.test 855233ef26eb3601b6886567ea4e326c72959360 F test/auth2.test 264c6af53cad9aba5218c68bbe18036e39007bfa F test/auth3.test 5cfa94ed90c6617c42b7ba4b133fd79678b251c7 F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7 -F test/autoindex1.test 6ff78b94f43a59616c06c11c55b12935173506d7 +F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea F test/autoindex2.test af7e595c6864cc6ef5fc38d5db579a3e34940cb8 F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972 F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf @@ -381,11 +384,12 @@ F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45 F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983 F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f +F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99 F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3 F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738 -F test/capi3.test f0718f4f90d0efdc980119bfbdf1d7f1541ee5ef +F test/capi3.test bf6f0308bbbba1e770dac13aa08e5c2ac61c7324 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 F test/capi3c.test fdc0d67a2cb8e8fc400d5b7735e330161ea057a2 F test/capi3d.test a82b6321c50a1cfc848e386fa2c851893606f68c @@ -395,14 +399,14 @@ F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763 F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815 F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4 F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 -F test/collate1.test 73b91005f264b7c403e2d63a6708d150679ac99a +F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846 F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621 -F test/collate3.test 79558a286362cb9ed603c6fa543f1cda7f563f0f +F test/collate3.test 89defc49983ddfbf0a0555aca8c0521a676f56a5 F test/collate4.test f04d5168685f2eef637ecfa2d4ddf8ec0d600177 F test/collate5.test 65d928034d30d2d263a80f6359f7549ee1598ec6 F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907 F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868 -F test/collate8.test df26649cfcbddf109c04122b340301616d3a88f6 +F test/collate8.test cd9b3d3f999b8520ffaa7cc1647061fc5bab1334 F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6 F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1 @@ -422,15 +426,16 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516 F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85 F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26 F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec -F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb +F test/corruptC.test 3fcc0f73d2cf2d69befe2d96332b942426a6aae2 F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040 F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804 F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067 F test/corruptI.test 221ad8b7f0a9ac6b80fc577e73b5ad8cdea31243 +F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91 F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318 -F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5 +F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 @@ -440,6 +445,7 @@ F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219 F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df F test/crash8.test 61442a9964ab6b124fc5254e4258b45747842e6f +F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8 F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c @@ -469,8 +475,8 @@ F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306 F test/e_expr.test 8f5fdd7261e2d746813b0c6a1c0e34824ad3c5ad F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707 F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459 -F test/e_insert.test 7b2fa9cd1456f83474d6c5d27db3abaeb8be2023 -F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589 +F test/e_insert.test 0e63edc037afe738bb81a626a676811ed7862c90 +F test/e_reindex.test 57d439f6c644befc8274ac93cf2f5449cf2736c1 F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6 F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763 F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f @@ -478,8 +484,8 @@ F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10 F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52 F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585 F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9 -F test/e_wal.test 0967f0b8f1dfda871dc7b9b5574198f1f4f7d69a -F test/e_walauto.test ca70cf75c07a6cb1874ced101dd426da76625649 +F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625 +F test/e_walauto.test 6544af03423abc61b53cfb976839385ddc2a0a70 F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608 F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664 F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea @@ -493,16 +499,16 @@ F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75 F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30 -F test/expr.test c4b9bf0cc60b26862475e19999fbd2609ca8259c +F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931 F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9 F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146 -F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b -F test/fkey2.test 1db212cda86b0d3ce72714001f7b6381c321341c +F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2 +F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d -F test/fkey5.test 488601fbda8350619b3029487e56830447056fd2 +F test/fkey5.test 56bcb5a6e8b725b17febc267fb041a6695e86853 F test/fkey6.test abb59f866c1b44926fd02d1fdd217d831fe04f48 F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13 F test/fkey8.test 8f08203458321e6c19a263829de4cfc936274ab0 @@ -545,7 +551,7 @@ F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654 F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0 -F test/fts3aa.test edd20ddbbc5b6015ab340abf2ca278ae11ec387d +F test/fts3aa.test 6c263a6f8845205ee02550981a94c2e8dc1e7058 F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63 F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49 @@ -560,7 +566,7 @@ F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8 F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18 F test/fts3ao.test 3e4e3d5e75c076520341d0bdf4eb17c00e8cbde2 -F test/fts3atoken.test fca30fd86db9241d571c637751e9a8a2f50f1451 +F test/fts3atoken.test e3a126365131a6db52efc20a9a6053cd44e5f289 F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9 F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221 F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba @@ -581,26 +587,27 @@ F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162 F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f F test/fts3expr4.test e1be1248566f43c252d4404d52914f1fc4bfa065 +F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49 F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660 -F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887 +F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499 F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6 -F test/fts3matchinfo.test 58544fa4d254000fa4e7f494b0a832f7ba61d45e +F test/fts3matchinfo.test 3e5f5ac2e0a8ba42eafd4c685f803ca48b4c3a83 F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905 -F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1 +F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2 F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce -F test/fts3query.test 4fefd43ff24993bc2c9b2778f2bec0cc7629e7ed +F test/fts3query.test c838b18f2b859e15fd31c64be3d79ef1556803ca F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0 F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e -F test/fts3snippet.test d524af6bcef4714e059ef559113dbdc924cd33d1 +F test/fts3snippet.test 63dbd687d5bf5191f1b8e6a0977aa9c1e28a7004 F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca -F test/fts3tok1.test c551043de056b0b1582a54e878991f57bad074bc +F test/fts3tok1.test 178c050199af8c05299b1ad572514ce1c54b7827 F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb -F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a -F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06 +F test/fts4check.test 9d9e818fd6cb29c0e007cd6d00447739d4fde430 +F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53 F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d @@ -620,45 +627,49 @@ F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74 F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 -F test/fuzz2.test b34fe575aa10292135421ff4bf315de4cde7824a +F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 +F test/fuzzdata1.txt 9fceb50868e0b798160e83742bd7e44e457176a0 +F test/fuzzdata2.txt ba9b4467d7ec46cc85d32c0d031540cd727ae6ad F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98 -F test/hexlit.test f9ecde8145bfc2341573473256c74ae37a200497 +F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67 F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 -F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e +F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 +F test/in.test b52fa96bcf6cebc5c8829c822315d0f87af9c6c2 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 F test/in5.test 1de657472fa9ac2924be25c2c959ac5ca1aae554 F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328 -F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600 +F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5 F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab F test/incrblob_err.test af1f12ba60d220c9752073ff2bda2ad59e88960d F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e +F test/incrcorrupt.test 9786cba68c5832f01887fde1c06b43c3904d86f6 F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32 -F test/incrvacuum2.test 379eeb8740b0ef60c372c439ad4cbea20b34bb9b +F test/incrvacuum2.test 676c41428765d58f1da7dbe659ef27726d3d30ac F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635 F test/index.test 4d990005a67a36984e4f1a5f1bdccea8d08da4ee F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6 -F test/index3.test 55a90cff99834305e8141df7afaef39674b57062 +F test/index3.test b6ec456cf3b81d9a32123fe7e449bde434db338b F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6 F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e -F test/index6.test c56852451b574ad5b2a1789e566e62e6ab244f42 -F test/index7.test 917cf1e1c7439bb155abbeabec511b28945e157b -F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec +F test/index6.test 3ae54e53c53f2adcacda269237d8e52bdb05a481 +F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c +F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371 -F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435 +F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208 F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30 -F test/insert4.test 4791662c50518bdd37d394cae9a7a8014e845bb3 +F test/insert4.test a20432f1c0fbbcff8f11d0e6ab4acb8c9db58023 F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6 F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2 F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4 @@ -680,32 +691,33 @@ F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b F test/journal1.test 69abc726c51b4a0409189f9a85191205297c0577 F test/journal2.test ae06f566c28552c313ded3fee79a6c69e6d049b1 F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307 -F test/jrnlmode.test 9ee3a78f53d52cca737db69293d15dc41c0cbd36 +F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 -F test/like.test e191e536d0fcd722a6b965e7cd1ee0bfd12a5991 +F test/like.test 4f2a71d36a536233727f71995fef900756705e56 F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da -F test/limit.test 3d7df19c35ac672a11f7de406cd3205d592babbb +F test/like3.test 7b0525a39e4f25c4fd113de7e2e28eb712dcdedf +F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e F test/loadext.test 648cb95f324d1775c54a55c12271b2d1156b633b F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7 -F test/lock.test 87af515b0c4cf928576d0f89946d67d7c265dfb4 +F test/lock.test b984ab9034e7389be0d863fe4e64cbbc4d2028f5 F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff F test/lock3.test f271375930711ae044080f4fe6d6eda930870d00 F test/lock4.test e175ae13865bc87680607563bafba21f31a26f12 F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38 F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5 F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431 -F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95 +F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035 F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2 F test/main.test 16131264ea0c2b93b95201f0c92958e85f2ba11a F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9 -F test/malloc.test 96939d2d1a6f39667bbebe5bc27c6525f2ab614e +F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8 F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a F test/malloc4.test 957337613002b7058a85116493a262f679f3a261 -F test/malloc5.test fafce0aa9157060445cd1a56ad50fc79d82f28c3 +F test/malloc5.test 79182b8bffd6d62f77b1a5a8ba8e6bf0e5053b8e F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151 F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d @@ -721,7 +733,7 @@ F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6 F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e -F test/mallocK.test 3cff7c0f64735f6883bacdd294e45a6ed5714817 +F test/mallocK.test da01dcdd316767b8356741f8d33a23a06a23def5 F test/mallocL.test 252ddc7eb4fbf75364eab17b938816085ff1fc17 F test/malloc_common.tcl 3663f9001ce3e29bbaa9677ffe15cd468e3ec7e3 F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e @@ -734,15 +746,16 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f -F test/misc1.test 1201a037c24f982cc0e956cdaa34fcaf6439c417 +F test/misc1.test 783ba75743b2cf71e0f646bf540a6cef57264811 F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6 -F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5 +F test/misc5.test f96428ea95b3820aafc6f1c50cf48a09e4597ee1 F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2 F test/misc8.test fc2754d38892f7dac30c22db3616c2764f117d66 F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912 +F test/mkfuzzdata1.tcl 5f9c33fadc64b078bb4a2c04c18b6dd3da075bec F test/mmap1.test 1bfd611b9841eafb44f7d83c0788e146d84a33c9 F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022 F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e @@ -750,7 +763,7 @@ F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3 F test/multiplex.test efd015ca0b5b4a57dc9535b8feb1273eebeadb60 F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101 -F test/multiplex4.test d3e8a5a522c51cbf3ed1c5b0bd496be02c29d7b1 +F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4 F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a @@ -759,10 +772,10 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62 -F test/null.test a8b09b8ed87852742343b33441a9240022108993 +F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394 -F test/orderby1.test eb246e377612b21a418fbea57047ba8ea88aaa6b +F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6 F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04 F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99 F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4 @@ -780,16 +793,16 @@ F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1 F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6 -F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0 +F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305 F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/permutations.test f9cc1dd987986c9d4949211c7a4ed55ec9aecba1 -F test/pragma.test aa16dedfe01c02c8895169012f7dfde9c163f0d5 -F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 +F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2 +F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028 F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c -F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 -F test/printf2.test b4acd4bf8734243257f01ddefa17c4fb090acc8a +F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc +F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054 F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca @@ -800,11 +813,11 @@ F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df -F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a +F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl 13f401c10dd4fe1a2fb811ae6ed27fd7d1300d3c -F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a +F test/releasetest.tcl 7ad4fd49ae50c41ec7781815bdda8a8b278781d4 +F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14 F test/rollbackfault.test 6a004f71087cc399296cffbb5429ea6da655ae65 @@ -827,20 +840,20 @@ F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5 F test/schema5.test 29699b4421f183c8f0e88bd28ce7d75d13ea653e F test/securedel.test 21749c32ccc30f1ea9e4b9f33295a6521ec20fa0 F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5 -F test/select1.test fc2a61f226a649393664ad54bc5376631801517c +F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686 F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56 F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 -F test/select4.test 8c5a60d439e2df824aed56223566877a883c5c84 +F test/select4.test 824342f382f16b4afe42d0887ef82b3d6abb6075 F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535 -F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2 +F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0 F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95 -F test/selectA.test 64b88a80271c1710966e50e633380696b60a12a4 +F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7 F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25 F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977 F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394 -F test/selectE.test fc02a1eb04c8eb537091482644b7d778ae8759b7 +F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3 F test/selectG.test e8600e379589e85e9fefd2fe4d44a4cdd63f6982 F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118 @@ -856,14 +869,14 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test cdeb849acc2c37aada70d084564b0cc0a2c7df08 +F test/shell1.test ce5e744870387164703bf2dee2cc9753e4a71513 F test/shell2.test 12b8bf901b0e3a8ac58cf5c0c63a0a388d4d1862 F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29 -F test/shell4.test 8a9c08976291e6c6c808b4d718f4a8b299f339f5 -F test/shell5.test 81aba4793fa7441b1300daae1aec4f7e4b5741c1 +F test/shell4.test ddf0a99044e2245a87fc17423e3aaa1445b3243b +F test/shell5.test c04e9f9f948305706b88377c464c7f08ce7479f9 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5 -F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868 +F test/shrink.test 06deac10d591186017466ce67d10645150bfdeec F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329 F test/skipscan1.test 2ddfe5d168462170c4487f534e2a99fb006b2076 F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a @@ -871,11 +884,11 @@ F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2 F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f -F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24 +F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 F test/sort.test 3f492e5b7be1d3f756728d2ff6edf4f6091e84cb F test/sort2.test 37afbc03f5559f2eb0f18940b55d38dfbb5172ac F test/sort3.test 6178ade30810ac9166fcdf14b7065e49c0f534e2 -F test/sort4.test d5e8903194ae551551349ce25dc8d0b40ca2b9c3 +F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c F test/sort5.test a448240a42b49239edc00f85d6d7ac7a1b261e1f F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66 F test/speed1.test f2974a91d79f58507ada01864c0e323093065452 @@ -886,12 +899,13 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523 F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b -F test/speedtest1.c e4e2aa37ff66bad9f414a50a8cb9edfaac65c9e5 +F test/speedtest1.c 2b416dca3a155fcaa849540b2e7fc1df12896c23 F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49 -F test/sqllimits1.test 9014524e7ab16e2a4976b13397db4c29cc29c6d9 -F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de +F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68 +F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf +F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9 -F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9 +F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a @@ -899,14 +913,14 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6 -F test/table.test 06271d61eb13871490d38168433c1ef3dd82bb2a +F test/table.test bd841e8df69b99172ce9c7d53587463913d711ca F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 -F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43 +F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054 F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1 -F test/tester.tcl ed77454e6c7b40eb501db7e79d1c6fbfd3eebbff +F test/tester.tcl 51211254f2ee2340d3e4fa0a83bd5381b9e1a227 F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5 F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1062,23 +1076,23 @@ F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4 F test/trace.test 73a5508100f7fccfbc3f8018d5f6963ed478eea0 -F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382 +F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983 F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76 F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94 F test/transitive1.test 03f532954f46cdf5608f7766bff0b0c52bf2a7cd -F test/trigger1.test dc47573ac79ffe0ee3eecaa517d70d8dacbccd03 +F test/trigger1.test ea9624cc1dae05645469df6119fa815f9e6f1e8c F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359 F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83 F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9 -F test/trigger7.test b39e6dee1debe0ff9c2ef66326668f149f07c9c4 +F test/trigger7.test 200dd51e728c9cdc20c72d99d9e9d45c667248f8 F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4 F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41 F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332 F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe -F test/triggerC.test a68980c5955d62ee24be6f97129d824f199f9a4c +F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092 F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 F test/triggerE.test 355e9c5cbaed5cd039a60baad1fb2197caeb8e52 F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1 @@ -1098,14 +1112,14 @@ F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9 F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d -F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324 +F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9 -F test/vtab1.test 1cef14310144718812351a61c5cfb4ba8494a171 -F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d +F test/vtab1.test d1e5ec7a818f1d3f0402382b6a1d0c06071b770f +F test/vtab2.test 3644649aa8d1daac57fd541f6a5f914cac59203e F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275 F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391 @@ -1113,7 +1127,7 @@ F test/vtab6.test 5f5380c425e52993560ab4763db4f826d2ba7b09 F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5 F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583 F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b -F test/vtabA.test c86e1990b7e1e2bb34602a06fffa4c69f2b516dc +F test/vtabA.test 1317f06a03597eee29f40a49b6c21e1aaba4285f F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796 F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292 F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96 @@ -1126,7 +1140,7 @@ F test/wal.test 885f32b2b390b30b4aa3dbb0e568f8f78d40f5cc F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0 F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c -F test/wal5.test dba8f5f5de95178bc40521d6edf153b2e2829917 +F test/wal5.test 88b5d9a6a3d1532497ee9f4296f010d66f07e33c F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8 F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd @@ -1135,6 +1149,7 @@ F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750 F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe F test/walbak.test b9f68e39646375c2b877be906babcc15d38b4877 F test/walbig.test f437473a16cfb314867c6b5d1dbcd519e73e3434 +F test/walblock.test be48f3a75eff0b4456209f26b3ce186c2015497d F test/walcksum.test 9afeb96240296c08c72fc524d199c912cfe34daa F test/walcrash.test 451d79e528add5c42764cea74aa2750754171b25 F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36 @@ -1155,25 +1170,26 @@ F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8 -F test/where8.test 806f1dcec4088be2b826b33f757fe6e17c3236a1 +F test/where8.test 2eafe74e01cc10355985874e1ff868ac03dbae5e F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739 F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2 F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a -F test/whereD.test fd9120e262f9da3c45940f52aefeef4d15b904e5 +F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622 F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767 +F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c -F test/win32lock.test 71642fa56e9b06e5cfffe6bad67cb8c1eb2c555a +F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d -F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068 +F test/with1.test a86bf7f9288ba759a25ee57221d3bffaca36032a F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775 F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991 F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151 @@ -1181,52 +1197,55 @@ F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 F test/without_rowid3.test 1081aabf60a1e1123b7f9a8f6ae19954351843b0 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862 -F test/without_rowid6.test deddb78ef539c355bddec00cdfaea6c56efd8b3f +F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda -F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688 +F test/zeroblob.test fb3c0e4ab172d386954deda24c03f500e121d80d F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac -F tool/build-all-msvc.bat a0534c971b86fe95f1983f445db5b896d3394818 x +F tool/build-all-msvc.bat 9058bd90a3c078a3d8c17d40e853aaa0f47885f4 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2 F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1 F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439 +F tool/fuzzershell.c e8be9a8bd8e0e7814592c5e3e38de99ad7beee83 F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce -F tool/lemon.c 1864c4fe4a72b1bb28f1792b60504804fe82c5d2 +F tool/lemon.c b9109f59b57e7b6f101c4fe644c8361ba6dee969 F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e -F tool/mkpragmatab.tcl 07a5124cf2dbafa1b375eefcf8ac4227028b0f8b +F tool/mkpragmatab.tcl 94f196c9961e0ca3513e29f57125a3197808be2d F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 -F tool/mksqlite3c-noext.tcl 9ef48e1748dce7b844f67e2450ff9dfeb0fb4ab5 -F tool/mksqlite3c.tcl cfde806851c413db7689b9cb74a4eeb92539c601 -F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12 +F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e +F tool/mksqlite3c.tcl 10c06c9c616415c0269c13a33304a75e3c319c3f +F tool/mksqlite3h.tcl 44730d586c9031638cdd2eb443b801c0d2dbd9f8 F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b -F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105 +F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091 F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5 -F tool/showdb.c bd073a78bce714a0e42d92ea474b3eb8cb53be5d +F tool/showdb.c 3b5d335d537e4dc44d0c86967023819453c87dc6 F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5 +F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68 F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a F tool/showwal.c 85cb36d4fe3e93e2fbd63e786e0d1ce42d0c4fad F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b -F tool/spaceanal.tcl 8e50b217c56a6a086a1b47eac9d09c5cd65b996f +F tool/spaceanal.tcl d5a09620c66a6c144576cb9d2bdfa9a6fbe362a5 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c +F tool/sqldiff.c 10e3c01111f97b99627adf0954cf5ffbfba0723c F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1237,11 +1256,11 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P ec27ab0eb3a1ee08a73dda23d2a0f9fb70962745 -R 7a9d6545656b7d4fe08d198e32a78d62 +P 40f67265c46572cdcfb802a2464d315a821f9be1 +R cbe65e60b1898893979d31fa14de6276 T +bgcolor * #d0c0ff T +sym-release * -T +sym-version-3.8.8.3 * +T +sym-version-3.8.10.2 * U drh -Z 9dbdbd01efd2c5089344e2a1709c163b +Z 9be1f4bd2e2a43cd85454d49558db35f # Remove this line to create a well-formed manifest. diff --git a/manifest.uuid b/manifest.uuid index 007138a..66cf9f1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9d6c1880fb75660bbabd693175579529785f8a6b +2ef4f3a5b1d1d0c4338f8243d40a2452cc1f7fe4 diff --git a/mkopcodeh.awk b/mkopcodeh.awk index babfdc6..94db75e 100644 --- a/mkopcodeh.awk +++ b/mkopcodeh.awk @@ -72,7 +72,6 @@ sub("\r","",name) op[name] = -1 # op[x] holds the numeric value for OP symbol x jump[name] = 0 - out2_prerelease[name] = 0 in1[name] = 0 in2[name] = 0 in3[name] = 0 @@ -92,8 +91,6 @@ sub(",","",x) if(x=="jump"){ jump[name] = 1 - }else if(x=="out2-prerelease"){ - out2_prerelease[name] = 1 }else if(x=="in1"){ in1[name] = 1 }else if(x=="in2"){ @@ -194,13 +191,12 @@ END { name = def[i] a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0 if( jump[name] ) a0 = 1; - if( out2_prerelease[name] ) a1 = 2; - if( in1[name] ) a2 = 4; - if( in2[name] ) a3 = 8; - if( in3[name] ) a4 = 16; - if( out2[name] ) a5 = 32; - if( out3[name] ) a6 = 64; - bv[i] = a0+a1+a2+a3+a4+a5+a6+a7; + if( in1[name] ) a2 = 2; + if( in2[name] ) a3 = 4; + if( in3[name] ) a4 = 8; + if( out2[name] ) a5 = 16; + if( out3[name] ) a6 = 32; + bv[i] = a0+a1+a2+a3+a4+a5+a6; } print "\n" print "/* Properties such as \"out2\" or \"jump\" that are specified in" @@ -208,12 +204,11 @@ END { print "** are encoded into bitvectors as follows:" print "*/" print "#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */" - print "#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */" - print "#define OPFLG_IN1 0x0004 /* in1: P1 is an input */" - print "#define OPFLG_IN2 0x0008 /* in2: P2 is an input */" - print "#define OPFLG_IN3 0x0010 /* in3: P3 is an input */" - print "#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */" - print "#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */" + print "#define OPFLG_IN1 0x0002 /* in1: P1 is an input */" + print "#define OPFLG_IN2 0x0004 /* in2: P2 is an input */" + print "#define OPFLG_IN3 0x0008 /* in3: P3 is an input */" + print "#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */" + print "#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */" print "#define OPFLG_INITIALIZER {\\" for(i=0; i<=max; i++){ if( i%8==0 ) printf("/* %3d */",i) diff --git a/mptest/crash01.test b/mptest/crash01.test index 46f170c..f1483df 100644 --- a/mptest/crash01.test +++ b/mptest/crash01.test @@ -32,6 +32,7 @@ --end --wait 1 --task 2 + DROP TABLE IF EXISTS t2; CREATE TABLE t2(a INTEGER PRIMARY KEY, b); INSERT INTO t2 SELECT a, b FROM t1; UPDATE t1 SET b='x'||a||'y'; @@ -46,6 +47,7 @@ --match 29 28 27 26 25 --end --task 3 + DROP TABLE IF EXISTS t3; CREATE TABLE t3(a INTEGER PRIMARY KEY, b); INSERT INTO t3 SELECT a, b FROM t1; UPDATE t1 SET b='x'||a||'y'; @@ -60,6 +62,7 @@ --match 29 28 27 26 25 --end --task 4 + DROP TABLE IF EXISTS t4; CREATE TABLE t4(a INTEGER PRIMARY KEY, b); INSERT INTO t4 SELECT a, b FROM t1; UPDATE t1 SET b='x'||a||'y'; @@ -74,6 +77,7 @@ --match 29 28 27 26 25 --end --task 5 + DROP TABLE IF EXISTS t5; CREATE TABLE t5(a INTEGER PRIMARY KEY, b); INSERT INTO t5 SELECT a, b FROM t1; UPDATE t1 SET b='x'||a||'y'; diff --git a/mptest/mptest.c b/mptest/mptest.c index 7b56b61..f81ffb5 100644 --- a/mptest/mptest.c +++ b/mptest/mptest.c @@ -53,6 +53,13 @@ # define GETPID getpid #endif +/* The directory separator character(s) */ +#if defined(_WIN32) +# define isDirSep(c) (((c) == '/') || ((c) == '\\')) +#else +# define isDirSep(c) ((c) == '/') +#endif + /* Mark a parameter as unused to suppress compiler warnings */ #define UNUSED_PARAMETER(x) (void)x @@ -824,7 +831,7 @@ static void waitForClient(int iClient, int iTimeout, char *zErrPrefix){ */ static char *filenameTail(char *z){ int i, j; - for(i=j=0; z[i]; i++) if( z[i]=='/' ) j = i+1; + for(i=j=0; z[i]; i++) if( isDirSep(z[i]) ) j = i+1; return z+j; } @@ -1021,9 +1028,9 @@ static void runScript( char *zNewFile, *zNewScript; char *zToDel = 0; zNewFile = azArg[0]; - if( zNewFile[0]!='/' ){ + if( !isDirSep(zNewFile[0]) ){ int k; - for(k=(int)strlen(zFilename)-1; k>=0 && zFilename[k]!='/'; k--){} + for(k=(int)strlen(zFilename)-1; k>=0 && !isDirSep(zFilename[k]); k--){} if( k>0 ){ zNewFile = zToDel = sqlite3_mprintf("%.*s/%s", k,zFilename,zNewFile); } @@ -1231,7 +1238,7 @@ static void usage(const char *argv0){ int i; const char *zTail = argv0; for(i=0; argv0[i]; i++){ - if( argv0[i]=='/' ) zTail = argv0+i+1; + if( isDirSep(argv0[i]) ) zTail = argv0+i+1; } fprintf(stderr,"Usage: %s DATABASE ?OPTIONS? ?SCRIPT?\n", zTail); exit(1); @@ -1252,7 +1259,7 @@ static void unrecognizedArguments( exit(1); } -int main(int argc, char **argv){ +int SQLITE_CDECL main(int argc, char **argv){ const char *zClient; int iClient; int n, i; @@ -1262,6 +1269,9 @@ int main(int argc, char **argv){ int taskId; const char *zTrace; const char *zCOption; + const char *zJMode; + const char *zNRep; + int nRep = 1, iRep; g.argv0 = argv[0]; g.iTrace = 1; @@ -1277,6 +1287,10 @@ int main(int argc, char **argv){ } n = argc-2; sqlite3_snprintf(sizeof(g.zName), g.zName, "%05d.mptest", GETPID()); + zJMode = findOption(argv+2, &n, "journalmode", 1); + zNRep = findOption(argv+2, &n, "repeat", 1); + if( zNRep ) nRep = atoi(zNRep); + if( nRep<1 ) nRep = 1; g.zVfs = findOption(argv+2, &n, "vfs", 1); zClient = findOption(argv+2, &n, "client", 1); g.zErrLog = findOption(argv+2, &n, "errlog", 1); @@ -1305,6 +1319,9 @@ int main(int argc, char **argv){ GETPID(), iClient); }else{ if( g.iTrace>0 ){ + printf("BEGIN: %s", argv[0]); + for(i=1; i0 ){ if( n>0 ) unrecognizedArguments(argv[0], n, argv+2); if( g.iTrace ) logMessage("start-client"); @@ -1349,6 +1377,9 @@ int main(int argc, char **argv){ } if( n>1 ) unrecognizedArguments(argv[0], n, argv+2); runSql( + "DROP TABLE IF EXISTS task;\n" + "DROP TABLE IF EXISTS counters;\n" + "DROP TABLE IF EXISTS client;\n" "CREATE TABLE task(\n" " id INTEGER PRIMARY KEY,\n" " name TEXT,\n" @@ -1364,10 +1395,12 @@ int main(int argc, char **argv){ "CREATE TABLE client(id INTEGER PRIMARY KEY, wantHalt);\n" ); zScript = readFile(argv[2]); - if( g.iTrace ) logMessage("begin script [%s]\n", argv[2]); - runScript(0, 0, zScript, argv[2]); + for(iRep=1; iRep<=nRep; iRep++){ + if( g.iTrace ) logMessage("begin script [%s] cycle %d\n", argv[2], iRep); + runScript(0, 0, zScript, argv[2]); + if( g.iTrace ) logMessage("end script [%s] cycle %d\n", argv[2], iRep); + } sqlite3_free(zScript); - if( g.iTrace ) logMessage("end script [%s]\n", argv[2]); waitForClient(0, 2000, "during shutdown...\n"); trySql("UPDATE client SET wantHalt=1"); sqlite3_sleep(10); @@ -1391,11 +1424,14 @@ int main(int argc, char **argv){ } sqlite3_finalize(pStmt); } - sqlite3_close(g.db); + sqlite3_close(g.db); maybeClose(g.pLog); maybeClose(g.pErrLog); if( iClient==0 ){ printf("Summary: %d errors out of %d tests\n", g.nError, g.nTest); + printf("END: %s", argv[0]); + for(i=1; i0; } diff --git a/mptest/multiwrite01.test b/mptest/multiwrite01.test index 4f88a68..7062ae0 100644 --- a/mptest/multiwrite01.test +++ b/mptest/multiwrite01.test @@ -361,6 +361,8 @@ PRAGMA integrity_check(10); WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y') ORDER BY t3.a LIMIT 7 --match 45 46 47 48 49 50 51 + PRAGMA integrity_check; + --match ok --end --task 5 SELECT t1.a FROM t1, t2 @@ -371,6 +373,8 @@ PRAGMA integrity_check(10); WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y') ORDER BY t3.a LIMIT 7 --match 45 46 47 48 49 50 51 + PRAGMA integrity_check; + --match ok --end --task 3 SELECT t1.a FROM t1, t2 @@ -381,6 +385,8 @@ PRAGMA integrity_check(10); WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y') ORDER BY t3.a LIMIT 7 --match 45 46 47 48 49 50 51 + PRAGMA integrity_check; + --match ok --end --task 2 SELECT t1.a FROM t1, t2 @@ -391,6 +397,8 @@ PRAGMA integrity_check(10); WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y') ORDER BY t3.a LIMIT 7 --match 45 46 47 48 49 50 51 + PRAGMA integrity_check; + --match ok --end --task 4 SELECT t1.a FROM t1, t2 @@ -401,5 +409,7 @@ PRAGMA integrity_check(10); WHERE t4.b GLOB 'x4?y' AND t3.b=('x'||(t4.a+5)||'y') ORDER BY t3.a LIMIT 7 --match 45 46 47 48 49 50 51 + PRAGMA integrity_check; + --match ok --end --wait all diff --git a/src/alter.c b/src/alter.c index dd06024..44422ca 100644 --- a/src/alter.c +++ b/src/alter.c @@ -126,6 +126,7 @@ static void renameParentFunc( n = sqlite3GetToken(z, &token); }while( token==TK_SPACE ); + if( token==TK_ILLEGAL ) break; zParent = sqlite3DbStrNDup(db, (const char *)z, n); if( zParent==0 ) break; sqlite3Dequote(zParent); @@ -690,7 +691,10 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ */ if( pDflt ){ sqlite3_value *pVal = 0; - if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){ + int rc; + rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal); + assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); + if( rc!=SQLITE_OK ){ db->mallocFailed = 1; return; } diff --git a/src/analyze.c b/src/analyze.c index fec2bdb..2a0d6d2 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1519,14 +1519,17 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ z = argv[2]; if( pIndex ){ + tRowcnt *aiRowEst = 0; int nCol = pIndex->nKeyCol+1; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 - tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero( - sizeof(tRowcnt) * nCol - ); - if( aiRowEst==0 ) pInfo->db->mallocFailed = 1; -#else - tRowcnt * const aiRowEst = 0; + /* Index.aiRowEst may already be set here if there are duplicate + ** sqlite_stat1 entries for this index. In that case just clobber + ** the old data with the new instead of allocating a new array. */ + if( pIndex->aiRowEst==0 ){ + pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol); + if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1; + } + aiRowEst = pIndex->aiRowEst; #endif pIndex->bUnordered = 0; decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex); diff --git a/src/attach.c b/src/attach.c index de87429..efc9eb9 100644 --- a/src/attach.c +++ b/src/attach.c @@ -191,7 +191,7 @@ static void attachFunc( case SQLITE_NULL: /* No key specified. Use the key from the main database */ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); - if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){ + if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); } break; @@ -298,7 +298,7 @@ static void detachFunc( sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; - sqlite3ResetAllSchemasOfConnection(db); + sqlite3CollapseDatabaseArray(db); return; detach_error: @@ -332,7 +332,6 @@ static void codeAttach( SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) ){ - pParse->nErr++; goto attach_end; } diff --git a/src/backup.c b/src/backup.c index e3f8690..81c8b5c 100644 --- a/src/backup.c +++ b/src/backup.c @@ -247,7 +247,7 @@ static int backupOnePage( ** guaranteed that the shared-mutex is held by this thread, handle ** p->pSrc may not actually be the owner. */ int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); - int nDestReserve = sqlite3BtreeGetReserve(p->pDest); + int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest); #endif int rc = SQLITE_OK; i64 iOff; diff --git a/src/bitvec.c b/src/bitvec.c index 52184aa..c348974 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -341,7 +341,7 @@ int sqlite3BitvecBuiltinTest(int sz, int *aOp){ ** bits to act as the reference */ pBitvec = sqlite3BitvecCreate( sz ); pV = sqlite3MallocZero( (sz+7)/8 + 1 ); - pTmpSpace = sqlite3_malloc(BITVEC_SZ); + pTmpSpace = sqlite3_malloc64(BITVEC_SZ); if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end; /* NULL pBitvec tests */ diff --git a/src/btmutex.c b/src/btmutex.c index f9fe5b3..c9c8572 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -141,6 +141,7 @@ static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){ ** Exit the recursive mutex on a Btree. */ void sqlite3BtreeLeave(Btree *p){ + assert( sqlite3_mutex_held(p->db->mutex) ); if( p->sharable ){ assert( p->wantToLock>0 ); p->wantToLock--; diff --git a/src/btree.c b/src/btree.c index f9f76c2..4831657 100644 --- a/src/btree.c +++ b/src/btree.c @@ -175,6 +175,12 @@ static int hasSharedCacheTableLock( for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ Index *pIdx = (Index *)sqliteHashData(p); if( pIdx->tnum==(int)iRoot ){ + if( iTab ){ + /* Two or more indexes share the same root page. There must + ** be imposter tables. So just return true. The assert is not + ** useful in that case. */ + return 1; + } iTab = pIdx->pTable->tnum; } } @@ -594,10 +600,15 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){ static int saveCursorPosition(BtCursor *pCur){ int rc; - assert( CURSOR_VALID==pCur->eState ); + assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState ); assert( 0==pCur->pKey ); assert( cursorHoldsMutex(pCur) ); + if( pCur->eState==CURSOR_SKIPNEXT ){ + pCur->eState = CURSOR_VALID; + }else{ + pCur->skipNext = 0; + } rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ @@ -668,7 +679,7 @@ static int SQLITE_NOINLINE saveCursorsOnList( ){ do{ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ - if( p->eState==CURSOR_VALID ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; @@ -740,17 +751,19 @@ static int btreeMoveto( */ static int btreeRestoreCursorPosition(BtCursor *pCur){ int rc; + int skipNext; assert( cursorHoldsMutex(pCur) ); assert( pCur->eState>=CURSOR_REQUIRESEEK ); if( pCur->eState==CURSOR_FAULT ){ return pCur->skipNext; } pCur->eState = CURSOR_INVALID; - rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext); + rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); + pCur->skipNext |= skipNext; if( pCur->skipNext && pCur->eState==CURSOR_VALID ){ pCur->eState = CURSOR_SKIPNEXT; } @@ -802,9 +815,10 @@ int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){ *pDifferentRow = 1; return rc; } - if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){ + if( pCur->eState!=CURSOR_VALID ){ *pDifferentRow = 1; }else{ + assert( pCur->skipNext==0 ); *pDifferentRow = 0; } return SQLITE_OK; @@ -1945,16 +1959,18 @@ int sqlite3BtreeOpen( */ if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){ if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ + int nFilename = sqlite3Strlen30(zFilename)+1; int nFullPathname = pVfs->mxPathname+1; - char *zFullPathname = sqlite3Malloc(nFullPathname); + char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename)); MUTEX_LOGIC( sqlite3_mutex *mutexShared; ) + p->sharable = 1; if( !zFullPathname ){ sqlite3_free(p); return SQLITE_NOMEM; } if( isMemdb ){ - memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1); + memcpy(zFullPathname, zFilename, nFilename); }else{ rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); @@ -2011,8 +2027,8 @@ int sqlite3BtreeOpen( ** the right size. This is to guard against size changes that result ** when compiling on a different architecture. */ - assert( sizeof(i64)==8 || sizeof(i64)==4 ); - assert( sizeof(u64)==8 || sizeof(u64)==4 ); + assert( sizeof(i64)==8 ); + assert( sizeof(u64)==8 ); assert( sizeof(u32)==4 ); assert( sizeof(u16)==2 ); assert( sizeof(Pgno)==4 ); @@ -2399,6 +2415,9 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){ BtShared *pBt = p->pBt; assert( nReserve>=-1 && nReserve<=255 ); sqlite3BtreeEnter(p); +#if SQLITE_HAS_CODEC + if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve; +#endif if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){ sqlite3BtreeLeave(p); return SQLITE_READONLY; @@ -2410,7 +2429,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){ if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && ((pageSize-1)&pageSize)==0 ){ assert( (pageSize & 7)==0 ); - assert( !pBt->pPage1 && !pBt->pCursor ); + assert( !pBt->pCursor ); pBt->pageSize = (u32)pageSize; freeTempSpace(pBt); } @@ -2428,7 +2447,6 @@ int sqlite3BtreeGetPageSize(Btree *p){ return p->pBt->pageSize; } -#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG) /* ** This function is similar to sqlite3BtreeGetReserve(), except that it ** may only be called if it is guaranteed that the b-tree mutex is already @@ -2441,25 +2459,33 @@ int sqlite3BtreeGetPageSize(Btree *p){ ** database handle that owns *p, causing undefined behavior. */ int sqlite3BtreeGetReserveNoMutex(Btree *p){ + int n; assert( sqlite3_mutex_held(p->pBt->mutex) ); - return p->pBt->pageSize - p->pBt->usableSize; + n = p->pBt->pageSize - p->pBt->usableSize; + return n; } -#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */ -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) /* ** Return the number of bytes of space at the end of every page that ** are intentually left unused. This is the "reserved" space that is ** sometimes used by extensions. +** +** If SQLITE_HAS_MUTEX is defined then the number returned is the +** greater of the current reserved space and the maximum requested +** reserve space. */ -int sqlite3BtreeGetReserve(Btree *p){ +int sqlite3BtreeGetOptimalReserve(Btree *p){ int n; sqlite3BtreeEnter(p); - n = p->pBt->pageSize - p->pBt->usableSize; + n = sqlite3BtreeGetReserveNoMutex(p); +#ifdef SQLITE_HAS_CODEC + if( npBt->optimalReserve ) n = p->pBt->optimalReserve; +#endif sqlite3BtreeLeave(p); return n; } + /* ** Set the maximum page count for a database if mxPage is positive. ** No changes are made if mxPage is 0 or negative. @@ -2490,7 +2516,6 @@ int sqlite3BtreeSecureDelete(Btree *p, int newFlag){ sqlite3BtreeLeave(p); return b; } -#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ /* ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' @@ -3610,7 +3635,7 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ for(p=pBtree->pBt->pCursor; p; p=p->pNext){ int i; if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ - if( p->eState==CURSOR_VALID ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ rc = saveCursorPosition(p); if( rc!=SQLITE_OK ){ (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); @@ -4016,6 +4041,8 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); + assert( pCur->iPage>=0 ); + assert( pCur->iPageapPage[pCur->iPage]->intKeyLeaf==1 ); getCellInfo(pCur); *pSize = pCur->info.nPayload; @@ -4424,13 +4451,18 @@ static const void *fetchPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ u32 *pAmt /* Write the number of available bytes here */ ){ + u32 amt; assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); assert( cursorHoldsMutex(pCur) ); assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); assert( pCur->info.nSize>0 ); - *pAmt = pCur->info.nLocal; + assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB ); + assert( pCur->info.pPayloadapPage[pCur->iPage]->aDataEnd ||CORRUPT_DB); + amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload); + if( pCur->info.nLocalinfo.nLocal; + *pAmt = amt; return (void*)pCur->info.pPayload; } @@ -4494,7 +4526,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ return SQLITE_OK; } -#if 0 +#if SQLITE_DEBUG /* ** Page pParent is an internal (non-leaf) tree page. This function ** asserts that page number iChild is the left-child if the iIdx'th @@ -4503,6 +4535,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ ** the page. */ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){ + if( CORRUPT_DB ) return; /* The conditions tested below might not be true + ** in a corrupt database */ assert( iIdx<=pParent->nCell ); if( iIdx==pParent->nCell ){ assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild ); @@ -4527,19 +4561,11 @@ static void moveToParent(BtCursor *pCur){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->iPage>0 ); assert( pCur->apPage[pCur->iPage] ); - - /* UPDATE: It is actually possible for the condition tested by the assert - ** below to be untrue if the database file is corrupt. This can occur if - ** one cursor has modified page pParent while a reference to it is held - ** by a second cursor. Which can only happen if a single page is linked - ** into more than one b-tree structure in a corrupt database. */ -#if 0 assertParentIndex( pCur->apPage[pCur->iPage-1], pCur->aiIdx[pCur->iPage-1], pCur->apPage[pCur->iPage]->pgno ); -#endif testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell ); releasePage(pCur->apPage[pCur->iPage]); @@ -6714,7 +6740,6 @@ static int balance_nonroot( }else if( iParentIdx==i ){ nxDiv = i-2+bBulk; }else{ - assert( bBulk==0 ); nxDiv = iParentIdx-1; } i = 2-bBulk; @@ -7465,7 +7490,8 @@ static int balance(BtCursor *pCur){ ** pSpace buffer passed to the latter call to balance_nonroot(). */ u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); - rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints); + rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, + pCur->hints&BTREE_BULKLOAD); if( pFree ){ /* If pFree is not NULL, it points to the pSpace buffer used ** by a previous call to balance_nonroot(). Its contents are @@ -7486,6 +7512,7 @@ static int balance(BtCursor *pCur){ /* The next iteration of the do-loop balances the parent page. */ releasePage(pPage); pCur->iPage--; + assert( pCur->iPage>=0 ); } }while( rc==SQLITE_OK ); @@ -7962,9 +7989,13 @@ static int clearDatabasePage( if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } - rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; + if( pPage->bBusy ){ + rc = SQLITE_CORRUPT_BKPT; + goto cleardatabasepage_out; + } + pPage->bBusy = 1; hdr = pPage->hdrOffset; for(i=0; inCell; i++){ pCell = findCell(pPage, i); @@ -7989,6 +8020,7 @@ static int clearDatabasePage( } cleardatabasepage_out: + pPage->bBusy = 0; releasePage(pPage); return rc; } @@ -8496,6 +8528,57 @@ static void checkList( } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ +/* +** An implementation of a min-heap. +** +** aHeap[0] is the number of elements on the heap. aHeap[1] is the +** root element. The daughter nodes of aHeap[N] are aHeap[N*2] +** and aHeap[N*2+1]. +** +** The heap property is this: Every node is less than or equal to both +** of its daughter nodes. A consequence of the heap property is that the +** root node aHeap[1] is always the minimum value currently in the heap. +** +** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto +** the heap, preserving the heap property. The btreeHeapPull() routine +** removes the root element from the heap (the minimum value in the heap) +** and then moves other nodes around as necessary to preserve the heap +** property. +** +** This heap is used for cell overlap and coverage testing. Each u32 +** entry represents the span of a cell or freeblock on a btree page. +** The upper 16 bits are the index of the first byte of a range and the +** lower 16 bits are the index of the last byte of that range. +*/ +static void btreeHeapInsert(u32 *aHeap, u32 x){ + u32 j, i = ++aHeap[0]; + aHeap[i] = x; + while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){ + x = aHeap[j]; + aHeap[j] = aHeap[i]; + aHeap[i] = x; + i = j; + } +} +static int btreeHeapPull(u32 *aHeap, u32 *pOut){ + u32 j, i, x; + if( (x = aHeap[0])==0 ) return 0; + *pOut = aHeap[1]; + aHeap[1] = aHeap[x]; + aHeap[x] = 0xffffffff; + aHeap[0]--; + i = 1; + while( (j = i*2)<=aHeap[0] ){ + if( aHeap[j]>aHeap[j+1] ) j++; + if( aHeap[i]zPfx; @@ -8673,15 +8757,15 @@ static int checkTreePage( */ data = pPage->aData; hdr = pPage->hdrOffset; - hit = sqlite3PageMalloc( pBt->pageSize ); + heap = (u32*)sqlite3PageMalloc( pBt->pageSize ); pCheck->zPfx = 0; - if( hit==0 ){ + if( heap==0 ){ pCheck->mallocFailed = 1; }else{ int contentOffset = get2byteNotZero(&data[hdr+5]); assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ - memset(hit+contentOffset, 0, usableSize-contentOffset); - memset(hit, 1, contentOffset); + heap[0] = 0; + btreeHeapInsert(heap, contentOffset-1); /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the ** number of cells on the page. */ nCell = get2byte(&data[hdr+3]); @@ -8693,7 +8777,6 @@ static int checkTreePage( for(i=0; i=pc; j--) hit[j]++; + btreeHeapInsert(heap, (pc<<16)|(pc+size-1)); } } /* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header @@ -8714,7 +8797,7 @@ static int checkTreePage( assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */ size = get2byte(&data[i+2]); assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */ - for(j=i+size-1; j>=i; j--) hit[j]++; + btreeHeapInsert(heap, (i<<16)|(i+size-1)); /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a ** big-endian integer which is the offset in the b-tree page of the next ** freeblock in the chain, or zero if the freeblock is the last on the @@ -8726,27 +8809,33 @@ static int checkTreePage( assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */ i = j; } - for(i=cnt=0; i1 ){ + cnt = 0; + assert( heap[0]>0 ); + assert( (heap[1]>>16)==0 ); + btreeHeapPull(heap,&prev); + while( btreeHeapPull(heap,&x) ){ + if( (prev&0xffff)+1>(x>>16) ){ checkAppendMsg(pCheck, - "Multiple uses for byte %d of page %d", i, iPage); + "Multiple uses for byte %u of page %d", x>>16, iPage); break; + }else{ + cnt += (x>>16) - (prev&0xffff) - 1; + prev = x; } } + cnt += usableSize - (prev&0xffff) - 1; /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments ** is stored in the fifth field of the b-tree page header. ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the ** number of fragmented free bytes within the cell content area. */ - if( cnt!=data[hdr+7] ){ + if( heap[0]==0 && cnt!=data[hdr+7] ){ checkAppendMsg(pCheck, "Fragmentation of %d bytes reported as %d on page %d", cnt, data[hdr+7], iPage); } } - sqlite3PageFree(hit); + sqlite3PageFree(heap); releasePage(pPage); end_of_check: @@ -8810,8 +8899,7 @@ char *sqlite3BtreeIntegrityCheck( } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); - sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); - sCheck.errMsg.useMalloc = 2; + sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); /* Check the integrity of the freelist */ @@ -9128,14 +9216,23 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ } /* -** set the mask of hint flags for cursor pCsr. Currently the only valid -** values are 0 and BTREE_BULKLOAD. +** set the mask of hint flags for cursor pCsr. */ void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ - assert( mask==BTREE_BULKLOAD || mask==0 ); + assert( mask==BTREE_BULKLOAD || mask==BTREE_SEEK_EQ || mask==0 ); pCsr->hints = mask; } +#ifdef SQLITE_DEBUG +/* +** Return true if the cursor has a hint specified. This routine is +** only used from within assert() statements +*/ +int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){ + return (pCsr->hints & mask)!=0; +} +#endif + /* ** Return true if the given Btree is read-only. */ diff --git a/src/btree.h b/src/btree.h index b57d500..3edc2b3 100644 --- a/src/btree.h +++ b/src/btree.h @@ -73,10 +73,8 @@ int sqlite3BtreeGetPageSize(Btree*); int sqlite3BtreeMaxPageCount(Btree*,int); u32 sqlite3BtreeLastPage(Btree*); int sqlite3BtreeSecureDelete(Btree*,int); -int sqlite3BtreeGetReserve(Btree*); -#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG) +int sqlite3BtreeGetOptimalReserve(Btree*); int sqlite3BtreeGetReserveNoMutex(Btree *p); -#endif int sqlite3BtreeSetAutoVacuum(Btree *, int); int sqlite3BtreeGetAutoVacuum(Btree *); int sqlite3BtreeBeginTrans(Btree*,int); @@ -154,8 +152,18 @@ int sqlite3BtreeNewDb(Btree *p); /* ** Values that may be OR'd together to form the second argument of an ** sqlite3BtreeCursorHints() call. +** +** The BTREE_BULKLOAD flag is set on index cursors when the index is going +** to be filled with content that is already in sorted order. +** +** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or +** OP_SeekLE opcodes for a range search, but where the range of entries +** selected will all have the same key. In other words, the cursor will +** be used only for equality key searches. +** */ -#define BTREE_BULKLOAD 0x00000001 +#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */ +#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */ int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ @@ -201,6 +209,9 @@ void sqlite3BtreeIncrblobCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); +#ifdef SQLITE_DEBUG +int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); +#endif int sqlite3BtreeIsReadonly(Btree *pBt); int sqlite3HeaderSizeBtree(void); diff --git a/src/btreeInt.h b/src/btreeInt.h index ed4d75e..33ef641 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -280,6 +280,7 @@ struct MemPage { u8 hdrOffset; /* 100 for page 1. 0 otherwise */ u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ u8 max1bytePayload; /* min(maxLocal,127) */ + u8 bBusy; /* Prevent endless loops on corrupt database files */ u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ @@ -418,6 +419,9 @@ struct BtShared { #endif u8 inTransaction; /* Transaction state */ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ +#ifdef SQLITE_HAS_CODEC + u8 optimalReserve; /* Desired amount of reserved space per page */ +#endif u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ diff --git a/src/build.c b/src/build.c index f02989b..7990561 100644 --- a/src/build.c +++ b/src/build.c @@ -142,9 +142,11 @@ void sqlite3FinishCoding(Parse *pParse){ assert( pParse->pToplevel==0 ); db = pParse->db; - if( db->mallocFailed ) return; if( pParse->nested ) return; - if( pParse->nErr ) return; + if( db->mallocFailed || pParse->nErr ){ + if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR; + return; + } /* Begin by generating some termination code at the end of the ** vdbe program @@ -226,7 +228,7 @@ void sqlite3FinishCoding(Parse *pParse){ /* Get the VDBE program ready for execution */ - if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){ + if( v && pParse->nErr==0 && !db->mallocFailed ){ assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */ /* A minimum of one cursor is required if autoincrement is used * See ticket [a696379c1f08866] */ @@ -308,10 +310,6 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ Table *p = 0; int i; -#ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || zName==0 ) return 0; -#endif - /* All mutexes are required for schema access. Make sure we hold them. */ assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) ); #if SQLITE_USER_AUTHENTICATION @@ -765,14 +763,12 @@ int sqlite3TwoPartName( if( ALWAYS(pName2!=0) && pName2->n>0 ){ if( db->init.busy ) { sqlite3ErrorMsg(pParse, "corrupt database"); - pParse->nErr++; return -1; } *pUnqual = pName2; iDb = sqlite3FindDb(db, pName1); if( iDb<0 ){ sqlite3ErrorMsg(pParse, "unknown database %T", pName1); - pParse->nErr++; return -1; } }else{ @@ -931,7 +927,7 @@ void sqlite3StartTable( if( !noErr ){ sqlite3ErrorMsg(pParse, "table %T already exists", pName); }else{ - assert( !db->init.busy ); + assert( !db->init.busy || CORRUPT_DB ); sqlite3CodeVerifySchema(pParse, iDb); } goto begin_table_error; @@ -1220,7 +1216,8 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){ p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; pCol = &p->aCol[p->nCol-1]; - assert( pCol->zType==0 ); + assert( pCol->zType==0 || CORRUPT_DB ); + sqlite3DbFree(pParse->db, pCol->zType); pCol->zType = sqlite3NameFromToken(pParse->db, pType); pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); } @@ -1731,11 +1728,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ assert( pPk!=0 ); nPk = pPk->nKeyCol; - /* Make sure every column of the PRIMARY KEY is NOT NULL */ - for(i=0; iaCol[pPk->aiColumn[i]].notNull = 1; + /* Make sure every column of the PRIMARY KEY is NOT NULL. (Except, + ** do not enforce this for imposter tables.) */ + if( !db->init.imposterTable ){ + for(i=0; iaCol[pPk->aiColumn[i]].notNull = 1; + } + pPk->uniqNotNull = 1; } - pPk->uniqNotNull = 1; /* The root page of the PRIMARY KEY is the table root page */ pPk->tnum = pTab->tnum; @@ -2451,6 +2451,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ } assert( pParse->nErr==0 ); assert( pName->nSrc==1 ); + if( sqlite3ReadSchema(pParse) ) goto exit_drop_table; if( noErr ) db->suppressErr++; pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; @@ -2764,7 +2765,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ addr2 = sqlite3VdbeCurrentAddr(v); } sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx); - sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1); + sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1); + sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v); @@ -2857,8 +2859,7 @@ Index *sqlite3CreateIndex( char *zExtra = 0; /* Extra space after the Index object */ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ - assert( pParse->nErr==0 ); /* Never called with prior errors */ - if( db->mallocFailed || IN_DECLARE_VTAB ){ + if( db->mallocFailed || IN_DECLARE_VTAB || pParse->nErr>0 ){ goto exit_create_index; } if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ @@ -3184,6 +3185,7 @@ Index *sqlite3CreateIndex( pIdx->onError = pIndex->onError; } } + pRet = pIdx; goto exit_create_index; } } @@ -3776,7 +3778,6 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){ void sqlite3SrcListShiftJoinType(SrcList *p){ if( p ){ int i; - assert( p->a || p->nSrc==0 ); for(i=p->nSrc-1; i>0; i--){ p->a[i].jointype = p->a[i-1].jointype; } @@ -4023,8 +4024,7 @@ void sqlite3UniqueConstraint( StrAccum errMsg; Table *pTab = pIdx->pTable; - sqlite3StrAccumInit(&errMsg, 0, 0, 200); - errMsg.db = pParse->db; + sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); for(j=0; jnKeyCol; j++){ char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2); diff --git a/src/complete.c b/src/complete.c index f7a35cc..a12184e 100644 --- a/src/complete.c +++ b/src/complete.c @@ -269,7 +269,7 @@ int sqlite3_complete(const char *zSql){ int sqlite3_complete16(const void *zSql){ sqlite3_value *pVal; char const *zSql8; - int rc = SQLITE_NOMEM; + int rc; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); diff --git a/src/ctime.c b/src/ctime.c index 4f98ffe..9503214 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -75,6 +75,9 @@ static const char * const azCompileOpt[] = { #if SQLITE_ENABLE_COLUMN_METADATA "ENABLE_COLUMN_METADATA", #endif +#if SQLITE_ENABLE_DBSTAT_VTAB + "ENABLE_DBSTAT_VTAB", +#endif #if SQLITE_ENABLE_EXPENSIVE_ASSERT "ENABLE_EXPENSIVE_ASSERT", #endif diff --git a/src/test_stat.c b/src/dbstat.c similarity index 81% rename from src/test_stat.c rename to src/dbstat.c index 615df3d..64cd5d8 100644 --- a/src/test_stat.c +++ b/src/dbstat.c @@ -18,11 +18,9 @@ ** for an example implementation. */ -#ifndef SQLITE_AMALGAMATION -# include "sqliteInt.h" -#endif - -#ifndef SQLITE_OMIT_VIRTUALTABLE +#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \ + && !defined(SQLITE_OMIT_VIRTUALTABLE) +#include "sqliteInt.h" /* Requires access to internal data structures */ /* ** Page paths: @@ -124,6 +122,7 @@ struct StatCursor { struct StatTable { sqlite3_vtab base; sqlite3 *db; + int iDb; /* Index of database to analyze */ }; #ifndef get2byte @@ -140,15 +139,34 @@ static int statConnect( sqlite3_vtab **ppVtab, char **pzErr ){ - StatTable *pTab; + StatTable *pTab = 0; + int rc = SQLITE_OK; + int iDb; - pTab = (StatTable *)sqlite3_malloc(sizeof(StatTable)); - memset(pTab, 0, sizeof(StatTable)); - pTab->db = db; + if( argc>=4 ){ + iDb = sqlite3FindDbName(db, argv[3]); + if( iDb<0 ){ + *pzErr = sqlite3_mprintf("no such database: %s", argv[3]); + return SQLITE_ERROR; + } + }else{ + iDb = 0; + } + rc = sqlite3_declare_vtab(db, VTAB_SCHEMA); + if( rc==SQLITE_OK ){ + pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable)); + if( pTab==0 ) rc = SQLITE_NOMEM; + } - sqlite3_declare_vtab(db, VTAB_SCHEMA); - *ppVtab = &pTab->base; - return SQLITE_OK; + assert( rc==SQLITE_OK || pTab==0 ); + if( rc==SQLITE_OK ){ + memset(pTab, 0, sizeof(StatTable)); + pTab->db = db; + pTab->iDb = iDb; + } + + *ppVtab = (sqlite3_vtab*)pTab; + return rc; } /* @@ -195,33 +213,45 @@ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ StatCursor *pCsr; int rc; - pCsr = (StatCursor *)sqlite3_malloc(sizeof(StatCursor)); - memset(pCsr, 0, sizeof(StatCursor)); - pCsr->base.pVtab = pVTab; + pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor)); + if( pCsr==0 ){ + rc = SQLITE_NOMEM; + }else{ + char *zSql; + memset(pCsr, 0, sizeof(StatCursor)); + pCsr->base.pVtab = pVTab; - rc = sqlite3_prepare_v2(pTab->db, - "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" - " UNION ALL " - "SELECT name, rootpage, type FROM sqlite_master WHERE rootpage!=0" - " ORDER BY name", -1, - &pCsr->pStmt, 0 - ); - if( rc!=SQLITE_OK ){ - sqlite3_free(pCsr); - return rc; + zSql = sqlite3_mprintf( + "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type" + " UNION ALL " + "SELECT name, rootpage, type" + " FROM \"%w\".sqlite_master WHERE rootpage!=0" + " ORDER BY name", pTab->db->aDb[pTab->iDb].zName); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0); + sqlite3_free(zSql); + } + if( rc!=SQLITE_OK ){ + sqlite3_free(pCsr); + pCsr = 0; + } } *ppCursor = (sqlite3_vtab_cursor *)pCsr; - return SQLITE_OK; + return rc; } static void statClearPage(StatPage *p){ int i; - for(i=0; inCell; i++){ - sqlite3_free(p->aCell[i].aOvfl); + if( p->aCell ){ + for(i=0; inCell; i++){ + sqlite3_free(p->aCell[i].aOvfl); + } + sqlite3_free(p->aCell); } sqlite3PagerUnref(p->pPg); - sqlite3_free(p->aCell); sqlite3_free(p->zPath); memset(p, 0, sizeof(StatPage)); } @@ -301,9 +331,13 @@ static int statDecodePage(Btree *pBt, StatPage *p){ if( p->nCell ){ int i; /* Used to iterate through cells */ - int nUsable = szPage - sqlite3BtreeGetReserve(pBt); + int nUsable; /* Usable bytes per page */ - p->aCell = sqlite3_malloc((p->nCell+1) * sizeof(StatCell)); + sqlite3BtreeEnter(pBt); + nUsable = szPage - sqlite3BtreeGetReserveNoMutex(pBt); + sqlite3BtreeLeave(pBt); + p->aCell = sqlite3_malloc64((p->nCell+1) * sizeof(StatCell)); + if( p->aCell==0 ) return SQLITE_NOMEM; memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell)); for(i=0; inCell; i++){ @@ -335,7 +369,8 @@ static int statDecodePage(Btree *pBt, StatPage *p){ int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); pCell->nOvfl = nOvfl; - pCell->aOvfl = sqlite3_malloc(sizeof(u32)*nOvfl); + pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); + if( pCell->aOvfl==0 ) return SQLITE_NOMEM; pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]); for(j=1; jpVtab; - Btree *pBt = pTab->db->aDb[0].pBt; + Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; Pager *pPager = sqlite3BtreePager(pBt); sqlite3_file *fd; sqlite3_int64 x[2]; @@ -377,7 +412,7 @@ static void statSizeAndOffset(StatCursor *pCsr){ */ fd = sqlite3PagerFile(pPager); x[0] = pCsr->iPageno; - if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ + if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ pCsr->iOffset = x[0]; pCsr->szPage = (int)x[1]; } @@ -389,9 +424,10 @@ static void statSizeAndOffset(StatCursor *pCsr){ static int statNext(sqlite3_vtab_cursor *pCursor){ int rc; int nPayload; + char *z; StatCursor *pCsr = (StatCursor *)pCursor; StatTable *pTab = (StatTable *)pCursor->pVtab; - Btree *pBt = pTab->db->aDb[0].pBt; + Btree *pBt = pTab->db->aDb[pTab->iDb].pBt; Pager *pPager = sqlite3BtreePager(pBt); sqlite3_free(pCsr->zPath); @@ -411,8 +447,9 @@ statNextRestart: rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg); pCsr->aPage[0].iPgno = iRoot; pCsr->aPage[0].iCell = 0; - pCsr->aPage[0].zPath = sqlite3_mprintf("/"); + pCsr->aPage[0].zPath = z = sqlite3_mprintf("/"); pCsr->iPage = 0; + if( z==0 ) rc = SQLITE_NOMEM; }else{ pCsr->isEof = 1; return sqlite3_reset(pCsr->pStmt); @@ -425,13 +462,17 @@ statNextRestart: while( p->iCellnCell ){ StatCell *pCell = &p->aCell[p->iCell]; if( pCell->iOvflnOvfl ){ - int nUsable = sqlite3BtreeGetPageSize(pBt)-sqlite3BtreeGetReserve(pBt); + int nUsable; + sqlite3BtreeEnter(pBt); + nUsable = sqlite3BtreeGetPageSize(pBt) - + sqlite3BtreeGetReserveNoMutex(pBt); + sqlite3BtreeLeave(pBt); pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); pCsr->iPageno = pCell->aOvfl[pCell->iOvfl]; pCsr->zPagetype = "overflow"; pCsr->nCell = 0; pCsr->nMxPayload = 0; - pCsr->zPath = sqlite3_mprintf( + pCsr->zPath = z = sqlite3_mprintf( "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl ); if( pCell->iOvflnOvfl-1 ){ @@ -443,7 +484,7 @@ statNextRestart: } pCell->iOvfl++; statSizeAndOffset(pCsr); - return SQLITE_OK; + return z==0 ? SQLITE_NOMEM : SQLITE_OK; } if( p->iRightChildPg ) break; p->iCell++; @@ -465,8 +506,9 @@ statNextRestart: } rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg); p[1].iCell = 0; - p[1].zPath = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); + p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell); p->iCell++; + if( z==0 ) rc = SQLITE_NOMEM; } @@ -479,31 +521,34 @@ statNextRestart: pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0); pCsr->iPageno = p->iPgno; - statDecodePage(pBt, p); - statSizeAndOffset(pCsr); + rc = statDecodePage(pBt, p); + if( rc==SQLITE_OK ){ + statSizeAndOffset(pCsr); - switch( p->flags ){ - case 0x05: /* table internal */ - case 0x02: /* index internal */ - pCsr->zPagetype = "internal"; - break; - case 0x0D: /* table leaf */ - case 0x0A: /* index leaf */ - pCsr->zPagetype = "leaf"; - break; - default: - pCsr->zPagetype = "corrupted"; - break; + switch( p->flags ){ + case 0x05: /* table internal */ + case 0x02: /* index internal */ + pCsr->zPagetype = "internal"; + break; + case 0x0D: /* table leaf */ + case 0x0A: /* index leaf */ + pCsr->zPagetype = "leaf"; + break; + default: + pCsr->zPagetype = "corrupted"; + break; + } + pCsr->nCell = p->nCell; + pCsr->nUnused = p->nUnused; + pCsr->nMxPayload = p->nMxPayload; + pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath); + if( z==0 ) rc = SQLITE_NOMEM; + nPayload = 0; + for(i=0; inCell; i++){ + nPayload += p->aCell[i].nLocal; + } + pCsr->nPayload = nPayload; } - pCsr->nCell = p->nCell; - pCsr->nUnused = p->nUnused; - pCsr->nMxPayload = p->nMxPayload; - pCsr->zPath = sqlite3_mprintf("%s", p->zPath); - nPayload = 0; - for(i=0; inCell; i++){ - nPayload += p->aCell[i].nLocal; - } - pCsr->nPayload = nPayload; } return rc; @@ -533,7 +578,7 @@ static int statColumn( StatCursor *pCsr = (StatCursor *)pCursor; switch( i ){ case 0: /* name */ - sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_STATIC); + sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT); break; case 1: /* path */ sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT); @@ -559,7 +604,8 @@ static int statColumn( case 8: /* pgoffset */ sqlite3_result_int64(ctx, pCsr->iOffset); break; - case 9: /* pgsize */ + default: /* pgsize */ + assert( i==9 ); sqlite3_result_int(ctx, pCsr->szPage); break; } @@ -572,6 +618,9 @@ static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ return SQLITE_OK; } +/* +** Invoke this routine to register the "dbstat" virtual table module +*/ int sqlite3_dbstat_register(sqlite3 *db){ static sqlite3_module dbstat_module = { 0, /* iVersion */ @@ -595,46 +644,6 @@ int sqlite3_dbstat_register(sqlite3 *db){ 0, /* xFindMethod */ 0, /* xRename */ }; - sqlite3_create_module(db, "dbstat", &dbstat_module, 0); - return SQLITE_OK; + return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); } - -#endif - -#if defined(SQLITE_TEST) || TCLSH==2 -#include - -static int test_dbstat( - void *clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifdef SQLITE_OMIT_VIRTUALTABLE - Tcl_AppendResult(interp, "dbstat not available because of " - "SQLITE_OMIT_VIRTUALTABLE", (void*)0); - return TCL_ERROR; -#else - struct SqliteDb { sqlite3 *db; }; - char *zDb; - Tcl_CmdInfo cmdInfo; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "DB"); - return TCL_ERROR; - } - - zDb = Tcl_GetString(objv[1]); - if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ - sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db; - sqlite3_dbstat_register(db); - } - return TCL_OK; -#endif -} - -int SqlitetestStat_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "register_dbstat_vtab", test_dbstat, 0, 0); - return TCL_OK; -} -#endif /* if defined(SQLITE_TEST) || TCLSH==2 */ +#endif /* SQLITE_ENABLE_DBSTAT_VTAB */ diff --git a/src/delete.c b/src/delete.c index 011fb80..ef6aace 100644 --- a/src/delete.c +++ b/src/delete.c @@ -189,7 +189,7 @@ Expr *sqlite3LimitWhere( pInClause->x.pSelect = pSelect; pInClause->flags |= EP_xIsSelect; - sqlite3ExprSetHeight(pParse, pInClause); + sqlite3ExprSetHeightAndFlags(pParse, pInClause); return pInClause; /* something went wrong. clean up anything allocated. */ diff --git a/src/expr.c b/src/expr.c index 32adedf..7e27ba9 100644 --- a/src/expr.c +++ b/src/expr.c @@ -69,10 +69,11 @@ char sqlite3ExprAffinity(Expr *pExpr){ Expr *sqlite3ExprAddCollateToken( Parse *pParse, /* Parsing context */ Expr *pExpr, /* Add the "COLLATE" clause to this expression */ - const Token *pCollName /* Name of collating sequence */ + const Token *pCollName, /* Name of collating sequence */ + int dequote /* True to dequote pCollName */ ){ if( pCollName->n>0 ){ - Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote); if( pNew ){ pNew->pLeft = pExpr; pNew->flags |= EP_Collate|EP_Skip; @@ -86,7 +87,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ assert( zC!=0 ); s.z = zC; s.n = sqlite3Strlen30(s.z); - return sqlite3ExprAddCollateToken(pParse, pExpr, &s); + return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0); } /* @@ -132,9 +133,9 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); break; } - if( p->pTab!=0 - && (op==TK_AGG_COLUMN || op==TK_COLUMN + if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER) + && p->pTab!=0 ){ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ @@ -146,10 +147,25 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ break; } if( p->flags & EP_Collate ){ - if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ + if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ - p = p->pRight; + Expr *pNext = p->pRight; + /* The Expr.x union is never used at the same time as Expr.pRight */ + assert( p->x.pList==0 || p->pRight==0 ); + /* p->flags holds EP_Collate and p->pLeft->flags does not. And + ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at + ** least one EP_Collate. Thus the following two ALWAYS. */ + if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){ + int i; + for(i=0; ALWAYS(ix.pList->nExpr); i++){ + if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ + pNext = p->x.pList->a[i].pExpr; + break; + } + } + } + p = pNext; } }else{ break; @@ -355,6 +371,9 @@ static void heightOfSelect(Select *p, int *pnHeight){ ** Expr.pSelect member has a height of 1. Any other expression ** has a height equal to the maximum height of any other ** referenced Expr plus one. +** +** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, +** if appropriate. */ static void exprSetHeight(Expr *p){ int nHeight = 0; @@ -362,8 +381,9 @@ static void exprSetHeight(Expr *p){ heightOfExpr(p->pRight, &nHeight); if( ExprHasProperty(p, EP_xIsSelect) ){ heightOfSelect(p->x.pSelect, &nHeight); - }else{ + }else if( p->x.pList ){ heightOfExprList(p->x.pList, &nHeight); + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); } p->nHeight = nHeight + 1; } @@ -372,8 +392,12 @@ static void exprSetHeight(Expr *p){ ** Set the Expr.nHeight variable using the exprSetHeight() function. If ** the height is greater than the maximum allowed expression depth, ** leave an error in pParse. +** +** Also propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. */ -void sqlite3ExprSetHeight(Parse *pParse, Expr *p){ +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + if( pParse->nErr ) return; exprSetHeight(p); sqlite3ExprCheckHeight(pParse, p->nHeight); } @@ -387,8 +411,17 @@ int sqlite3SelectExprHeight(Select *p){ heightOfSelect(p, &nHeight); return nHeight; } -#else - #define exprSetHeight(y) +#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ +/* +** Propagate all EP_Propagate flags from the Expr.x.pList into +** Expr.flags. +*/ +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ + if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ + p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); + } +} +#define exprSetHeight(y) #endif /* SQLITE_MAX_EXPR_DEPTH>0 */ /* @@ -490,11 +523,11 @@ void sqlite3ExprAttachSubtrees( }else{ if( pRight ){ pRoot->pRight = pRight; - pRoot->flags |= EP_Collate & pRight->flags; + pRoot->flags |= EP_Propagate & pRight->flags; } if( pLeft ){ pRoot->pLeft = pLeft; - pRoot->flags |= EP_Collate & pLeft->flags; + pRoot->flags |= EP_Propagate & pLeft->flags; } exprSetHeight(pRoot); } @@ -594,7 +627,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ } pNew->x.pList = pList; assert( !ExprHasProperty(pNew, EP_xIsSelect) ); - sqlite3ExprSetHeight(pParse, pNew); + sqlite3ExprSetHeightAndFlags(pParse, pNew); return pNew; } @@ -1209,6 +1242,22 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ sqlite3DbFree(db, pList); } +/* +** Return the bitwise-OR of all Expr.flags fields in the given +** ExprList. +*/ +u32 sqlite3ExprListFlags(const ExprList *pList){ + int i; + u32 m = 0; + if( pList ){ + for(i=0; inExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + if( ALWAYS(pExpr) ) m |= pExpr->flags; + } + } + return m; +} + /* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The @@ -1249,7 +1298,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ ** and either pWalker->eCode==4 or 5 or the function has the ** SQLITE_FUNC_CONST flag. */ case TK_FUNCTION: - if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_Constant) ){ + if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){ return WRC_Continue; }else{ pWalker->eCode = 0; @@ -1643,7 +1692,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ ** ephemeral table. */ p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); - if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){ + if( pParse->nErr==0 && isCandidateForInOpt(p) ){ sqlite3 *db = pParse->db; /* Database connection */ Table *pTab; /* Table . */ Expr *pExpr; /* Expression */ @@ -1968,6 +2017,7 @@ int sqlite3CodeSubselect( pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[1]); pSel->iLimit = 0; + pSel->selFlags &= ~SF_MultiValue; if( sqlite3Select(pParse, pSel, &dest) ){ return 0; } @@ -2256,7 +2306,8 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ int idxLru; struct yColCache *p; - assert( iReg>0 ); /* Register numbers are always positive */ + /* Unless an error has occurred, register numbers are always positive. */ + assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed ); assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ /* The SQLITE_ColumnCache flag disables the column cache. This is used @@ -3332,7 +3383,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ break; } case TK_ID: { - sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken); + sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken); break; } #ifndef SQLITE_OMIT_CAST @@ -3967,7 +4018,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2; if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; - if( ALWAYS((combinedFlags & EP_Reduced)==0) ){ + if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ if( pA->iColumn!=pB->iColumn ) return 2; if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; diff --git a/src/fkey.c b/src/fkey.c index fa148ba..09513e4 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -1184,7 +1184,8 @@ static Trigger *fkActionTrigger( iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iFromCol>=0 ); - tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid"; + assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKeynCol) ); + tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName; tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName; tToCol.n = sqlite3Strlen30(tToCol.z); @@ -1196,10 +1197,10 @@ static Trigger *fkActionTrigger( ** parent table are used for the comparison. */ pEq = sqlite3PExpr(pParse, TK_EQ, sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) + sqlite3ExprAlloc(db, TK_ID, &tOld, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) , 0), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol) + sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0) , 0); pWhere = sqlite3ExprAnd(db, pWhere, pEq); @@ -1211,12 +1212,12 @@ static Trigger *fkActionTrigger( if( pChanges ){ pEq = sqlite3PExpr(pParse, TK_IS, sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), + sqlite3ExprAlloc(db, TK_ID, &tOld, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), 0), sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol), + sqlite3ExprAlloc(db, TK_ID, &tNew, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0), 0), 0); pWhen = sqlite3ExprAnd(db, pWhen, pEq); @@ -1226,8 +1227,8 @@ static Trigger *fkActionTrigger( Expr *pNew; if( action==OE_Cascade ){ pNew = sqlite3PExpr(pParse, TK_DOT, - sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew), - sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol) + sqlite3ExprAlloc(db, TK_ID, &tNew, 0), + sqlite3ExprAlloc(db, TK_ID, &tToCol, 0) , 0); }else if( action==OE_SetDflt ){ Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt; @@ -1274,13 +1275,12 @@ static Trigger *fkActionTrigger( pTrigger = (Trigger *)sqlite3DbMallocZero(db, sizeof(Trigger) + /* struct Trigger */ sizeof(TriggerStep) + /* Single step in trigger program */ - nFrom + 1 /* Space for pStep->target.z */ + nFrom + 1 /* Space for pStep->zTarget */ ); if( pTrigger ){ pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1]; - pStep->target.z = (char *)&pStep[1]; - pStep->target.n = nFrom; - memcpy((char *)pStep->target.z, zFrom, nFrom); + pStep->zTarget = (char *)&pStep[1]; + memcpy((char *)pStep->zTarget, zFrom, nFrom); pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE); diff --git a/src/func.c b/src/func.c index a057993..62abf13 100644 --- a/src/func.c +++ b/src/func.c @@ -22,7 +22,9 @@ ** Return the collating function associated with a function. */ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ - VdbeOp *pOp = &context->pVdbe->aOp[context->iOp-1]; + VdbeOp *pOp; + assert( context->pVdbe!=0 ); + pOp = &context->pVdbe->aOp[context->iOp-1]; assert( pOp->opcode==OP_CollSeq ); assert( pOp->p4type==P4_COLLSEQ ); return pOp->p4.pColl; @@ -230,13 +232,13 @@ static void printfFunc( StrAccum str; const char *zFormat; int n; + sqlite3 *db = sqlite3_context_db_handle(context); if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){ x.nArg = argc-1; x.nUsed = 0; x.apArg = argv+1; - sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH); - str.db = sqlite3_context_db_handle(context); + sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x); n = str.nChar; sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, @@ -291,6 +293,14 @@ static void substrFunc( } } } +#ifdef SQLITE_SUBSTR_COMPATIBILITY + /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as + ** as substr(X,1,N) - it returns the first N characters of X. This + ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8] + ** from 2009-02-02 for compatibility of applications that exploited the + ** old buggy behavior. */ + if( p1==0 ) p1 = 1; /* */ +#endif if( argc==3 ){ p2 = sqlite3_value_int(argv[2]); if( p2<0 ){ @@ -378,7 +388,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ #endif /* -** Allocate nByte bytes of space using sqlite3_malloc(). If the +** Allocate nByte bytes of space using sqlite3Malloc(). If the ** allocation fails, call sqlite3_result_error_nomem() to notify ** the database handle that malloc() has failed and return NULL. ** If nByte is larger than the maximum string or blob length, then @@ -1047,7 +1057,7 @@ static void charFunc( ){ unsigned char *z, *zOut; int i; - zOut = z = sqlite3_malloc( argc*4+1 ); + zOut = z = sqlite3_malloc64( argc*4+1 ); if( z==0 ){ sqlite3_result_error_nomem(context); return; @@ -1195,7 +1205,7 @@ static void replaceFunc( return; } zOld = zOut; - zOut = sqlite3_realloc(zOut, (int)nOut); + zOut = sqlite3_realloc64(zOut, (int)nOut); if( zOut==0 ){ sqlite3_result_error_nomem(context); sqlite3_free(zOld); @@ -1557,8 +1567,7 @@ static void groupConcatStep( if( pAccum ){ sqlite3 *db = sqlite3_context_db_handle(context); - int firstTerm = pAccum->useMalloc==0; - pAccum->useMalloc = 2; + int firstTerm = pAccum->mxAlloc==0; pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; if( !firstTerm ){ if( argc==2 ){ @@ -1642,6 +1651,11 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ ** then set aWc[0] through aWc[2] to the wildcard characters and ** return TRUE. If the function is not a LIKE-style function then ** return FALSE. +** +** *pIsNocase is set to true if uppercase and lowercase are equivalent for +** the function (default for LIKE). If the function makes the distinction +** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to +** false. */ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ FuncDef *pDef; diff --git a/src/global.c b/src/global.c index c7043bb..61450b3 100644 --- a/src/global.c +++ b/src/global.c @@ -46,16 +46,16 @@ const unsigned char sqlite3UpperToLower[] = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */ - 96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */ - 112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */ + 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */ + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */ - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */ + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */ 160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */ 192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */ 208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */ - 224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */ - 239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */ + 224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */ + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */ #endif }; diff --git a/src/insert.c b/src/insert.c index a5c3f3e..c794ae4 100644 --- a/src/insert.c +++ b/src/insert.c @@ -342,20 +342,23 @@ static int xferOptimization( /* ** This routine is called to handle SQL of the following forms: ** -** insert into TABLE (IDLIST) values(EXPRLIST) +** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),... ** insert into TABLE (IDLIST) select +** insert into TABLE (IDLIST) default values ** ** The IDLIST following the table name is always optional. If omitted, -** then a list of all columns for the table is substituted. The IDLIST -** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted. +** then a list of all (non-hidden) columns for the table is substituted. +** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST +** is omitted. ** -** The pList parameter holds EXPRLIST in the first form of the INSERT -** statement above, and pSelect is NULL. For the second form, pList is -** NULL and pSelect is a pointer to the select statement used to generate -** data for the insert. +** For the pSelect parameter holds the values to be inserted for the +** first two forms shown above. A VALUES clause is really just short-hand +** for a SELECT statement that omits the FROM clause and everything else +** that follows. If the pSelect parameter is NULL, that means that the +** DEFAULT VALUES form of the INSERT statement is intended. ** ** The code generated follows one of four templates. For a simple -** insert with data coming from a VALUES clause, the code executes +** insert with data coming from a single-row VALUES clause, the code executes ** once straight down through. Pseudo-code follows (we call this ** the "1st template"): ** @@ -462,7 +465,7 @@ void sqlite3Insert( u8 useTempTable = 0; /* Store SELECT results in intermediate table */ u8 appendFlag = 0; /* True if the insert is likely to be an append */ u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */ - u8 bIdListInOrder = 1; /* True if IDLIST is in table order */ + u8 bIdListInOrder; /* True if IDLIST is in table order */ ExprList *pList = 0; /* List of VALUES() to be inserted */ /* Register allocations */ @@ -487,8 +490,8 @@ void sqlite3Insert( } /* If the Select object is really just a simple VALUES() list with a - ** single row values (the common case) then keep that one row of values - ** and go ahead and discard the Select object + ** single row (the common case) then keep that one row of values + ** and discard the other (unused) parts of the pSelect object */ if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){ pList = pSelect->pEList; @@ -596,6 +599,7 @@ void sqlite3Insert( ** is appears in the original table. (The index of the INTEGER ** PRIMARY KEY in the original table is pTab->iPKey.) */ + bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0; if( pColumn ){ for(i=0; inId; i++){ pColumn->a[i].idx = -1; @@ -631,7 +635,8 @@ void sqlite3Insert( ** co-routine is the common header to the 3rd and 4th templates. */ if( pSelect ){ - /* Data is coming from a SELECT. Generate a co-routine to run the SELECT */ + /* Data is coming from a SELECT or from a multi-row VALUES clause. + ** Generate a co-routine to run the SELECT. */ int regYield; /* Register holding co-routine entry-point */ int addrTop; /* Top of the co-routine */ int rc; /* Result code */ @@ -644,8 +649,7 @@ void sqlite3Insert( dest.nSdst = pTab->nCol; rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; - assert( pParse->nErr==0 || rc ); - if( rc || db->mallocFailed ) goto insert_cleanup; + if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); @@ -693,8 +697,8 @@ void sqlite3Insert( sqlite3ReleaseTempReg(pParse, regTempRowid); } }else{ - /* This is the case if the data for the INSERT is coming from a VALUES - ** clause + /* This is the case if the data for the INSERT is coming from a + ** single-row VALUES clause */ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); @@ -1765,6 +1769,7 @@ static int xferOptimization( int onError, /* How to handle constraint errors */ int iDbDest /* The database of pDest */ ){ + sqlite3 *db = pParse->db; ExprList *pEList; /* The result set of the SELECT */ Table *pSrc; /* The table in the FROM clause of SELECT */ Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ @@ -1912,11 +1917,11 @@ static int xferOptimization( ** the extra complication to make this rule less restrictive is probably ** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e] */ - if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ + if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){ return 0; } #endif - if( (pParse->db->flags & SQLITE_CountRows)!=0 ){ + if( (db->flags & SQLITE_CountRows)!=0 ){ return 0; /* xfer opt does not play well with PRAGMA count_changes */ } @@ -1927,7 +1932,7 @@ static int xferOptimization( #ifdef SQLITE_TEST sqlite3_xferopt_count++; #endif - iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); + iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; @@ -1937,14 +1942,18 @@ static int xferOptimization( regRowid = sqlite3GetTempReg(pParse); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); assert( HasRowid(pDest) || destHasUniqueIdx ); - if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ + if( (db->flags & SQLITE_Vacuum)==0 && ( + (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */ || destHasUniqueIdx /* (2) */ || (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */ - ){ + )){ /* In some circumstances, we are able to run the xfer optimization - ** only if the destination table is initially empty. This code makes - ** that determination. Conditions under which the destination must - ** be empty: + ** only if the destination table is initially empty. Unless the + ** SQLITE_Vacuum flag is set, this block generates code to make + ** that determination. If SQLITE_Vacuum is set, then the destination + ** table is always empty. + ** + ** Conditions under which the destination must be empty: ** ** (1) There is no INTEGER PRIMARY KEY but there are indices. ** (If the destination is not initially empty, the rowid fields @@ -1987,6 +1996,7 @@ static int xferOptimization( sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName); } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + u8 useSeekResult = 0; for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } @@ -2000,7 +2010,33 @@ static int xferOptimization( VdbeComment((v, "%s", pDestIdx->zName)); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); + if( db->flags & SQLITE_Vacuum ){ + /* This INSERT command is part of a VACUUM operation, which guarantees + ** that the destination table is empty. If all indexed columns use + ** collation sequence BINARY, then it can also be assumed that the + ** index will be populated by inserting keys in strictly sorted + ** order. In this case, instead of seeking within the b-tree as part + ** of every OP_IdxInsert opcode, an OP_Last is added before the + ** OP_IdxInsert to seek to the point within the b-tree where each key + ** should be inserted. This is faster. + ** + ** If any of the indexed columns use a collation sequence other than + ** BINARY, this optimization is disabled. This is because the user + ** might change the definition of a collation sequence and then run + ** a VACUUM command. In that case keys may not be written in strictly + ** sorted order. */ + for(i=0; inColumn; i++){ + char *zColl = pSrcIdx->azColl[i]; + assert( zColl!=0 ); + if( sqlite3_stricmp("BINARY", zColl) ) break; + } + if( i==pSrcIdx->nColumn ){ + useSeekResult = OPFLAG_USESEEKRESULT; + sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1); + } + } sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); + sqlite3VdbeChangeP5(v, useSeekResult); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); diff --git a/src/loadext.c b/src/loadext.c index 7b39ff1..5a2b9d2 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -430,7 +430,7 @@ static int sqlite3LoadExtension( const char *zEntry; char *zAltEntry = 0; void **aHandle; - int nMsg = 300 + sqlite3Strlen30(zFile); + u64 nMsg = 300 + sqlite3Strlen30(zFile); int ii; /* Shared library endings to try if zFile cannot be loaded as written */ @@ -473,7 +473,7 @@ static int sqlite3LoadExtension( #endif if( handle==0 ){ if( pzErrMsg ){ - *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); + *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "unable to open shared library [%s]", zFile); @@ -499,7 +499,7 @@ static int sqlite3LoadExtension( if( xInit==0 && zProc==0 ){ int iFile, iEntry, c; int ncFile = sqlite3Strlen30(zFile); - zAltEntry = sqlite3_malloc(ncFile+30); + zAltEntry = sqlite3_malloc64(ncFile+30); if( zAltEntry==0 ){ sqlite3OsDlClose(pVfs, handle); return SQLITE_NOMEM; @@ -521,7 +521,7 @@ static int sqlite3LoadExtension( if( xInit==0 ){ if( pzErrMsg ){ nMsg += sqlite3Strlen30(zEntry); - *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg); + *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg); if( zErrmsg ){ sqlite3_snprintf(nMsg, zErrmsg, "no entry point [%s] in shared library [%s]", zEntry, zFile); @@ -620,7 +620,7 @@ static const sqlite3_api_routines sqlite3Apis = { 0 }; */ typedef struct sqlite3AutoExtList sqlite3AutoExtList; static SQLITE_WSD struct sqlite3AutoExtList { - int nExt; /* Number of entries in aExt[] */ + u32 nExt; /* Number of entries in aExt[] */ void (**aExt)(void); /* Pointers to the extension init functions */ } sqlite3Autoext = { 0, 0 }; @@ -653,7 +653,7 @@ int sqlite3_auto_extension(void (*xInit)(void)){ }else #endif { - int i; + u32 i; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif @@ -663,9 +663,9 @@ int sqlite3_auto_extension(void (*xInit)(void)){ if( wsdAutoext.aExt[i]==xInit ) break; } if( i==wsdAutoext.nExt ){ - int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]); + u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]); void (**aNew)(void); - aNew = sqlite3_realloc(wsdAutoext.aExt, nByte); + aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte); if( aNew==0 ){ rc = SQLITE_NOMEM; }else{ @@ -697,7 +697,7 @@ int sqlite3_cancel_auto_extension(void (*xInit)(void)){ int n = 0; wsdAutoextInit; sqlite3_mutex_enter(mutex); - for(i=wsdAutoext.nExt-1; i>=0; i--){ + for(i=(int)wsdAutoext.nExt-1; i>=0; i--){ if( wsdAutoext.aExt[i]==xInit ){ wsdAutoext.nExt--; wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt]; @@ -735,7 +735,7 @@ void sqlite3_reset_auto_extension(void){ ** If anything goes wrong, set an error in the database connection. */ void sqlite3AutoLoadExtensions(sqlite3 *db){ - int i; + u32 i; int go = 1; int rc; int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); diff --git a/src/main.c b/src/main.c index 5aa37fa..cc819c3 100644 --- a/src/main.c +++ b/src/main.c @@ -55,6 +55,18 @@ int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } */ int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } +/* +** When compiling the test fixture or with debugging enabled (on Win32), +** this variable being set to non-zero will cause OSTRACE macros to emit +** extra diagnostic information. +*/ +#ifdef SQLITE_HAVE_OS_TRACE +# ifndef SQLITE_DEBUG_OS_TRACE +# define SQLITE_DEBUG_OS_TRACE 0 +# endif + int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; +#endif + #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE) /* ** If the following function pointer is not NULL and if @@ -62,7 +74,7 @@ int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } ** I/O active are written using this function. These messages ** are intended for debugging activity only. */ -/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0; +SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0; #endif /* @@ -128,6 +140,11 @@ int sqlite3_initialize(void){ } #endif + /* If the following assert() fails on some obscure processor/compiler + ** combination, the work-around is to set the correct pointer + ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */ + assert( SQLITE_PTRSIZE==sizeof(char*) ); + /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end @@ -340,26 +357,28 @@ int sqlite3_config(int op, ...){ */ #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */ case SQLITE_CONFIG_SINGLETHREAD: { - /* Disable all mutexing */ - sqlite3GlobalConfig.bCoreMutex = 0; - sqlite3GlobalConfig.bFullMutex = 0; + /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to + ** Single-thread. */ + sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */ + sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */ case SQLITE_CONFIG_MULTITHREAD: { - /* Disable mutexing of database connections */ - /* Enable mutexing of core data structures */ - sqlite3GlobalConfig.bCoreMutex = 1; - sqlite3GlobalConfig.bFullMutex = 0; + /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to + ** Multi-thread. */ + sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ + sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */ break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */ case SQLITE_CONFIG_SERIALIZED: { - /* Enable all mutexing */ - sqlite3GlobalConfig.bCoreMutex = 1; - sqlite3GlobalConfig.bFullMutex = 1; + /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to + ** Serialized. */ + sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ + sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */ break; } #endif @@ -471,7 +490,8 @@ int sqlite3_config(int op, ...){ case SQLITE_CONFIG_HEAP: { /* EVIDENCE-OF: R-19854-42126 There are three arguments to ** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the - ** number of bytes in the memory buffer, and the minimum allocation size. */ + ** number of bytes in the memory buffer, and the minimum allocation size. + */ sqlite3GlobalConfig.pHeap = va_arg(ap, void*); sqlite3GlobalConfig.nHeap = va_arg(ap, int); sqlite3GlobalConfig.mnReq = va_arg(ap, int); @@ -576,7 +596,9 @@ int sqlite3_config(int op, ...){ ** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE ** compile-time option. */ - if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ) mxMmap = SQLITE_MAX_MMAP_SIZE; + if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){ + mxMmap = SQLITE_MAX_MMAP_SIZE; + } if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE; if( szMmap>mxMmap) szMmap = mxMmap; sqlite3GlobalConfig.mxMmap = mxMmap; @@ -1184,7 +1206,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ ** Return a static string containing the name corresponding to the error code ** specified in the argument. */ -#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST) +#if defined(SQLITE_NEED_ERR_NAME) const char *sqlite3ErrName(int rc){ const char *zName = 0; int i, origRc = rc; @@ -1414,7 +1436,7 @@ int sqlite3_busy_handler( void *pArg ){ #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE; + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); db->busyHandler.xFunc = xBusy; @@ -2409,18 +2431,30 @@ int sqlite3ParseUri( int eState; /* Parser state when parsing URI */ int iIn; /* Input character index */ int iOut = 0; /* Output character index */ - int nByte = nUri+2; /* Bytes of space to allocate */ + u64 nByte = nUri+2; /* Bytes of space to allocate */ /* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen ** method that there may be extra parameters following the file-name. */ flags |= SQLITE_OPEN_URI; for(iIn=0; iInmallocFailed && rc==SQLITE_OK){ + int sqlite3_dbstat_register(sqlite3*); + rc = sqlite3_dbstat_register(db); + } +#endif + /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. @@ -2860,7 +2904,8 @@ static int openDatabase( opendb_out: sqlite3_free(zOpen); if( db ){ - assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); + assert( db->mutex!=0 || isThreadsafe==0 + || sqlite3GlobalConfig.bFullMutex==0 ); sqlite3_mutex_leave(db->mutex); } rc = sqlite3_errcode(db); @@ -3142,13 +3187,19 @@ int sqlite3_table_column_metadata( Table *pTab = 0; Column *pCol = 0; int iCol = 0; - char const *zDataType = 0; char const *zCollSeq = 0; int notnull = 0; int primarykey = 0; int autoinc = 0; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + /* Ensure the database schema has been loaded */ sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); @@ -3295,7 +3346,7 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ sqlite3BtreeLeave(pBtree); } sqlite3_mutex_leave(db->mutex); - return rc; + return rc; } /* @@ -3598,6 +3649,35 @@ int sqlite3_test_control(int op, ...){ if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR; break; } + + /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum); + ** + ** This test control is used to create imposter tables. "db" is a pointer + ** to the database connection. dbName is the database name (ex: "main" or + ** "temp") which will receive the imposter. "onOff" turns imposter mode on + ** or off. "tnum" is the root page of the b-tree to which the imposter + ** table should connect. + ** + ** Enable imposter mode only when the schema has already been parsed. Then + ** run a single CREATE TABLE statement to construct the imposter table in + ** the parsed schema. Then turn imposter mode back off again. + ** + ** If onOff==0 and tnum>0 then reset the schema for all databases, causing + ** the schema to be reparsed the next time it is needed. This has the + ** effect of erasing all imposter tables. + */ + case SQLITE_TESTCTRL_IMPOSTER: { + sqlite3 *db = va_arg(ap, sqlite3*); + sqlite3_mutex_enter(db->mutex); + db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); + db->init.busy = db->init.imposterTable = va_arg(ap,int); + db->init.newTnum = va_arg(ap,int); + if( db->init.busy==0 && db->init.newTnum>0 ){ + sqlite3ResetAllSchemasOfConnection(db); + } + sqlite3_mutex_leave(db->mutex); + break; + } } va_end(ap); #endif /* SQLITE_OMIT_BUILTIN_TEST */ diff --git a/src/malloc.c b/src/malloc.c index 4960f91..f06e27d 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -75,6 +75,13 @@ static SQLITE_WSD struct Mem0Global { #define mem0 GLOBAL(struct Mem0Global, mem0) +/* +** Return the memory allocator mutex. sqlite3_status() needs it. +*/ +sqlite3_mutex *sqlite3MallocMutex(void){ + return mem0.mutex; +} + /* ** This routine runs when the memory allocator sees that the ** total memory allocation is about to exceed the soft heap @@ -97,7 +104,7 @@ static int sqlite3MemoryAlarm( void *pArg, sqlite3_int64 iThreshold ){ - int nUsed; + sqlite3_int64 nUsed; sqlite3_mutex_enter(mem0.mutex); mem0.alarmCallback = xCallback; mem0.alarmArg = pArg; @@ -155,6 +162,7 @@ void sqlite3_soft_heap_limit(int n){ ** Initialize the memory allocation subsystem. */ int sqlite3MallocInit(void){ + int rc; if( sqlite3GlobalConfig.m.xMalloc==0 ){ sqlite3MemSetDefault(); } @@ -190,7 +198,9 @@ int sqlite3MallocInit(void){ sqlite3GlobalConfig.szPage = 0; sqlite3GlobalConfig.nPage = 0; } - return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); + rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); + if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0)); + return rc; } /* @@ -266,7 +276,7 @@ static int mallocWithAlarm(int n, void **pp){ nFull = sqlite3GlobalConfig.m.xRoundup(n); sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n); if( mem0.alarmCallback!=0 ){ - int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); + sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); if( nUsed >= mem0.alarmThreshold - nFull ){ mem0.nearlyFull = 1; sqlite3MallocAlarm(nFull); @@ -283,8 +293,8 @@ static int mallocWithAlarm(int n, void **pp){ #endif if( p ){ nFull = sqlite3MallocSize(p); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull); - sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1); + sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull); + sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1); } *pp = p; return nFull; @@ -361,14 +371,14 @@ void *sqlite3ScratchMalloc(int n){ p = mem0.pScratchFree; mem0.pScratchFree = mem0.pScratchFree->pNext; mem0.nScratchFree--; - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); + sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1); sqlite3_mutex_leave(mem0.mutex); }else{ sqlite3_mutex_leave(mem0.mutex); p = sqlite3Malloc(n); if( sqlite3GlobalConfig.bMemstat && p ){ sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); + sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p)); sqlite3_mutex_leave(mem0.mutex); } sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); @@ -409,19 +419,19 @@ void sqlite3ScratchFree(void *p){ mem0.pScratchFree = pSlot; mem0.nScratchFree++; assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch ); - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1); + sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1); sqlite3_mutex_leave(mem0.mutex); }else{ /* Release memory back to the heap */ assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) ); - assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); if( sqlite3GlobalConfig.bMemstat ){ int iSize = sqlite3MallocSize(p); sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize); - sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); + sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize); + sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize); + sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); sqlite3GlobalConfig.m.xFree(p); sqlite3_mutex_leave(mem0.mutex); }else{ @@ -452,7 +462,7 @@ int sqlite3MallocSize(void *p){ } int sqlite3DbMallocSize(sqlite3 *db, void *p){ if( db==0 ){ - assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); return sqlite3MallocSize(p); }else{ @@ -461,13 +471,13 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){ return db->lookaside.sz; }else{ assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); return sqlite3GlobalConfig.m.xSize(p); } } } sqlite3_uint64 sqlite3_msize(void *p){ - assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p); } @@ -478,11 +488,11 @@ sqlite3_uint64 sqlite3_msize(void *p){ void sqlite3_free(void *p){ if( p==0 ) return; /* IMP: R-49053-54554 */ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); - assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) ); if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p)); - sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); + sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p)); + sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1); sqlite3GlobalConfig.m.xFree(p); sqlite3_mutex_leave(mem0.mutex); }else{ @@ -523,7 +533,7 @@ void sqlite3DbFree(sqlite3 *db, void *p){ } } assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); sqlite3_free(p); @@ -536,7 +546,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){ int nOld, nNew, nDiff; void *pNew; assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) ); - assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) ); + assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) ); if( pOld==0 ){ return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */ } @@ -570,7 +580,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){ } if( pNew ){ nNew = sqlite3MallocSize(pNew); - sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld); + sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld); } sqlite3_mutex_leave(mem0.mutex); }else{ @@ -703,7 +713,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){ } }else{ assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); - assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); + assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); pNew = sqlite3_realloc64(p, n); if( !pNew ){ diff --git a/src/msvc.h b/src/msvc.h index 4508e69..01ebf2b 100644 --- a/src/msvc.h +++ b/src/msvc.h @@ -20,6 +20,7 @@ #pragma warning(disable : 4055) #pragma warning(disable : 4100) #pragma warning(disable : 4127) +#pragma warning(disable : 4130) #pragma warning(disable : 4152) #pragma warning(disable : 4189) #pragma warning(disable : 4206) diff --git a/src/mutex_noop.c b/src/mutex_noop.c index 1a900c2..7f68aea 100644 --- a/src/mutex_noop.c +++ b/src/mutex_noop.c @@ -120,8 +120,12 @@ static sqlite3_mutex *debugMutexAlloc(int id){ break; } default: { - assert( id-2 >= 0 ); - assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) ); +#ifdef SQLITE_ENABLE_API_ARMOR + if( id-2<0 || id-2>=ArraySize(aStatic) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif pNew = &aStatic[id-2]; pNew->id = id; break; @@ -136,8 +140,13 @@ static sqlite3_mutex *debugMutexAlloc(int id){ static void debugMutexFree(sqlite3_mutex *pX){ sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX; assert( p->cnt==0 ); - assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); - sqlite3_free(p); + if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){ + sqlite3_free(p); + }else{ +#ifdef SQLITE_ENABLE_API_ARMOR + (void)SQLITE_MISUSE_BKPT; +#endif + } } /* diff --git a/src/mutex_unix.c b/src/mutex_unix.c index c936914..e08448e 100644 --- a/src/mutex_unix.c +++ b/src/mutex_unix.c @@ -40,8 +40,10 @@ */ struct sqlite3_mutex { pthread_mutex_t mutex; /* Mutex controlling the lock */ -#if SQLITE_MUTEX_NREF +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) int id; /* Mutex type */ +#endif +#if SQLITE_MUTEX_NREF volatile int nRef; /* Number of entrances */ volatile pthread_t owner; /* Thread that is within this mutex */ int trace; /* True to trace changes */ @@ -157,9 +159,6 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&p->mutex, &recursiveAttr); pthread_mutexattr_destroy(&recursiveAttr); -#endif -#if SQLITE_MUTEX_NREF - p->id = iType; #endif } break; @@ -167,9 +166,6 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ case SQLITE_MUTEX_FAST: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ -#if SQLITE_MUTEX_NREF - p->id = iType; -#endif pthread_mutex_init(&p->mutex, 0); } break; @@ -182,12 +178,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ } #endif p = &staticMutexes[iType-2]; -#if SQLITE_MUTEX_NREF - p->id = iType; -#endif break; } } +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) + if( p ) p->id = iType; +#endif return p; } @@ -199,9 +195,18 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ */ static void pthreadMutexFree(sqlite3_mutex *p){ assert( p->nRef==0 ); - assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); - pthread_mutex_destroy(&p->mutex); - sqlite3_free(p); +#if SQLITE_ENABLE_API_ARMOR + if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ) +#endif + { + pthread_mutex_destroy(&p->mutex); + sqlite3_free(p); + } +#ifdef SQLITE_ENABLE_API_ARMOR + else{ + (void)SQLITE_MISUSE_BKPT; + } +#endif } /* diff --git a/src/mutex_w32.c b/src/mutex_w32.c index a799c86..6786614 100644 --- a/src/mutex_w32.c +++ b/src/mutex_w32.c @@ -194,8 +194,8 @@ static sqlite3_mutex *winMutexAlloc(int iType){ case SQLITE_MUTEX_RECURSIVE: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ -#ifdef SQLITE_DEBUG p->id = iType; +#ifdef SQLITE_DEBUG #ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC p->trace = 1; #endif @@ -215,12 +215,9 @@ static sqlite3_mutex *winMutexAlloc(int iType){ return 0; } #endif - assert( iType-2 >= 0 ); - assert( iType-2 < ArraySize(winMutex_staticMutexes) ); - assert( winMutex_isInit==1 ); p = &winMutex_staticMutexes[iType-2]; -#ifdef SQLITE_DEBUG p->id = iType; +#ifdef SQLITE_DEBUG #ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC p->trace = 1; #endif @@ -239,13 +236,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){ */ static void winMutexFree(sqlite3_mutex *p){ assert( p ); -#ifdef SQLITE_DEBUG assert( p->nRef==0 && p->owner==0 ); - assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){ + DeleteCriticalSection(&p->mutex); + sqlite3_free(p); + }else{ +#ifdef SQLITE_ENABLE_API_ARMOR + (void)SQLITE_MISUSE_BKPT; #endif - assert( winMutex_isInit==1 ); - DeleteCriticalSection(&p->mutex); - sqlite3_free(p); + } } /* diff --git a/src/os_common.h b/src/os_common.h index f6c3e7f..d18b95a 100644 --- a/src/os_common.h +++ b/src/os_common.h @@ -29,16 +29,6 @@ # error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." #endif -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) -# ifndef SQLITE_DEBUG_OS_TRACE -# define SQLITE_DEBUG_OS_TRACE 0 -# endif - int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE; -# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X -#else -# define OSTRACE(X) -#endif - /* ** Macros for performance tracing. Normally turned off. Only works ** on i486 hardware. diff --git a/src/os_unix.c b/src/os_unix.c index ddd6a80..9ec1003 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -71,18 +71,6 @@ # endif #endif -/* -** Define the OS_VXWORKS pre-processor macro to 1 if building on -** vxworks, or 0 otherwise. -*/ -#ifndef OS_VXWORKS -# if defined(__RTP__) || defined(_WRS_KERNEL) -# define OS_VXWORKS 1 -# else -# define OS_VXWORKS 0 -# endif -#endif - /* ** standard include files. */ @@ -97,18 +85,30 @@ # include #endif -#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS +#if SQLITE_ENABLE_LOCKING_STYLE # include -# if OS_VXWORKS -# include -# include -# else -# include -# include -# endif +# include +# include #endif /* SQLITE_ENABLE_LOCKING_STYLE */ -#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS) +#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \ + (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000)) +# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \ + && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0)) +# define HAVE_GETHOSTUUID 1 +# else +# warning "gethostuuid() is disabled." +# endif +#endif + + +#if OS_VXWORKS +# include +# include +# include +#endif /* OS_VXWORKS */ + +#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE # include #endif @@ -149,6 +149,10 @@ */ #define MAX_PATHNAME 512 +/* Always cast the getpid() return type for compatibility with +** kernel modules in VxWorks. */ +#define osGetpid(X) (pid_t)getpid() + /* ** Only set the lastErrno if the error code is a real error and not ** a normal expected return code of SQLITE_BUSY or SQLITE_OK @@ -237,7 +241,7 @@ struct unixFile { ** method was called. If xOpen() is called from a different process id, ** indicating that a fork() has occurred, the PRNG will be reset. */ -static int randomnessPid = 0; +static pid_t randomnessPid = 0; /* ** Allowed values for the unixFile.ctrlFlags bitmask: @@ -254,7 +258,8 @@ static int randomnessPid = 0; #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ -#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */ +#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings issued */ +#define UNIXFILE_BLOCK 0x0200 /* Next SHM lock might block */ /* ** Include code that is common to all os_*.c files @@ -385,7 +390,7 @@ static struct unix_syscall { { "read", (sqlite3_syscall_ptr)read, 0 }, #define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent) -#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS) +#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE { "pread", (sqlite3_syscall_ptr)pread, 0 }, #else { "pread", (sqlite3_syscall_ptr)0, 0 }, @@ -402,7 +407,7 @@ static struct unix_syscall { { "write", (sqlite3_syscall_ptr)write, 0 }, #define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent) -#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS) +#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE { "pwrite", (sqlite3_syscall_ptr)pwrite, 0 }, #else { "pwrite", (sqlite3_syscall_ptr)0, 0 }, @@ -636,7 +641,7 @@ static int unixMutexHeld(void) { #endif -#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) +#ifdef SQLITE_HAVE_OS_TRACE /* ** Helper function for printing out trace information from debugging ** binaries. This returns the string representation of the supplied @@ -717,9 +722,9 @@ static int lockTrace(int fd, int op, struct flock *p){ /* ** Retry ftruncate() calls that fail due to EINTR ** -** All calls to ftruncate() within this file should be made through this wrapper. -** On the Android platform, bypassing the logic below could lead to a corrupt -** database. +** All calls to ftruncate() within this file should be made through +** this wrapper. On the Android platform, bypassing the logic below +** could lead to a corrupt database. */ static int robust_ftruncate(int h, sqlite3_int64 sz){ int rc; @@ -899,7 +904,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){ assert( zAbsoluteName[0]=='/' ); n = (int)strlen(zAbsoluteName); - pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) ); + pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) ); if( pNew==0 ) return 0; pNew->zCanonicalName = (char*)&pNew[1]; memcpy(pNew->zCanonicalName, zAbsoluteName, n+1); @@ -1178,6 +1183,14 @@ static void robust_close(unixFile *pFile, int h, int lineno){ } } +/* +** Set the pFile->lastErrno. Do this in a subroutine as that provides +** a convenient place to set a breakpoint. +*/ +static void storeLastErrno(unixFile *pFile, int error){ + pFile->lastErrno = error; +} + /* ** Close all file descriptors accumuated in the unixInodeInfo->pUnused list. */ @@ -1251,7 +1264,7 @@ static int findInodeInfo( fd = pFile->h; rc = osFstat(fd, &statbuf); if( rc!=0 ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); #ifdef EOVERFLOW if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS; #endif @@ -1272,12 +1285,12 @@ static int findInodeInfo( if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){ do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR ); if( rc!=1 ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return SQLITE_IOERR; } rc = osFstat(fd, &statbuf); if( rc!=0 ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return SQLITE_IOERR; } } @@ -1295,7 +1308,7 @@ static int findInodeInfo( pInode = pInode->pNext; } if( pInode==0 ){ - pInode = sqlite3_malloc( sizeof(*pInode) ); + pInode = sqlite3_malloc64( sizeof(*pInode) ); if( pInode==0 ){ return SQLITE_NOMEM; } @@ -1400,7 +1413,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ lock.l_type = F_WRLCK; if( osFcntl(pFile->h, F_GETLK, &lock) ){ rc = SQLITE_IOERR_CHECKRESERVEDLOCK; - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); } else if( lock.l_type!=F_UNLCK ){ reserved = 1; } @@ -1533,7 +1546,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){ assert( pFile ); OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h, azFileLock(eFileLock), azFileLock(pFile->eFileLock), - azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid())); + azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared, + osGetpid(0))); /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the end_lock: exit path, as @@ -1600,7 +1614,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( rc!=SQLITE_BUSY ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_lock; } @@ -1635,7 +1649,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ if( rc ){ if( rc!=SQLITE_BUSY ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_lock; }else{ @@ -1668,7 +1682,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( rc!=SQLITE_BUSY ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } } } @@ -1741,7 +1755,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock, pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, - getpid())); + osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ @@ -1775,7 +1789,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ ** 4: [RRRR.] */ if( eFileLock==SHARED_LOCK ){ - #if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE (void)handleNFSUnlock; assert( handleNFSUnlock==0 ); @@ -1793,7 +1806,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_unlock; } @@ -1805,7 +1818,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_unlock; } @@ -1817,7 +1830,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ tErrno = errno; rc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } goto end_unlock; } @@ -1836,7 +1849,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ ** SQLITE_BUSY would confuse the upper layer (in practice it causes ** an assert to fail). */ rc = SQLITE_IOERR_RDLOCK; - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); goto end_unlock; } } @@ -1849,7 +1862,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ pInode->eFileLock = SHARED_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); goto end_unlock; } } @@ -1867,7 +1880,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ pInode->eFileLock = NO_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); pInode->eFileLock = NO_LOCK; pFile->eFileLock = NO_LOCK; } @@ -2142,7 +2155,7 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) { } else { rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } } return rc; @@ -2169,7 +2182,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock, - pFile->eFileLock, getpid())); + pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -2196,7 +2209,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) { rc = SQLITE_IOERR_UNLOCK; } if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } return rc; } @@ -2232,10 +2245,9 @@ static int dotlockClose(sqlite3_file *id) { ** still works when you do this, but concurrency is reduced since ** only a single process can be reading the database at a time. ** -** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if -** compiling for VXWORKS. +** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off */ -#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS +#if SQLITE_ENABLE_LOCKING_STYLE /* ** Retry flock() calls that fail with EINTR @@ -2283,7 +2295,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ /* unlock failed with an error */ lrc = SQLITE_IOERR_UNLOCK; if( IS_LOCK_ERROR(lrc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); rc = lrc; } } @@ -2293,7 +2305,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ /* someone else might have it reserved */ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(lrc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); rc = lrc; } } @@ -2359,7 +2371,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) { /* didn't get, must be busy */ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } } else { /* got it, set the type and return ok */ @@ -2388,7 +2400,7 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock, - pFile->eFileLock, getpid())); + pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -2449,7 +2461,7 @@ static int flockClose(sqlite3_file *id) { ** to a non-zero value otherwise *pResOut is set to zero. The return value ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ -static int semCheckReservedLock(sqlite3_file *id, int *pResOut) { +static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) { int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; @@ -2471,7 +2483,7 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) { int tErrno = errno; if( EAGAIN != tErrno ){ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK); - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } else { /* someone else has the lock when we are in NO_LOCK */ reserved = (pFile->eFileLock < SHARED_LOCK); @@ -2516,7 +2528,7 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) { ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ -static int semLock(sqlite3_file *id, int eFileLock) { +static int semXLock(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; sem_t *pSem = pFile->pInode->pSem; int rc = SQLITE_OK; @@ -2549,14 +2561,14 @@ static int semLock(sqlite3_file *id, int eFileLock) { ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ -static int semUnlock(sqlite3_file *id, int eFileLock) { +static int semXUnlock(sqlite3_file *id, int eFileLock) { unixFile *pFile = (unixFile*)id; sem_t *pSem = pFile->pInode->pSem; assert( pFile ); assert( pSem ); OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock, - pFile->eFileLock, getpid())); + pFile->eFileLock, osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ @@ -2575,7 +2587,7 @@ static int semUnlock(sqlite3_file *id, int eFileLock) { int rc, tErrno = errno; rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } return rc; } @@ -2586,10 +2598,10 @@ static int semUnlock(sqlite3_file *id, int eFileLock) { /* ** Close a file. */ -static int semClose(sqlite3_file *id) { +static int semXClose(sqlite3_file *id) { if( id ){ unixFile *pFile = (unixFile*)id; - semUnlock(id, NO_LOCK); + semXUnlock(id, NO_LOCK); assert( pFile ); unixEnterMutex(); releaseInodeInfo(pFile); @@ -2677,7 +2689,7 @@ static int afpSetLock( setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); #endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */ if( IS_LOCK_ERROR(rc) ){ - pFile->lastErrno = tErrno; + storeLastErrno(pFile, tErrno); } return rc; } else { @@ -2770,7 +2782,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ assert( pFile ); OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h, azFileLock(eFileLock), azFileLock(pFile->eFileLock), - azFileLock(pInode->eFileLock), pInode->nShared , getpid())); + azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0))); /* If there is already a lock of this type or more restrictive on the ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as @@ -2860,7 +2872,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); if( IS_LOCK_ERROR(lrc1) ) { - pFile->lastErrno = lrc1Errno; + storeLastErrno(pFile, lrc1Errno); rc = lrc1; goto afp_end_lock; } else if( IS_LOCK_ERROR(lrc2) ){ @@ -2956,7 +2968,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { assert( pFile ); OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock, pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared, - getpid())); + osGetpid(0))); assert( eFileLock<=SHARED_LOCK ); if( pFile->eFileLock<=eFileLock ){ @@ -3147,9 +3159,9 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ SimulateIOError( newOffset-- ); if( newOffset!=offset ){ if( newOffset == -1 ){ - ((unixFile*)id)->lastErrno = errno; + storeLastErrno((unixFile*)id, errno); }else{ - ((unixFile*)id)->lastErrno = 0; + storeLastErrno((unixFile*)id, 0); } return -1; } @@ -3159,7 +3171,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ if( got<0 ){ if( errno==EINTR ){ got = 1; continue; } prior = 0; - ((unixFile*)id)->lastErrno = errno; + storeLastErrno((unixFile*)id, errno); break; }else if( got>0 ){ cnt -= got; @@ -3224,7 +3236,7 @@ static int unixRead( /* lastErrno set by seekAndRead */ return SQLITE_IOERR_READ; }else{ - pFile->lastErrno = 0; /* not a system error */ + storeLastErrno(pFile, 0); /* not a system error */ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[got], 0, amt-got); return SQLITE_IOERR_SHORT_READ; @@ -3253,9 +3265,9 @@ static int seekAndWriteFd( TIMER_START; #if defined(USE_PREAD) - do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); + do{ rc = (int)osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); #elif defined(USE_PREAD64) - do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); + do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); #else do{ i64 iSeek = lseek(fd, iOff, SEEK_SET); @@ -3365,7 +3377,7 @@ static int unixWrite( /* lastErrno set by seekAndWrite */ return SQLITE_IOERR_WRITE; }else{ - pFile->lastErrno = 0; /* not a system error */ + storeLastErrno(pFile, 0); /* not a system error */ return SQLITE_FULL; } } @@ -3574,7 +3586,7 @@ static int unixSync(sqlite3_file *id, int flags){ rc = full_fsync(pFile->h, isFullsync, isDataOnly); SimulateIOError( rc=1 ); if( rc ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath); } @@ -3618,7 +3630,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){ rc = robust_ftruncate(pFile->h, nByte); if( rc ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); }else{ #ifdef SQLITE_DEBUG @@ -3658,7 +3670,7 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){ rc = osFstat(((unixFile*)id)->h, &buf); SimulateIOError( rc=1 ); if( rc!=0 ){ - ((unixFile*)id)->lastErrno = errno; + storeLastErrno((unixFile*)id, errno); return SQLITE_IOERR_FSTAT; } *pSize = buf.st_size; @@ -3694,7 +3706,9 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ i64 nSize; /* Required file size */ struct stat buf; /* Used to hold return values of fstat() */ - if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT; + if( osFstat(pFile->h, &buf) ){ + return SQLITE_IOERR_FSTAT; + } nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk; if( nSize>(i64)buf.st_size ){ @@ -3741,7 +3755,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){ int rc; if( pFile->szChunk<=0 ){ if( robust_ftruncate(pFile->h, nByte) ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); } } @@ -3779,11 +3793,15 @@ static int unixGetTempname(int nBuf, char *zBuf); static int unixFileControl(sqlite3_file *id, int op, void *pArg){ unixFile *pFile = (unixFile*)id; switch( op ){ + case SQLITE_FCNTL_WAL_BLOCK: { + /* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */ + return SQLITE_OK; + } case SQLITE_FCNTL_LOCKSTATE: { *(int*)pArg = pFile->eFileLock; return SQLITE_OK; } - case SQLITE_LAST_ERRNO: { + case SQLITE_FCNTL_LAST_ERRNO: { *(int*)pArg = pFile->lastErrno; return SQLITE_OK; } @@ -3811,7 +3829,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ return SQLITE_OK; } case SQLITE_FCNTL_TEMPFILENAME: { - char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname ); + char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname ); if( zTFile ){ unixGetTempname(pFile->pVfs->mxPathname, zTFile); *(char**)pArg = zTFile; @@ -3852,8 +3870,8 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ } #endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) - case SQLITE_SET_LOCKPROXYFILE: - case SQLITE_GET_LOCKPROXYFILE: { + case SQLITE_FCNTL_SET_LOCKPROXYFILE: + case SQLITE_FCNTL_GET_LOCKPROXYFILE: { return proxyFileControl(id,op,pArg); } #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */ @@ -3993,7 +4011,9 @@ static int unixDeviceCharacteristics(sqlite3_file *id){ ** Instead, it should be called via macro osGetpagesize(). */ static int unixGetpagesize(void){ -#if defined(_BSD_SOURCE) +#if OS_VXWORKS + return 1024; +#elif defined(_BSD_SOURCE) return getpagesize(); #else return (int)sysconf(_SC_PAGESIZE); @@ -4086,15 +4106,17 @@ struct unixShm { ** otherwise. */ static int unixShmSystemLock( - unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */ + unixFile *pFile, /* Open connection to the WAL file */ int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ int ofst, /* First byte of the locking range */ int n /* Number of bytes to lock */ ){ - struct flock f; /* The posix advisory locking structure */ - int rc = SQLITE_OK; /* Result code form fcntl() */ + unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */ + struct flock f; /* The posix advisory locking structure */ + int rc = SQLITE_OK; /* Result code form fcntl() */ /* Access to the unixShmNode object is serialized by the caller */ + pShmNode = pFile->pInode->pShmNode; assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 ); /* Shared locks never span more than one byte */ @@ -4104,6 +4126,7 @@ static int unixShmSystemLock( assert( n>=1 && nh>=0 ){ + int lkType; /* Initialize the locking parameters */ memset(&f, 0, sizeof(f)); f.l_type = lockType; @@ -4111,8 +4134,10 @@ static int unixShmSystemLock( f.l_start = ofst; f.l_len = n; - rc = osFcntl(pShmNode->h, F_SETLK, &f); + lkType = (pFile->ctrlFlags & UNIXFILE_BLOCK)!=0 ? F_SETLKW : F_SETLK; + rc = osFcntl(pShmNode->h, lkType, &f); rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; + pFile->ctrlFlags &= ~UNIXFILE_BLOCK; } /* Update the global lock state and do debug tracing */ @@ -4245,7 +4270,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ int nShmFilename; /* Size of the SHM filename in bytes */ /* Allocate space for the new unixShm object. */ - p = sqlite3_malloc( sizeof(*p) ); + p = sqlite3_malloc64( sizeof(*p) ); if( p==0 ) return SQLITE_NOMEM; memset(p, 0, sizeof(*p)); assert( pDbFd->pShm==0 ); @@ -4258,6 +4283,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ pShmNode = pInode->pShmNode; if( pShmNode==0 ){ struct stat sStat; /* fstat() info for database file */ +#ifndef SQLITE_SHM_DIRECTORY + const char *zBasePath = pDbFd->zPath; +#endif /* Call fstat() to figure out the permissions on the database file. If ** a new *-shm file is created, an attempt will be made to create it @@ -4271,9 +4299,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ #ifdef SQLITE_SHM_DIRECTORY nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31; #else - nShmFilename = 6 + (int)strlen(pDbFd->zPath); + nShmFilename = 6 + (int)strlen(zBasePath); #endif - pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename ); + pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename ); if( pShmNode==0 ){ rc = SQLITE_NOMEM; goto shm_open_err; @@ -4285,7 +4313,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x", (u32)sStat.st_ino, (u32)sStat.st_dev); #else - sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath); + sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath); sqlite3FileSuffix3(pDbFd->zPath, zShmFilename); #endif pShmNode->h = -1; @@ -4319,13 +4347,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ ** If not, truncate the file to zero length. */ rc = SQLITE_OK; - if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ + if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){ if( robust_ftruncate(pShmNode->h, 0) ){ rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename); } } if( rc==SQLITE_OK ){ - rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1); + rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1); } if( rc ) goto shm_open_err; } @@ -4483,7 +4511,7 @@ static int unixShmMap( goto shmpage_out; } }else{ - pMem = sqlite3_malloc(szRegion); + pMem = sqlite3_malloc64(szRegion); if( pMem==0 ){ rc = SQLITE_NOMEM; goto shmpage_out; @@ -4557,7 +4585,7 @@ static int unixShmLock( /* Unlock the system-level locks */ if( (mask & allMask)==0 ){ - rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n); }else{ rc = SQLITE_OK; } @@ -4585,7 +4613,7 @@ static int unixShmLock( /* Get shared locks at the system level, if necessary */ if( rc==SQLITE_OK ){ if( (allShared & mask)==0 ){ - rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n); }else{ rc = SQLITE_OK; } @@ -4610,7 +4638,7 @@ static int unixShmLock( ** also mark the local connection as being locked. */ if( rc==SQLITE_OK ){ - rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n); + rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n); if( rc==SQLITE_OK ){ assert( (p->sharedMask & mask)==0 ); p->exclMask |= mask; @@ -4619,7 +4647,7 @@ static int unixShmLock( } sqlite3_mutex_leave(pShmNode->mutex); OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", - p->id, getpid(), p->sharedMask, p->exclMask)); + p->id, osGetpid(0), p->sharedMask, p->exclMask)); return rc; } @@ -4678,7 +4706,9 @@ static int unixShmUnmap( assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename); + if( deleteFlag && pShmNode->h>=0 ){ + osUnlink(pShmNode->zFilename); + } unixShmPurge(pDbFd); } unixLeaveMutex(); @@ -4955,7 +4985,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ ** * An I/O method finder function called FINDER that returns a pointer ** to the METHOD object in the previous bullet. */ -#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK, SHMMAP) \ +#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP) \ static const sqlite3_io_methods METHOD = { \ VERSION, /* iVersion */ \ CLOSE, /* xClose */ \ @@ -5020,7 +5050,7 @@ IOMETHODS( 0 /* xShmMap method */ ) -#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS +#if SQLITE_ENABLE_LOCKING_STYLE IOMETHODS( flockIoFinder, /* Finder function name */ flockIoMethods, /* sqlite3_io_methods object name */ @@ -5038,10 +5068,10 @@ IOMETHODS( semIoFinder, /* Finder function name */ semIoMethods, /* sqlite3_io_methods object name */ 1, /* shared memory is disabled */ - semClose, /* xClose method */ - semLock, /* xLock method */ - semUnlock, /* xUnlock method */ - semCheckReservedLock, /* xCheckReservedLock method */ + semXClose, /* xClose method */ + semXLock, /* xLock method */ + semXUnlock, /* xUnlock method */ + semXCheckReservedLock, /* xCheckReservedLock method */ 0 /* xShmMap method */ ) #endif @@ -5165,15 +5195,13 @@ static const sqlite3_io_methods #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */ -#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE -/* -** This "finder" function attempts to determine the best locking strategy -** for the database file "filePath". It then returns the sqlite3_io_methods -** object that implements that strategy. -** -** This is for VXWorks only. +#if OS_VXWORKS +/* +** This "finder" function for VxWorks checks to see if posix advisory +** locking works. If it does, then that is what is used. If it does not +** work, then fallback to named semaphore locking. */ -static const sqlite3_io_methods *autolockIoFinderImpl( +static const sqlite3_io_methods *vxworksIoFinderImpl( const char *filePath, /* name of the database file */ unixFile *pNew /* the open file object */ ){ @@ -5199,9 +5227,9 @@ static const sqlite3_io_methods *autolockIoFinderImpl( } } static const sqlite3_io_methods - *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl; + *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl; -#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */ +#endif /* OS_VXWORKS */ /* ** An abstract type for a pointer to an IO method finder function: @@ -5320,7 +5348,7 @@ static int fillInUnixFile( ** the afpLockingContext. */ afpLockingContext *pCtx; - pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) ); + pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) ); if( pCtx==0 ){ rc = SQLITE_NOMEM; }else{ @@ -5350,7 +5378,7 @@ static int fillInUnixFile( int nFilename; assert( zFilename!=0 ); nFilename = (int)strlen(zFilename) + 6; - zLockFile = (char *)sqlite3_malloc(nFilename); + zLockFile = (char *)sqlite3_malloc64(nFilename); if( zLockFile==0 ){ rc = SQLITE_NOMEM; }else{ @@ -5383,7 +5411,7 @@ static int fillInUnixFile( } #endif - pNew->lastErrno = 0; + storeLastErrno(pNew, 0); #if OS_VXWORKS if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); @@ -5714,8 +5742,8 @@ static int unixOpen( ** the same instant might all reset the PRNG. But multiple resets ** are harmless. */ - if( randomnessPid!=getpid() ){ - randomnessPid = getpid(); + if( randomnessPid!=osGetpid(0) ){ + randomnessPid = osGetpid(0); sqlite3_randomness(0,0); } @@ -5727,7 +5755,7 @@ static int unixOpen( if( pUnused ){ fd = pUnused->fd; }else{ - pUnused = sqlite3_malloc(sizeof(*pUnused)); + pUnused = sqlite3_malloc64(sizeof(*pUnused)); if( !pUnused ){ return SQLITE_NOMEM; } @@ -5831,13 +5859,16 @@ static int unixOpen( #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE if( fstatfs(fd, &fsInfo) == -1 ){ - ((unixFile*)pFile)->lastErrno = errno; + storeLastErrno(p, errno); robust_close(p, fd, __LINE__); return SQLITE_IOERR_ACCESS; } if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) { ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; } + if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) { + ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS; + } #endif /* Set up appropriate ctrlFlags */ @@ -5860,19 +5891,6 @@ static int unixOpen( if( envforce!=NULL ){ useProxy = atoi(envforce)>0; }else{ - if( statfs(zPath, &fsInfo) == -1 ){ - /* In theory, the close(fd) call is sub-optimal. If the file opened - ** with fd is a database file, and there are other connections open - ** on that file that are currently holding advisory locks on it, - ** then the call to close() will cancel those locks. In practice, - ** we're assuming that statfs() doesn't fail very often. At least - ** not while other file descriptors opened by the same process on - ** the same file are working. */ - p->lastErrno = errno; - robust_close(p, fd, __LINE__); - rc = SQLITE_IOERR_ACCESS; - goto open_finished; - } useProxy = !(fsInfo.f_flags&MNT_LOCAL); } if( useProxy ){ @@ -6116,8 +6134,8 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ ** tests repeatable. */ memset(zBuf, 0, nBuf); - randomnessPid = getpid(); -#if !defined(SQLITE_TEST) + randomnessPid = osGetpid(0); +#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) { int fd, got; fd = robust_open("/dev/urandom", O_RDONLY, 0); @@ -6298,9 +6316,10 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ ** ** C APIs ** -** sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE, +** sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE, ** | ":auto:"); -** sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &); +** sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE, +** &); ** ** ** SQL pragmas @@ -6393,7 +6412,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ ** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will ** force proxy locking to be used for every database file opened, and 0 ** will force automatic proxy locking to be disabled for all database -** files (explicitly calling the SQLITE_SET_LOCKPROXYFILE pragma or +** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or ** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING). */ @@ -6414,6 +6433,7 @@ struct proxyLockingContext { char *lockProxyPath; /* Name of the proxy lock file */ char *dbPath; /* Name of the open file */ int conchHeld; /* 1 if the conch is held, -1 if lockless */ + int nFails; /* Number of conch taking failures */ void *oldLockingContext; /* Original lockingcontext to restore on close */ sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ }; @@ -6435,7 +6455,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ { if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){ OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n", - lPath, errno, getpid())); + lPath, errno, osGetpid(0))); return SQLITE_IOERR_LOCK; } len = strlcat(lPath, "sqliteplocks", maxLen); @@ -6457,7 +6477,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ } lPath[i+len]='\0'; strlcat(lPath, ":auto:", maxLen); - OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid())); + OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid(0))); return SQLITE_OK; } @@ -6484,7 +6504,7 @@ static int proxyCreateLockPath(const char *lockPath){ if( err!=EEXIST ) { OSTRACE(("CREATELOCKPATH FAILED creating %s, " "'%s' proxy lock path=%s pid=%d\n", - buf, strerror(err), lockPath, getpid())); + buf, strerror(err), lockPath, osGetpid(0))); return err; } } @@ -6493,7 +6513,7 @@ static int proxyCreateLockPath(const char *lockPath){ } buf[i] = lockPath[i]; } - OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid())); + OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid(0))); return 0; } @@ -6527,7 +6547,7 @@ static int proxyCreateUnixFile( if( pUnused ){ fd = pUnused->fd; }else{ - pUnused = sqlite3_malloc(sizeof(*pUnused)); + pUnused = sqlite3_malloc64(sizeof(*pUnused)); if( !pUnused ){ return SQLITE_NOMEM; } @@ -6560,7 +6580,7 @@ static int proxyCreateUnixFile( } } - pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew)); + pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew)); if( pNew==NULL ){ rc = SQLITE_NOMEM; goto end_create_proxy; @@ -6593,8 +6613,10 @@ int sqlite3_hostid_num = 0; #define PROXY_HOSTIDLEN 16 /* conch file host id length */ +#ifdef HAVE_GETHOSTUUID /* Not always defined in the headers as it ought to be */ extern int gethostuuid(uuid_t id, const struct timespec *wait); +#endif /* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN ** bytes of writable memory. @@ -6602,10 +6624,9 @@ extern int gethostuuid(uuid_t id, const struct timespec *wait); static int proxyGetHostID(unsigned char *pHostID, int *pError){ assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); memset(pHostID, 0, PROXY_HOSTIDLEN); -#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\ - && __MAC_OS_X_VERSION_MIN_REQUIRED<1050 +#ifdef HAVE_GETHOSTUUID { - static const struct timespec timeout = {1, 0}; /* 1 sec timeout */ + struct timespec timeout = {1, 0}; /* 1 sec timeout */ if( gethostuuid(pHostID, &timeout) ){ int err = errno; if( pError ){ @@ -6720,7 +6741,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ */ struct stat buf; if( osFstat(conchFile->h, &buf) ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return SQLITE_IOERR_LOCK; } @@ -6740,7 +6761,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ char tBuf[PROXY_MAXCONCHLEN]; int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0); if( len<0 ){ - pFile->lastErrno = errno; + storeLastErrno(pFile, errno); return SQLITE_IOERR_LOCK; } if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){ @@ -6760,7 +6781,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){ if( 0==proxyBreakConchLock(pFile, myHostID) ){ rc = SQLITE_OK; if( lockType==EXCLUSIVE_LOCK ){ - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); + rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); } if( !rc ){ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType); @@ -6798,11 +6819,12 @@ static int proxyTakeConch(unixFile *pFile){ int forceNewLockPath = 0; OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h, - (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid())); + (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), + osGetpid(0))); rc = proxyGetHostID(myHostID, &pError); if( (rc&0xff)==SQLITE_IOERR ){ - pFile->lastErrno = pError; + storeLastErrno(pFile, pError); goto end_takeconch; } rc = proxyConchLock(pFile, myHostID, SHARED_LOCK); @@ -6813,7 +6835,7 @@ static int proxyTakeConch(unixFile *pFile){ readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN); if( readLen<0 ){ /* I/O error: lastErrno set by seekAndRead */ - pFile->lastErrno = conchFile->lastErrno; + storeLastErrno(pFile, conchFile->lastErrno); rc = SQLITE_IOERR_READ; goto end_takeconch; }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) || @@ -6886,7 +6908,7 @@ static int proxyTakeConch(unixFile *pFile){ rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); } }else{ - rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); + rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK); } if( rc==SQLITE_OK ){ char writeBuffer[PROXY_MAXCONCHLEN]; @@ -6895,7 +6917,8 @@ static int proxyTakeConch(unixFile *pFile){ writeBuffer[0] = (char)PROXY_CONCHVERSION; memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN); if( pCtx->lockProxyPath!=NULL ){ - strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN); + strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, + MAXPATHLEN); }else{ strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN); } @@ -7007,7 +7030,7 @@ static int proxyReleaseConch(unixFile *pFile){ conchFile = pCtx->conchFile; OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h, (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), - getpid())); + osGetpid(0))); if( pCtx->conchHeld>0 ){ rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); } @@ -7019,7 +7042,7 @@ static int proxyReleaseConch(unixFile *pFile){ /* ** Given the name of a database file, compute the name of its conch file. -** Store the conch filename in memory obtained from sqlite3_malloc(). +** Store the conch filename in memory obtained from sqlite3_malloc64(). ** Make *pConchPath point to the new name. Return SQLITE_OK on success ** or SQLITE_NOMEM if unable to obtain memory. ** @@ -7035,7 +7058,7 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){ /* Allocate space for the conch filename and initialize the name to ** the name of the original database file. */ - *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8); + *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8); if( conchPath==0 ){ return SQLITE_NOMEM; } @@ -7107,7 +7130,8 @@ static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){ /* afp style keeps a reference to the db path in the filePath field ** of the struct */ assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); - strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN); + strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, + MAXPATHLEN); } else #endif if( pFile->pMethod == &dotlockIoMethods ){ @@ -7148,9 +7172,9 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { } OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h, - (lockPath ? lockPath : ":auto:"), getpid())); + (lockPath ? lockPath : ":auto:"), osGetpid(0))); - pCtx = sqlite3_malloc( sizeof(*pCtx) ); + pCtx = sqlite3_malloc64( sizeof(*pCtx) ); if( pCtx==0 ){ return SQLITE_NOMEM; } @@ -7220,7 +7244,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) { */ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ switch( op ){ - case SQLITE_GET_LOCKPROXYFILE: { + case SQLITE_FCNTL_GET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; if( pFile->pMethod == &proxyIoMethods ){ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; @@ -7235,13 +7259,16 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){ } return SQLITE_OK; } - case SQLITE_SET_LOCKPROXYFILE: { + case SQLITE_FCNTL_SET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; int rc = SQLITE_OK; int isProxyStyle = (pFile->pMethod == &proxyIoMethods); if( pArg==NULL || (const char *)pArg==0 ){ if( isProxyStyle ){ - /* turn off proxy locking - not supported */ + /* turn off proxy locking - not supported. If support is added for + ** switching proxy locking mode off then it will need to fail if + ** the journal mode is WAL mode. + */ rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/; }else{ /* turn off proxy locking - already off - NOOP */ @@ -7486,8 +7513,10 @@ int sqlite3_os_init(void){ ** array cannot be const. */ static sqlite3_vfs aVfs[] = { -#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__)) +#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) UNIXVFS("unix", autolockIoFinder ), +#elif OS_VXWORKS + UNIXVFS("unix", vxworksIoFinder ), #else UNIXVFS("unix", posixIoFinder ), #endif @@ -7497,11 +7526,11 @@ int sqlite3_os_init(void){ #if OS_VXWORKS UNIXVFS("unix-namedsem", semIoFinder ), #endif -#if SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS UNIXVFS("unix-posix", posixIoFinder ), -#if !OS_VXWORKS - UNIXVFS("unix-flock", flockIoFinder ), #endif +#if SQLITE_ENABLE_LOCKING_STYLE + UNIXVFS("unix-flock", flockIoFinder ), #endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) UNIXVFS("unix-afp", afpIoFinder ), diff --git a/src/os_win.c b/src/os_win.c index e2f9aec..0ebea5a 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -197,8 +197,10 @@ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif /* SQLITE_OS_WINRT */ /* -** This file mapping API is common to both Win32 and WinRT. +** These file mapping APIs are common to both Win32 and WinRT. */ + +WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T); WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); #endif /* SQLITE_WIN32_FILEMAPPING_API */ @@ -1066,6 +1068,32 @@ static struct win_syscall { SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) #endif /* defined(InterlockedCompareExchange) */ +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + { "UuidCreate", (SYSCALL)UuidCreate, 0 }, +#else + { "UuidCreate", (SYSCALL)0, 0 }, +#endif + +#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) + +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, +#else + { "UuidCreateSequential", (SYSCALL)0, 0 }, +#endif + +#define osUuidCreateSequential \ + ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) + +#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 + { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, +#else + { "FlushViewOfFile", (SYSCALL)0, 0 }, +#endif + +#define osFlushViewOfFile \ + ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) + }; /* End of the overrideable system calls */ /* @@ -1949,11 +1977,11 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){ /* ** Log a I/O error retry episode. */ -static void winLogIoerr(int nRetry){ +static void winLogIoerr(int nRetry, int lineno){ if( nRetry ){ - sqlite3_log(SQLITE_IOERR, - "delayed %dms for lock/sharing conflict", - winIoerrRetryDelay*nRetry*(nRetry+1)/2 + sqlite3_log(SQLITE_NOTICE, + "delayed %dms for lock/sharing conflict at line %d", + winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno ); } } @@ -2433,7 +2461,8 @@ static int winClose(sqlite3_file *id){ assert( pFile->pShm==0 ); #endif assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); - OSTRACE(("CLOSE file=%p\n", pFile->h)); + OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n", + osGetCurrentProcessId(), pFile, pFile->h)); #if SQLITE_MAX_MMAP_SIZE>0 winUnmapfile(pFile); @@ -2462,7 +2491,8 @@ static int winClose(sqlite3_file *id){ pFile->h = NULL; } OpenCounter(-1); - OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed")); + OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n", + osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed")); return rc ? SQLITE_OK : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), "winClose", pFile->zPath); @@ -2490,7 +2520,8 @@ static int winRead( assert( amt>0 ); assert( offset>=0 ); SimulateIOError(return SQLITE_IOERR_READ); - OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n", + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " + "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, pFile->h, pBuf, amt, offset, pFile->locktype)); #if SQLITE_MAX_MMAP_SIZE>0 @@ -2499,7 +2530,8 @@ static int winRead( if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); - OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; }else{ int nCopy = (int)(pFile->mmapSize - offset); @@ -2513,7 +2545,8 @@ static int winRead( #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) if( winSeekFile(pFile, offset) ){ - OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_FULL; } while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ @@ -2527,19 +2560,22 @@ static int winRead( DWORD lastErrno; if( winRetryIoerr(&nRetry, &lastErrno) ) continue; pFile->lastErrno = lastErrno; - OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h)); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n", + osGetCurrentProcessId(), pFile, pFile->h)); return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, "winRead", pFile->zPath); } - winLogIoerr(nRetry); + winLogIoerr(nRetry, __LINE__); if( nRead<(DWORD)amt ){ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[nRead], 0, amt-nRead); - OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h)); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_IOERR_SHORT_READ; } - OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; } @@ -2562,7 +2598,8 @@ static int winWrite( SimulateIOError(return SQLITE_IOERR_WRITE); SimulateDiskfullError(return SQLITE_FULL); - OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n", + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " + "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, pFile->h, pBuf, amt, offset, pFile->locktype)); #if SQLITE_MAX_MMAP_SIZE>0 @@ -2571,7 +2608,8 @@ static int winWrite( if( offsetmmapSize ){ if( offset+amt <= pFile->mmapSize ){ memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); - OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; }else{ int nCopy = (int)(pFile->mmapSize - offset); @@ -2634,17 +2672,20 @@ static int winWrite( if( rc ){ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) || ( pFile->lastErrno==ERROR_DISK_FULL )){ - OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h)); + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", + osGetCurrentProcessId(), pFile, pFile->h)); return winLogError(SQLITE_FULL, pFile->lastErrno, "winWrite1", pFile->zPath); } - OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h)); + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n", + osGetCurrentProcessId(), pFile, pFile->h)); return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, "winWrite2", pFile->zPath); }else{ - winLogIoerr(nRetry); + winLogIoerr(nRetry, __LINE__); } - OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; } @@ -2658,8 +2699,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ assert( pFile ); SimulateIOError(return SQLITE_IOERR_TRUNCATE); - OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n", - pFile->h, nByte, pFile->locktype)); + OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n", + osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype)); /* If the user has configured a chunk-size for this file, truncate the ** file so that it consists of an integer number of chunks (i.e. the @@ -2691,7 +2732,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ } #endif - OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); + OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n", + osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc))); return rc; } @@ -2715,7 +2757,7 @@ static int winSync(sqlite3_file *id, int flags){ BOOL rc; #endif #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \ - (defined(SQLITE_TEST) && defined(SQLITE_DEBUG)) + defined(SQLITE_HAVE_OS_TRACE) /* ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or ** OSTRACE() macros. @@ -2736,8 +2778,9 @@ static int winSync(sqlite3_file *id, int flags){ */ SimulateDiskfullError( return SQLITE_FULL ); - OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n", - pFile->h, flags, pFile->locktype)); + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n", + osGetCurrentProcessId(), pFile, pFile->h, flags, + pFile->locktype)); #ifndef SQLITE_TEST UNUSED_PARAMETER(flags); @@ -2752,19 +2795,38 @@ static int winSync(sqlite3_file *id, int flags){ ** no-op */ #ifdef SQLITE_NO_SYNC - OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; #else +#if SQLITE_MAX_MMAP_SIZE>0 + if( pFile->pMapRegion ){ + if( osFlushViewOfFile(pFile->pMapRegion, 0) ){ + OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " + "rc=SQLITE_OK\n", osGetCurrentProcessId(), + pFile, pFile->pMapRegion)); + }else{ + pFile->lastErrno = osGetLastError(); + OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " + "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), + pFile, pFile->pMapRegion)); + return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, + "winSync1", pFile->zPath); + } + } +#endif rc = osFlushFileBuffers(pFile->h); SimulateIOError( rc=FALSE ); if( rc ){ - OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h)); + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", + osGetCurrentProcessId(), pFile, pFile->h)); return SQLITE_OK; }else{ pFile->lastErrno = osGetLastError(); - OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h)); + OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n", + osGetCurrentProcessId(), pFile, pFile->h)); return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, - "winSync", pFile->zPath); + "winSync2", pFile->zPath); } #endif } @@ -3372,7 +3434,7 @@ struct winShmNode { int nRef; /* Number of winShm objects pointing to this */ winShm *pFirst; /* All winShm objects pointing to this */ winShmNode *pNext; /* Next in list of all winShmNode objects */ -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) u8 nextShmId; /* Next available winShm.id value */ #endif }; @@ -3403,7 +3465,7 @@ struct winShm { u8 hasMutex; /* True if holding the winShmNode mutex */ u16 sharedMask; /* Mask of shared locks held */ u16 exclMask; /* Mask of exclusive locks held */ -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) u8 id; /* Id of this connection with its winShmNode */ #endif }; @@ -3594,7 +3656,7 @@ static int winOpenSharedMemory(winFile *pDbFd){ /* Make the new connection a child of the winShmNode */ p->pShmNode = pShmNode; -#ifdef SQLITE_DEBUG +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) p->id = pShmNode->nextShmId++; #endif pShmNode->nRef++; @@ -3814,16 +3876,16 @@ static int winShmMap( void volatile **pp /* OUT: Mapped memory */ ){ winFile *pDbFd = (winFile*)fd; - winShm *p = pDbFd->pShm; + winShm *pShm = pDbFd->pShm; winShmNode *pShmNode; int rc = SQLITE_OK; - if( !p ){ + if( !pShm ){ rc = winOpenSharedMemory(pDbFd); if( rc!=SQLITE_OK ) return rc; - p = pDbFd->pShm; + pShm = pDbFd->pShm; } - pShmNode = p->pShmNode; + pShmNode = pShm->pShmNode; sqlite3_mutex_enter(pShmNode->mutex); assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); @@ -3863,7 +3925,7 @@ static int winShmMap( } /* Map the requested memory region into this processes address space. */ - apNew = (struct ShmRegion *)sqlite3_realloc( + apNew = (struct ShmRegion *)sqlite3_realloc64( pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) ); if( !apNew ){ @@ -4735,7 +4797,7 @@ static int winOpen( } } #endif - winLogIoerr(cnt); + winLogIoerr(cnt, __LINE__); OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name, dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); @@ -4919,7 +4981,7 @@ static int winDelete( if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); }else{ - winLogIoerr(cnt); + winLogIoerr(cnt, __LINE__); } sqlite3_free(zConverted); OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc))); @@ -4969,7 +5031,7 @@ static int winAccess( attr = sAttrData.dwFileAttributes; } }else{ - winLogIoerr(cnt); + winLogIoerr(cnt, __LINE__); if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ sqlite3_free(zConverted); return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", @@ -5310,7 +5372,7 @@ static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ int n = 0; UNUSED_PARAMETER(pVfs); -#if defined(SQLITE_TEST) +#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) n = nBuf; memset(zBuf, 0, nBuf); #else @@ -5344,7 +5406,23 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ memcpy(&zBuf[n], &i, sizeof(i)); n += sizeof(i); } +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID + if( sizeof(UUID)<=nBuf-n ){ + UUID id; + memset(&id, 0, sizeof(UUID)); + osUuidCreate(&id); + memcpy(zBuf, &id, sizeof(UUID)); + n += sizeof(UUID); + } + if( sizeof(UUID)<=nBuf-n ){ + UUID id; + memset(&id, 0, sizeof(UUID)); + osUuidCreateSequential(&id); + memcpy(zBuf, &id, sizeof(UUID)); + n += sizeof(UUID); + } #endif +#endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */ return n; } @@ -5522,7 +5600,7 @@ int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==77 ); + assert( ArraySize(aSyscall)==80 ); /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); diff --git a/src/os_win.h b/src/os_win.h index 5174ac7..17d6a2b 100644 --- a/src/os_win.h +++ b/src/os_win.h @@ -74,4 +74,15 @@ # define SQLITE_WIN32_VOLATILE volatile #endif +/* +** For some Windows sub-platforms, the _beginthreadex() / _endthreadex() +** functions are not available (e.g. those not using MSVC, Cygwin, etc). +*/ +#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ + SQLITE_THREADSAFE>0 && !defined(__CYGWIN__) +# define SQLITE_OS_WIN_THREADS 1 +#else +# define SQLITE_OS_WIN_THREADS 0 +#endif + #endif /* _OS_WIN_H_ */ diff --git a/src/pager.c b/src/pager.c index 2230174..91378f0 100644 --- a/src/pager.c +++ b/src/pager.c @@ -3044,9 +3044,7 @@ static int pagerWalFrames( ){ int rc; /* Return code */ int nList; /* Number of pages in pList */ -#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES) PgHdr *p; /* For looping over pages */ -#endif assert( pPager->pWal ); assert( pList ); @@ -3063,7 +3061,6 @@ static int pagerWalFrames( ** any pages with page numbers greater than nTruncate into the WAL file. ** They will never be read by any client. So remove them from the pDirty ** list here. */ - PgHdr *p; PgHdr **ppNext = &pList; nList = 0; for(p=pList; (*ppNext = p)!=0; p=p->pDirty){ @@ -3083,7 +3080,6 @@ static int pagerWalFrames( pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags ); if( rc==SQLITE_OK && pPager->pBackup ){ - PgHdr *p; for(p=pList; p; p=p->pDirty){ sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); } @@ -7014,6 +7010,8 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ } assert( state==pPager->eState ); } + }else if( eMode==PAGER_JOURNALMODE_OFF ){ + sqlite3OsClose(pPager->jfd); } } diff --git a/src/parse.y b/src/parse.y index 544888a..6a64206 100644 --- a/src/parse.y +++ b/src/parse.y @@ -409,28 +409,35 @@ cmd ::= select(X). { %type oneselect {Select*} %destructor oneselect {sqlite3SelectDelete(pParse->db, $$);} -select(A) ::= with(W) selectnowith(X). { - Select *p = X, *pNext, *pLoop; - if( p ){ - int cnt = 0, mxSelect; - p->pWith = W; +%include { + /* + ** For a compound SELECT statement, make sure p->pPrior->pNext==p for + ** all elements in the list. And make sure list length does not exceed + ** SQLITE_LIMIT_COMPOUND_SELECT. + */ + static void parserDoubleLinkSelect(Parse *pParse, Select *p){ if( p->pPrior ){ - u16 allValues = SF_Values; - pNext = 0; + Select *pNext = 0, *pLoop; + int mxSelect, cnt = 0; for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){ pLoop->pNext = pNext; pLoop->selFlags |= SF_Compound; - allValues &= pLoop->selFlags; } - if( allValues ){ - p->selFlags |= SF_AllValues; - }else if( - (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 - && cnt>mxSelect + if( (p->selFlags & SF_MultiValue)==0 && + (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 && + cnt>mxSelect ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); } } + } +} + +select(A) ::= with(W) selectnowith(X). { + Select *p = X; + if( p ){ + p->pWith = W; + parserDoubleLinkSelect(pParse, p); }else{ sqlite3WithDelete(pParse->db, W); } @@ -445,12 +452,14 @@ selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). { SrcList *pFrom; Token x; x.n = 0; + parserDoubleLinkSelect(pParse, pRhs); pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0); } if( pRhs ){ pRhs->op = (u8)Y; pRhs->pPrior = X; + pRhs->selFlags &= ~SF_MultiValue; if( Y!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, X); @@ -498,13 +507,16 @@ values(A) ::= VALUES LP nexprlist(X) RP. { A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0); } values(A) ::= values(X) COMMA LP exprlist(Y) RP. { - Select *pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values,0,0); + Select *pRight, *pLeft = X; + pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0); + if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; - pRight->pPrior = X; + pLeft = X; + pRight->pPrior = pLeft; A = pRight; }else{ - A = X; + A = pLeft; } } @@ -860,7 +872,7 @@ expr(A) ::= VARIABLE(X). { spanSet(&A, &X, &X); } expr(A) ::= expr(E) COLLATE ids(C). { - A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C); + A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C, 1); A.zStart = E.zStart; A.zEnd = &C.z[C.n]; } @@ -1078,7 +1090,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Y; - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } @@ -1091,8 +1103,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = X; - ExprSetProperty(A.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, A.pExpr); + ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, X); } @@ -1103,8 +1115,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = Y; - ExprSetProperty(A.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, A.pExpr); + ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, Y); } @@ -1117,8 +1129,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(A.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, A.pExpr); + ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } @@ -1130,8 +1142,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { Expr *p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ p->x.pSelect = Y; - ExprSetProperty(p, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, p); + ExprSetProperty(p, EP_xIsSelect|EP_Subquery); + sqlite3ExprSetHeightAndFlags(pParse, p); }else{ sqlite3SelectDelete(pParse->db, Y); } @@ -1145,7 +1157,7 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; - sqlite3ExprSetHeight(pParse, A.pExpr); + sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); sqlite3ExprDelete(pParse->db, Z); @@ -1206,14 +1218,14 @@ uniqueflag(A) ::= . {A = OE_None;} idxlist_opt(A) ::= . {A = 0;} idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). { - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C); + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1); A = sqlite3ExprListAppend(pParse,X, p); sqlite3ExprListSetName(pParse,A,&Y,1); sqlite3ExprListCheckLength(pParse, A, "index"); if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; } idxlist(A) ::= nm(Y) collate(C) sortorder(Z). { - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C); + Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1); A = sqlite3ExprListAppend(pParse,0, p); sqlite3ExprListSetName(pParse, A, &Y, 1); sqlite3ExprListCheckLength(pParse, A, "index"); diff --git a/src/pcache.c b/src/pcache.c index 467e2b3..d768fe0 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -114,12 +114,20 @@ static void pcacheUnpin(PgHdr *p){ } /* -** Compute the number of pages of cache requested. +** Compute the number of pages of cache requested. p->szCache is the +** cache size requested by the "PRAGMA cache_size" statement. +** +** */ static int numberOfCachePages(PCache *p){ if( p->szCache>=0 ){ + /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the + ** suggested cache size is set to N. */ return p->szCache; }else{ + /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then + ** the number of cache pages is adjusted to use approximately abs(N*1024) + ** bytes of memory. */ return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); } } diff --git a/src/pcache1.c b/src/pcache1.c index f5f7893..a8755a3 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -195,7 +195,6 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ static void *pcache1Alloc(int nByte){ void *p = 0; assert( sqlite3_mutex_notheld(pcache1.grp.mutex) ); - sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); if( nByte<=pcache1.szSlot ){ sqlite3_mutex_enter(pcache1.mutex); p = (PgHdr1 *)pcache1.pFree; @@ -204,7 +203,8 @@ static void *pcache1Alloc(int nByte){ pcache1.nFreeSlot--; pcache1.bUnderPressure = pcache1.nFreeSlot=0 ); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); + sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1); } sqlite3_mutex_leave(pcache1.mutex); } @@ -217,7 +217,8 @@ static void *pcache1Alloc(int nByte){ if( p ){ int sz = sqlite3MallocSize(p); sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); + sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte); + sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); sqlite3_mutex_leave(pcache1.mutex); } #endif @@ -235,7 +236,7 @@ static int pcache1Free(void *p){ if( p>=pcache1.pStart && ppNext = pcache1.pFree; pcache1.pFree = pSlot; @@ -249,7 +250,7 @@ static int pcache1Free(void *p){ nFreed = sqlite3MallocSize(p); #ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS sqlite3_mutex_enter(pcache1.mutex); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed); + sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed); sqlite3_mutex_leave(pcache1.mutex); #endif sqlite3_free(p); @@ -986,6 +987,14 @@ void sqlite3PCacheSetDefault(void){ */ int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } +/* +** Return the global mutex used by this PCACHE implementation. The +** sqlite3_status() routine needs access to this mutex. +*/ +sqlite3_mutex *sqlite3Pcache1Mutex(void){ + return pcache1.mutex; +} + #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* ** This function is called to free superfluous dynamically allocated memory diff --git a/src/pragma.c b/src/pragma.c index 34830e3..1b42138 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -22,464 +22,13 @@ #endif /*************************************************************************** -** The next block of code, including the PragTyp_XXXX macro definitions and -** the aPragmaName[] object is composed of generated code. DO NOT EDIT. -** -** To add new pragmas, edit the code in ../tool/mkpragmatab.tcl and rerun -** that script. Then copy/paste the output in place of the following: -*/ -#define PragTyp_HEADER_VALUE 0 -#define PragTyp_AUTO_VACUUM 1 -#define PragTyp_FLAG 2 -#define PragTyp_BUSY_TIMEOUT 3 -#define PragTyp_CACHE_SIZE 4 -#define PragTyp_CASE_SENSITIVE_LIKE 5 -#define PragTyp_COLLATION_LIST 6 -#define PragTyp_COMPILE_OPTIONS 7 -#define PragTyp_DATA_STORE_DIRECTORY 8 -#define PragTyp_DATABASE_LIST 9 -#define PragTyp_DEFAULT_CACHE_SIZE 10 -#define PragTyp_ENCODING 11 -#define PragTyp_FOREIGN_KEY_CHECK 12 -#define PragTyp_FOREIGN_KEY_LIST 13 -#define PragTyp_INCREMENTAL_VACUUM 14 -#define PragTyp_INDEX_INFO 15 -#define PragTyp_INDEX_LIST 16 -#define PragTyp_INTEGRITY_CHECK 17 -#define PragTyp_JOURNAL_MODE 18 -#define PragTyp_JOURNAL_SIZE_LIMIT 19 -#define PragTyp_LOCK_PROXY_FILE 20 -#define PragTyp_LOCKING_MODE 21 -#define PragTyp_PAGE_COUNT 22 -#define PragTyp_MMAP_SIZE 23 -#define PragTyp_PAGE_SIZE 24 -#define PragTyp_SECURE_DELETE 25 -#define PragTyp_SHRINK_MEMORY 26 -#define PragTyp_SOFT_HEAP_LIMIT 27 -#define PragTyp_STATS 28 -#define PragTyp_SYNCHRONOUS 29 -#define PragTyp_TABLE_INFO 30 -#define PragTyp_TEMP_STORE 31 -#define PragTyp_TEMP_STORE_DIRECTORY 32 -#define PragTyp_THREADS 33 -#define PragTyp_WAL_AUTOCHECKPOINT 34 -#define PragTyp_WAL_CHECKPOINT 35 -#define PragTyp_ACTIVATE_EXTENSIONS 36 -#define PragTyp_HEXKEY 37 -#define PragTyp_KEY 38 -#define PragTyp_REKEY 39 -#define PragTyp_LOCK_STATUS 40 -#define PragTyp_PARSER_TRACE 41 -#define PragFlag_NeedSchema 0x01 -#define PragFlag_ReadOnly 0x02 -static const struct sPragmaNames { - const char *const zName; /* Name of pragma */ - u8 ePragTyp; /* PragTyp_XXX value */ - u8 mPragFlag; /* Zero or more PragFlag_XXX values */ - u32 iArg; /* Extra argument */ -} aPragmaNames[] = { -#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) - { /* zName: */ "activate_extensions", - /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "application_id", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ 0, - /* iArg: */ BTREE_APPLICATION_ID }, -#endif -#if !defined(SQLITE_OMIT_AUTOVACUUM) - { /* zName: */ "auto_vacuum", - /* ePragTyp: */ PragTyp_AUTO_VACUUM, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) - { /* zName: */ "automatic_index", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_AutoIndex }, -#endif -#endif - { /* zName: */ "busy_timeout", - /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "cache_size", - /* ePragTyp: */ PragTyp_CACHE_SIZE, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "cache_spill", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_CacheSpill }, -#endif - { /* zName: */ "case_sensitive_like", - /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "checkpoint_fullfsync", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_CkptFullFSync }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "collation_list", - /* ePragTyp: */ PragTyp_COLLATION_LIST, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) - { /* zName: */ "compile_options", - /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "count_changes", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_CountRows }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN - { /* zName: */ "data_store_directory", - /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "data_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ PragFlag_ReadOnly, - /* iArg: */ BTREE_DATA_VERSION }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "database_list", - /* ePragTyp: */ PragTyp_DATABASE_LIST, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) - { /* zName: */ "default_cache_size", - /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { /* zName: */ "defer_foreign_keys", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_DeferFKs }, -#endif -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "empty_result_callbacks", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_NullCallback }, -#endif -#if !defined(SQLITE_OMIT_UTF16) - { /* zName: */ "encoding", - /* ePragTyp: */ PragTyp_ENCODING, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { /* zName: */ "foreign_key_check", - /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FOREIGN_KEY) - { /* zName: */ "foreign_key_list", - /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { /* zName: */ "foreign_keys", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_ForeignKeys }, -#endif -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "freelist_count", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ PragFlag_ReadOnly, - /* iArg: */ BTREE_FREE_PAGE_COUNT }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "full_column_names", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_FullColNames }, - { /* zName: */ "fullfsync", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_FullFSync }, -#endif -#if defined(SQLITE_HAS_CODEC) - { /* zName: */ "hexkey", - /* ePragTyp: */ PragTyp_HEXKEY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "hexrekey", - /* ePragTyp: */ PragTyp_HEXKEY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if !defined(SQLITE_OMIT_CHECK) - { /* zName: */ "ignore_check_constraints", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_IgnoreChecks }, -#endif -#endif -#if !defined(SQLITE_OMIT_AUTOVACUUM) - { /* zName: */ "incremental_vacuum", - /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "index_info", - /* ePragTyp: */ PragTyp_INDEX_INFO, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "index_list", - /* ePragTyp: */ PragTyp_INDEX_LIST, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) - { /* zName: */ "integrity_check", - /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "journal_mode", - /* ePragTyp: */ PragTyp_JOURNAL_MODE, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "journal_size_limit", - /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_HAS_CODEC) - { /* zName: */ "key", - /* ePragTyp: */ PragTyp_KEY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "legacy_file_format", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_LegacyFileFmt }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE - { /* zName: */ "lock_proxy_file", - /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) - { /* zName: */ "lock_status", - /* ePragTyp: */ PragTyp_LOCK_STATUS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "locking_mode", - /* ePragTyp: */ PragTyp_LOCKING_MODE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "max_page_count", - /* ePragTyp: */ PragTyp_PAGE_COUNT, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "mmap_size", - /* ePragTyp: */ PragTyp_MMAP_SIZE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "page_count", - /* ePragTyp: */ PragTyp_PAGE_COUNT, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, - { /* zName: */ "page_size", - /* ePragTyp: */ PragTyp_PAGE_SIZE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if defined(SQLITE_DEBUG) - { /* zName: */ "parser_trace", - /* ePragTyp: */ PragTyp_PARSER_TRACE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "query_only", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_QueryOnly }, -#endif -#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) - { /* zName: */ "quick_check", - /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "read_uncommitted", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_ReadUncommitted }, - { /* zName: */ "recursive_triggers", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_RecTriggers }, -#endif -#if defined(SQLITE_HAS_CODEC) - { /* zName: */ "rekey", - /* ePragTyp: */ PragTyp_REKEY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "reverse_unordered_selects", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_ReverseOrder }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "schema_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ 0, - /* iArg: */ BTREE_SCHEMA_VERSION }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "secure_delete", - /* ePragTyp: */ PragTyp_SECURE_DELETE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "short_column_names", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_ShortColNames }, -#endif - { /* zName: */ "shrink_memory", - /* ePragTyp: */ PragTyp_SHRINK_MEMORY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "soft_heap_limit", - /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if defined(SQLITE_DEBUG) - { /* zName: */ "sql_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_SqlTrace }, -#endif -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "stats", - /* ePragTyp: */ PragTyp_STATS, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "synchronous", - /* ePragTyp: */ PragTyp_SYNCHRONOUS, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - { /* zName: */ "table_info", - /* ePragTyp: */ PragTyp_TABLE_INFO, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) - { /* zName: */ "temp_store", - /* ePragTyp: */ PragTyp_TEMP_STORE, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "temp_store_directory", - /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#endif - { /* zName: */ "threads", - /* ePragTyp: */ PragTyp_THREADS, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, -#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) - { /* zName: */ "user_version", - /* ePragTyp: */ PragTyp_HEADER_VALUE, - /* ePragFlag: */ 0, - /* iArg: */ BTREE_USER_VERSION }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) -#if defined(SQLITE_DEBUG) - { /* zName: */ "vdbe_addoptrace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_VdbeAddopTrace }, - { /* zName: */ "vdbe_debug", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, - { /* zName: */ "vdbe_eqp", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_VdbeEQP }, - { /* zName: */ "vdbe_listing", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_VdbeListing }, - { /* zName: */ "vdbe_trace", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_VdbeTrace }, -#endif -#endif -#if !defined(SQLITE_OMIT_WAL) - { /* zName: */ "wal_autocheckpoint", - /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, - /* ePragFlag: */ 0, - /* iArg: */ 0 }, - { /* zName: */ "wal_checkpoint", - /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, - /* ePragFlag: */ PragFlag_NeedSchema, - /* iArg: */ 0 }, -#endif -#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) - { /* zName: */ "writable_schema", - /* ePragTyp: */ PragTyp_FLAG, - /* ePragFlag: */ 0, - /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, -#endif -}; -/* Number of pragmas: 58 on by default, 71 total. */ -/* End of the automatically generated pragma table. -***************************************************************************/ +** The "pragma.h" include file is an automatically generated file that +** that includes the PragType_XXXX macro definitions and the aPragmaName[] +** object. This ensures that the aPragmaName[] table is arranged in +** lexicographical order to facility a binary search of the pragma name. +** Do not edit pragma.h directly. Edit and rerun the script in at +** ../tool/mkpragmatab.tcl. */ +#include "pragma.h" /* ** Interpret the given string as a safety level. Return 0 for OFF, @@ -615,15 +164,15 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){ */ static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){ Vdbe *v = sqlite3GetVdbe(pParse); - int mem = ++pParse->nMem; + int nMem = ++pParse->nMem; i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value)); if( pI64 ){ memcpy(pI64, &value, sizeof(value)); } - sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64); + sqlite3VdbeAddOp4(v, OP_Int64, 0, nMem, 0, (char*)pI64, P4_INT64); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1); } @@ -732,6 +281,7 @@ void sqlite3Pragma( sqlite3 *db = pParse->db; /* The database connection */ Db *pDb; /* The specific database being pragmaed */ Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ + const struct sPragmaNames *pPragma; if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); @@ -767,6 +317,17 @@ void sqlite3Pragma( /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS ** connection. If it returns SQLITE_OK, then assume that the VFS ** handled the pragma and generate a no-op prepared statement. + ** + ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed, + ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file + ** object corresponding to the database file to which the pragma + ** statement refers. + ** + ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA + ** file control is an array of pointers to strings (char**) in which the + ** second element of the array is the name of the pragma and the third + ** element is the argument to the pragma or NULL if the pragma has no + ** argument. */ aFcntl[0] = 0; aFcntl[1] = zLeft; @@ -776,11 +337,11 @@ void sqlite3Pragma( rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); if( rc==SQLITE_OK ){ if( aFcntl[0] ){ - int mem = ++pParse->nMem; - sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0); + int nMem = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, nMem, 0, aFcntl[0], 0); sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC); - sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); + sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1); sqlite3_free(aFcntl[0]); } goto pragma_out; @@ -809,14 +370,15 @@ void sqlite3Pragma( } } if( lwr>upr ) goto pragma_out; + pPragma = &aPragmaNames[mid]; /* Make sure the database schema is loaded if the pragma requires that */ - if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){ + if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; } /* Jump to the appropriate pragma handler */ - switch( aPragmaNames[mid].ePragTyp ){ + switch( pPragma->ePragTyp ){ #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* @@ -1384,7 +946,9 @@ void sqlite3Pragma( sqlite3ErrorMsg(pParse, "Safety level may not be changed inside a transaction"); }else{ - pDb->safety_level = getSafetyLevel(zRight,0,1)+1; + int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK; + if( iLevel==0 ) iLevel = 1; + pDb->safety_level = iLevel; setAllPagerFlags(db); } } @@ -1395,10 +959,9 @@ void sqlite3Pragma( #ifndef SQLITE_OMIT_FLAG_PRAGMAS case PragTyp_FLAG: { if( zRight==0 ){ - returnSingleInt(pParse, aPragmaNames[mid].zName, - (db->flags & aPragmaNames[mid].iArg)!=0 ); + returnSingleInt(pParse, pPragma->zName, (db->flags & pPragma->iArg)!=0 ); }else{ - int mask = aPragmaNames[mid].iArg; /* Mask of bits to set or clear. */ + int mask = pPragma->iArg; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ /* Foreign key support may not be enabled or disabled while not ** in auto-commit mode. */ @@ -1480,7 +1043,7 @@ void sqlite3Pragma( }else if( pPk==0 ){ k = 1; }else{ - for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){} + for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } sqlite3VdbeAddOp2(v, OP_Integer, k, 6); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); @@ -1527,20 +1090,42 @@ void sqlite3Pragma( pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ int i; + int mx; + if( pPragma->iArg ){ + /* PRAGMA index_xinfo (newer version with more rows and columns) */ + mx = pIdx->nColumn; + pParse->nMem = 6; + }else{ + /* PRAGMA index_info (legacy version) */ + mx = pIdx->nKeyCol; + pParse->nMem = 3; + } pTab = pIdx->pTable; - sqlite3VdbeSetNumCols(v, 3); - pParse->nMem = 3; + sqlite3VdbeSetNumCols(v, pParse->nMem); sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC); - for(i=0; inKeyCol; i++){ + if( pPragma->iArg ){ + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC); + } + for(i=0; iaiColumn[i]; sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2); - assert( pTab->nCol>cnum ); - sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + if( cnum<0 ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, 3); + }else{ + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0); + } + if( pPragma->iArg ){ + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4); + sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0); + sqlite3VdbeAddOp2(v, OP_Integer, inKeyCol, 6); + } + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem); } } } @@ -1553,17 +1138,22 @@ void sqlite3Pragma( pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ v = sqlite3GetVdbe(pParse); - sqlite3VdbeSetNumCols(v, 3); - pParse->nMem = 3; + sqlite3VdbeSetNumCols(v, 5); + pParse->nMem = 5; sqlite3CodeVerifySchema(pParse, iDb); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "origin", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "partial", SQLITE_STATIC); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ + const char *azOrigin[] = { "c", "u", "pk" }; sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); sqlite3VdbeAddOp2(v, OP_Integer, IsUniqueIndex(pIdx), 3); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, azOrigin[pIdx->idxType], 0); + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->pPartIdxWhere!=0, 5); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); } } } @@ -2133,9 +1723,9 @@ void sqlite3Pragma( ** applications for any purpose. */ case PragTyp_HEADER_VALUE: { - int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */ + int iCookie = pPragma->iArg; /* Which cookie to read or write */ sqlite3VdbeUsesBtree(v, iDb); - if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){ + if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){ /* Write the specified cookie value */ static const VdbeOpList setCookie[] = { { OP_Transaction, 0, 1, 0}, /* 0 */ @@ -2237,8 +1827,9 @@ void sqlite3Pragma( /* ** PRAGMA shrink_memory ** - ** This pragma attempts to free as much memory as possible from the - ** current database connection. + ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database + ** connection on which it is invoked to free up as much memory as it + ** can, by calling sqlite3_db_release_memory(). */ case PragTyp_SHRINK_MEMORY: { sqlite3_db_release_memory(db); @@ -2255,7 +1846,7 @@ void sqlite3Pragma( ** disables the timeout. */ /*case PragTyp_BUSY_TIMEOUT*/ default: { - assert( aPragmaNames[mid].ePragTyp==PragTyp_BUSY_TIMEOUT ); + assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT ); if( zRight ){ sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); } @@ -2267,8 +1858,12 @@ void sqlite3Pragma( ** PRAGMA soft_heap_limit ** PRAGMA soft_heap_limit = N ** - ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted, - ** use -1. + ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the + ** sqlite3_soft_heap_limit64() interface with the argument N, if N is + ** specified and is a non-negative integer. + ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always + ** returns the same integer that would be returned by the + ** sqlite3_soft_heap_limit64(-1) C-language function. */ case PragTyp_SOFT_HEAP_LIMIT: { sqlite3_int64 N; diff --git a/src/pragma.h b/src/pragma.h new file mode 100644 index 0000000..c9ae8e6 --- /dev/null +++ b/src/pragma.h @@ -0,0 +1,459 @@ +/* DO NOT EDIT! +** This file is automatically generated by the script at +** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit +** that script and rerun it. +*/ +#define PragTyp_HEADER_VALUE 0 +#define PragTyp_AUTO_VACUUM 1 +#define PragTyp_FLAG 2 +#define PragTyp_BUSY_TIMEOUT 3 +#define PragTyp_CACHE_SIZE 4 +#define PragTyp_CASE_SENSITIVE_LIKE 5 +#define PragTyp_COLLATION_LIST 6 +#define PragTyp_COMPILE_OPTIONS 7 +#define PragTyp_DATA_STORE_DIRECTORY 8 +#define PragTyp_DATABASE_LIST 9 +#define PragTyp_DEFAULT_CACHE_SIZE 10 +#define PragTyp_ENCODING 11 +#define PragTyp_FOREIGN_KEY_CHECK 12 +#define PragTyp_FOREIGN_KEY_LIST 13 +#define PragTyp_INCREMENTAL_VACUUM 14 +#define PragTyp_INDEX_INFO 15 +#define PragTyp_INDEX_LIST 16 +#define PragTyp_INTEGRITY_CHECK 17 +#define PragTyp_JOURNAL_MODE 18 +#define PragTyp_JOURNAL_SIZE_LIMIT 19 +#define PragTyp_LOCK_PROXY_FILE 20 +#define PragTyp_LOCKING_MODE 21 +#define PragTyp_PAGE_COUNT 22 +#define PragTyp_MMAP_SIZE 23 +#define PragTyp_PAGE_SIZE 24 +#define PragTyp_SECURE_DELETE 25 +#define PragTyp_SHRINK_MEMORY 26 +#define PragTyp_SOFT_HEAP_LIMIT 27 +#define PragTyp_STATS 28 +#define PragTyp_SYNCHRONOUS 29 +#define PragTyp_TABLE_INFO 30 +#define PragTyp_TEMP_STORE 31 +#define PragTyp_TEMP_STORE_DIRECTORY 32 +#define PragTyp_THREADS 33 +#define PragTyp_WAL_AUTOCHECKPOINT 34 +#define PragTyp_WAL_CHECKPOINT 35 +#define PragTyp_ACTIVATE_EXTENSIONS 36 +#define PragTyp_HEXKEY 37 +#define PragTyp_KEY 38 +#define PragTyp_REKEY 39 +#define PragTyp_LOCK_STATUS 40 +#define PragTyp_PARSER_TRACE 41 +#define PragFlag_NeedSchema 0x01 +#define PragFlag_ReadOnly 0x02 +static const struct sPragmaNames { + const char *const zName; /* Name of pragma */ + u8 ePragTyp; /* PragTyp_XXX value */ + u8 mPragFlag; /* Zero or more PragFlag_XXX values */ + u32 iArg; /* Extra argument */ +} aPragmaNames[] = { +#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) + { /* zName: */ "activate_extensions", + /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "application_id", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ 0, + /* iArg: */ BTREE_APPLICATION_ID }, +#endif +#if !defined(SQLITE_OMIT_AUTOVACUUM) + { /* zName: */ "auto_vacuum", + /* ePragTyp: */ PragTyp_AUTO_VACUUM, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) + { /* zName: */ "automatic_index", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_AutoIndex }, +#endif +#endif + { /* zName: */ "busy_timeout", + /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "cache_size", + /* ePragTyp: */ PragTyp_CACHE_SIZE, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "cache_spill", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_CacheSpill }, +#endif + { /* zName: */ "case_sensitive_like", + /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "checkpoint_fullfsync", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_CkptFullFSync }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "collation_list", + /* ePragTyp: */ PragTyp_COLLATION_LIST, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) + { /* zName: */ "compile_options", + /* ePragTyp: */ PragTyp_COMPILE_OPTIONS, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "count_changes", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_CountRows }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN + { /* zName: */ "data_store_directory", + /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "data_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ PragFlag_ReadOnly, + /* iArg: */ BTREE_DATA_VERSION }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "database_list", + /* ePragTyp: */ PragTyp_DATABASE_LIST, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) + { /* zName: */ "default_cache_size", + /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + { /* zName: */ "defer_foreign_keys", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_DeferFKs }, +#endif +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "empty_result_callbacks", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_NullCallback }, +#endif +#if !defined(SQLITE_OMIT_UTF16) + { /* zName: */ "encoding", + /* ePragTyp: */ PragTyp_ENCODING, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + { /* zName: */ "foreign_key_check", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FOREIGN_KEY) + { /* zName: */ "foreign_key_list", + /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) + { /* zName: */ "foreign_keys", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_ForeignKeys }, +#endif +#endif +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "freelist_count", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ PragFlag_ReadOnly, + /* iArg: */ BTREE_FREE_PAGE_COUNT }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "full_column_names", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_FullColNames }, + { /* zName: */ "fullfsync", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_FullFSync }, +#endif +#if defined(SQLITE_HAS_CODEC) + { /* zName: */ "hexkey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "hexrekey", + /* ePragTyp: */ PragTyp_HEXKEY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if !defined(SQLITE_OMIT_CHECK) + { /* zName: */ "ignore_check_constraints", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_IgnoreChecks }, +#endif +#endif +#if !defined(SQLITE_OMIT_AUTOVACUUM) + { /* zName: */ "incremental_vacuum", + /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "index_info", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "index_list", + /* ePragTyp: */ PragTyp_INDEX_LIST, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "index_xinfo", + /* ePragTyp: */ PragTyp_INDEX_INFO, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 1 }, +#endif +#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) + { /* zName: */ "integrity_check", + /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "journal_mode", + /* ePragTyp: */ PragTyp_JOURNAL_MODE, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "journal_size_limit", + /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if defined(SQLITE_HAS_CODEC) + { /* zName: */ "key", + /* ePragTyp: */ PragTyp_KEY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "legacy_file_format", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_LegacyFileFmt }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE + { /* zName: */ "lock_proxy_file", + /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + { /* zName: */ "lock_status", + /* ePragTyp: */ PragTyp_LOCK_STATUS, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "locking_mode", + /* ePragTyp: */ PragTyp_LOCKING_MODE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "max_page_count", + /* ePragTyp: */ PragTyp_PAGE_COUNT, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "mmap_size", + /* ePragTyp: */ PragTyp_MMAP_SIZE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "page_count", + /* ePragTyp: */ PragTyp_PAGE_COUNT, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, + { /* zName: */ "page_size", + /* ePragTyp: */ PragTyp_PAGE_SIZE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if defined(SQLITE_DEBUG) + { /* zName: */ "parser_trace", + /* ePragTyp: */ PragTyp_PARSER_TRACE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "query_only", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_QueryOnly }, +#endif +#if !defined(SQLITE_OMIT_INTEGRITY_CHECK) + { /* zName: */ "quick_check", + /* ePragTyp: */ PragTyp_INTEGRITY_CHECK, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "read_uncommitted", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_ReadUncommitted }, + { /* zName: */ "recursive_triggers", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_RecTriggers }, +#endif +#if defined(SQLITE_HAS_CODEC) + { /* zName: */ "rekey", + /* ePragTyp: */ PragTyp_REKEY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "reverse_unordered_selects", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_ReverseOrder }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "schema_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ 0, + /* iArg: */ BTREE_SCHEMA_VERSION }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "secure_delete", + /* ePragTyp: */ PragTyp_SECURE_DELETE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "short_column_names", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_ShortColNames }, +#endif + { /* zName: */ "shrink_memory", + /* ePragTyp: */ PragTyp_SHRINK_MEMORY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "soft_heap_limit", + /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if defined(SQLITE_DEBUG) + { /* zName: */ "sql_trace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_SqlTrace }, +#endif +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "stats", + /* ePragTyp: */ PragTyp_STATS, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "synchronous", + /* ePragTyp: */ PragTyp_SYNCHRONOUS, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + { /* zName: */ "table_info", + /* ePragTyp: */ PragTyp_TABLE_INFO, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) + { /* zName: */ "temp_store", + /* ePragTyp: */ PragTyp_TEMP_STORE, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "temp_store_directory", + /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#endif + { /* zName: */ "threads", + /* ePragTyp: */ PragTyp_THREADS, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) + { /* zName: */ "user_version", + /* ePragTyp: */ PragTyp_HEADER_VALUE, + /* ePragFlag: */ 0, + /* iArg: */ BTREE_USER_VERSION }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) +#if defined(SQLITE_DEBUG) + { /* zName: */ "vdbe_addoptrace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_VdbeAddopTrace }, + { /* zName: */ "vdbe_debug", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace }, + { /* zName: */ "vdbe_eqp", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_VdbeEQP }, + { /* zName: */ "vdbe_listing", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_VdbeListing }, + { /* zName: */ "vdbe_trace", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_VdbeTrace }, +#endif +#endif +#if !defined(SQLITE_OMIT_WAL) + { /* zName: */ "wal_autocheckpoint", + /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT, + /* ePragFlag: */ 0, + /* iArg: */ 0 }, + { /* zName: */ "wal_checkpoint", + /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, + /* ePragFlag: */ PragFlag_NeedSchema, + /* iArg: */ 0 }, +#endif +#if !defined(SQLITE_OMIT_FLAG_PRAGMAS) + { /* zName: */ "writable_schema", + /* ePragTyp: */ PragTyp_FLAG, + /* ePragFlag: */ 0, + /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, +#endif +}; +/* Number of pragmas: 59 on by default, 72 total. */ diff --git a/src/prepare.c b/src/prepare.c index 97be900..a55a0fe 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -67,7 +67,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 ){ corruptSchema(pData, argv[0], 0); - }else if( argv[2] && argv[2][0] ){ + }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data @@ -98,8 +98,8 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ } } sqlite3_finalize(pStmt); - }else if( argv[0]==0 ){ - corruptSchema(pData, 0, 0); + }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){ + corruptSchema(pData, argv[0], 0); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE diff --git a/src/printf.c b/src/printf.c index 428c959..1d50d77 100644 --- a/src/printf.c +++ b/src/printf.c @@ -138,6 +138,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ ** Set the StrAccum object to an error mode. */ static void setStrAccumError(StrAccum *p, u8 eError){ + assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG ); p->accError = eError; p->nAlloc = 0; } @@ -212,13 +213,6 @@ void sqlite3VXPrintf( PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ -#ifdef SQLITE_ENABLE_API_ARMOR - if( ap==0 ){ - (void)SQLITE_MISUSE_BKPT; - sqlite3StrAccumReset(pAccum); - return; - } -#endif bufpt = 0; if( bFlags ){ if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){ @@ -259,7 +253,6 @@ void sqlite3VXPrintf( } }while( !done && (c=(*++fmt))!=0 ); /* Get the field width */ - width = 0; if( c=='*' ){ if( bArgList ){ width = (int)getIntArg(pArgList); @@ -268,18 +261,21 @@ void sqlite3VXPrintf( } if( width<0 ){ flag_leftjustify = 1; - width = -width; + width = width >= -2147483647 ? -width : 0; } c = *++fmt; }else{ + unsigned wx = 0; while( c>='0' && c<='9' ){ - width = width*10 + c - '0'; + wx = wx*10 + c - '0'; c = *++fmt; } + testcase( wx>0x7fffffff ); + width = wx & 0x7fffffff; } + /* Get the precision */ if( c=='.' ){ - precision = 0; c = *++fmt; if( c=='*' ){ if( bArgList ){ @@ -287,13 +283,18 @@ void sqlite3VXPrintf( }else{ precision = va_arg(ap,int); } - if( precision<0 ) precision = -precision; c = *++fmt; + if( precision<0 ){ + precision = precision >= -2147483647 ? -precision : -1; + } }else{ + unsigned px = 0; while( c>='0' && c<='9' ){ - precision = precision*10 + c - '0'; + px = px*10 + c - '0'; c = *++fmt; } + testcase( px>0x7fffffff ); + precision = px & 0x7fffffff; } }else{ precision = -1; @@ -457,7 +458,8 @@ void sqlite3VXPrintf( else prefix = 0; } if( xtype==etGENERIC && precision>0 ) precision--; - for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){} + testcase( precision>0xfff ); + for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){} if( xtype==etFLOAT ) realvalue += rounder; /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; @@ -512,8 +514,9 @@ void sqlite3VXPrintf( }else{ e2 = exp; } - if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){ - bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 ); + if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){ + bufpt = zExtra + = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 ); if( bufpt==0 ){ setStrAccumError(pAccum, STRACCUM_NOMEM); return; @@ -745,13 +748,13 @@ void sqlite3VXPrintf( */ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ char *zNew; - assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */ + assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ if( p->accError ){ testcase(p->accError==STRACCUM_TOOBIG); testcase(p->accError==STRACCUM_NOMEM); return 0; } - if( !p->useMalloc ){ + if( p->mxAlloc==0 ){ N = p->nAlloc - p->nChar - 1; setStrAccumError(p, STRACCUM_TOOBIG); return N; @@ -771,10 +774,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ }else{ p->nAlloc = (int)szNew; } - if( p->useMalloc==1 ){ + if( p->db ){ zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc); }else{ - zNew = sqlite3_realloc(zOld, p->nAlloc); + zNew = sqlite3_realloc64(zOld, p->nAlloc); } if( zNew ){ assert( p->zText!=0 || p->nChar==0 ); @@ -794,7 +797,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ ** Append N copies of character c to the given string buffer. */ void sqlite3AppendChar(StrAccum *p, int N, char c){ - if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return; + testcase( p->nChar + (i64)N > 0x7fffffff ); + if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ + return; + } while( (N--)>0 ) p->zText[p->nChar++] = c; } @@ -819,7 +825,7 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){ ** size of the memory allocation for StrAccum if necessary. */ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ - assert( z!=0 ); + assert( z!=0 || N==0 ); assert( p->zText!=0 || p->nChar==0 || p->accError ); assert( N>=0 ); assert( p->accError==0 || p->nAlloc==0 ); @@ -848,12 +854,8 @@ void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){ char *sqlite3StrAccumFinish(StrAccum *p){ if( p->zText ){ p->zText[p->nChar] = 0; - if( p->useMalloc && p->zText==p->zBase ){ - if( p->useMalloc==1 ){ - p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); - }else{ - p->zText = sqlite3_malloc(p->nChar+1); - } + if( p->mxAlloc>0 && p->zText==p->zBase ){ + p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 ); if( p->zText ){ memcpy(p->zText, p->zBase, p->nChar+1); }else{ @@ -869,25 +871,31 @@ char *sqlite3StrAccumFinish(StrAccum *p){ */ void sqlite3StrAccumReset(StrAccum *p){ if( p->zText!=p->zBase ){ - if( p->useMalloc==1 ){ - sqlite3DbFree(p->db, p->zText); - }else{ - sqlite3_free(p->zText); - } + sqlite3DbFree(p->db, p->zText); } p->zText = 0; } /* -** Initialize a string accumulator +** Initialize a string accumulator. +** +** p: The accumulator to be initialized. +** db: Pointer to a database connection. May be NULL. Lookaside +** memory is used if not NULL. db->mallocFailed is set appropriately +** when not NULL. +** zBase: An initial buffer. May be NULL in which case the initial buffer +** is malloced. +** n: Size of zBase in bytes. If total space requirements never exceed +** n then no memory allocations ever occur. +** mx: Maximum number of bytes to accumulate. If mx==0 then no memory +** allocations will ever occur. */ -void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){ +void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){ p->zText = p->zBase = zBase; - p->db = 0; + p->db = db; p->nChar = 0; p->nAlloc = n; p->mxAlloc = mx; - p->useMalloc = 1; p->accError = 0; } @@ -900,9 +908,8 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ char zBase[SQLITE_PRINT_BUF_SIZE]; StrAccum acc; assert( db!=0 ); - sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), + sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); - acc.db = db; sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap); z = sqlite3StrAccumFinish(&acc); if( acc.accError==STRACCUM_NOMEM ){ @@ -960,8 +967,7 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){ #ifndef SQLITE_OMIT_AUTOINIT if( sqlite3_initialize() ) return 0; #endif - sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); - acc.useMalloc = 2; + sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH); sqlite3VXPrintf(&acc, 0, zFormat, ap); z = sqlite3StrAccumFinish(&acc); return z; @@ -1002,12 +1008,11 @@ char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){ #ifdef SQLITE_ENABLE_API_ARMOR if( zBuf==0 || zFormat==0 ) { (void)SQLITE_MISUSE_BKPT; - if( zBuf && n>0 ) zBuf[0] = 0; + if( zBuf ) zBuf[0] = 0; return zBuf; } #endif - sqlite3StrAccumInit(&acc, zBuf, n, 0); - acc.useMalloc = 0; + sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); sqlite3VXPrintf(&acc, 0, zFormat, ap); return sqlite3StrAccumFinish(&acc); } @@ -1033,8 +1038,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ StrAccum acc; /* String accumulator */ char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */ - sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); - acc.useMalloc = 0; + sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0); sqlite3VXPrintf(&acc, 0, zFormat, ap); sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, sqlite3StrAccumFinish(&acc)); @@ -1052,7 +1056,7 @@ void sqlite3_log(int iErrCode, const char *zFormat, ...){ } } -#if defined(SQLITE_DEBUG) +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) /* ** A version of printf() that understands %lld. Used for debugging. ** The printf() built into some versions of windows does not understand %lld @@ -1062,8 +1066,7 @@ void sqlite3DebugPrintf(const char *zFormat, ...){ va_list ap; StrAccum acc; char zBuf[500]; - sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); - acc.useMalloc = 0; + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); va_start(ap,zFormat); sqlite3VXPrintf(&acc, 0, zFormat, ap); va_end(ap); @@ -1090,7 +1093,7 @@ void sqlite3DebugPrintf(const char *zFormat, ...){ ** is not the last item in the tree. */ TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ if( p==0 ){ - p = sqlite3_malloc( sizeof(*p) ); + p = sqlite3_malloc64( sizeof(*p) ); if( p==0 ) return 0; memset(p, 0, sizeof(*p)); }else{ @@ -1113,8 +1116,7 @@ void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ int i; StrAccum acc; char zBuf[500]; - sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0); - acc.useMalloc = 0; + sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); if( p ){ for(i=0; iiLevel && ibLine)-1; i++){ sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4); diff --git a/src/resolve.c b/src/resolve.c index d4bd548..23636ea 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -79,7 +79,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){ ** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; ** ** The nSubquery parameter specifies how many levels of subquery the -** alias is removed from the original expression. The usually value is +** alias is removed from the original expression. The usual value is ** zero but it might be more if the alias is contained within a subquery ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION ** structures must be increased by the nSubquery amount. @@ -99,7 +99,6 @@ static void resolveAlias( assert( iCol>=0 && iColnExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); - assert( pOrig->flags & EP_Resolved ); db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); if( pDup==0 ) return; @@ -247,9 +246,10 @@ static int lookupName( testcase( pNC->ncFlags & NC_PartIdx ); testcase( pNC->ncFlags & NC_IsCheck ); if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){ - /* Silently ignore database qualifiers inside CHECK constraints and partial - ** indices. Do not raise errors because that might break legacy and - ** because it does not hurt anything to just ignore the database name. */ + /* Silently ignore database qualifiers inside CHECK constraints and + ** partial indices. Do not raise errors because that might break + ** legacy and because it does not hurt anything to just ignore the + ** database name. */ zDb = 0; }else{ for(i=0; inDb; i++){ @@ -320,7 +320,8 @@ static int lookupName( if( pMatch ){ pExpr->iTable = pMatch->iCursor; pExpr->pTab = pMatch->pTab; - assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */ + /* RIGHT JOIN not (yet) supported */ + assert( (pMatch->jointype & JT_RIGHT)==0 ); if( (pMatch->jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } @@ -641,7 +642,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->affinity = SQLITE_AFF_INTEGER; break; } -#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */ +#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) + && !defined(SQLITE_OMIT_SUBQUERY) */ /* A lone identifier is the name of a column. */ @@ -706,19 +708,20 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ if( n==2 ){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ - sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a " - "constant between 0.0 and 1.0"); + sqlite3ErrorMsg(pParse, + "second argument to likelihood() must be a " + "constant between 0.0 and 1.0"); pNC->nErr++; } }else{ - /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to - ** likelihood(X, 0.0625). - ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for - ** likelihood(X,0.0625). - ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for - ** likelihood(X,0.9375). - ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to - ** likelihood(X,0.9375). */ + /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is + ** equivalent to likelihood(X, 0.0625). + ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is + ** short-hand for likelihood(X,0.0625). + ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand + ** for likelihood(X,0.9375). + ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent + ** to likelihood(X,0.9375). */ /* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */ pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120; } @@ -735,7 +738,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ return WRC_Prune; } #endif - if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant); + if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ){ + ExprSetProperty(pExpr,EP_ConstFunc); + } } if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); @@ -987,9 +992,11 @@ static int resolveCompoundOrderBy( if( pItem->pExpr==pE ){ pItem->pExpr = pNew; }else{ - assert( pItem->pExpr->op==TK_COLLATE ); - assert( pItem->pExpr->pLeft==pE ); - pItem->pExpr->pLeft = pNew; + Expr *pParent = pItem->pExpr; + assert( pParent->op==TK_COLLATE ); + while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft; + assert( pParent->pLeft==pE ); + pParent->pLeft = pNew; } sqlite3ExprDelete(db, pE); pItem->u.x.iOrderByCol = (u16)iCol; @@ -1046,7 +1053,8 @@ int sqlite3ResolveOrderGroupBy( resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); return 1; } - resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0); + resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, + zType,0); } } return 0; @@ -1179,6 +1187,20 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ sqlite3ResolveExprNames(&sNC, p->pOffset) ){ return WRC_Abort; } + + /* If the SF_Converted flags is set, then this Select object was + ** was created by the convertCompoundSelectToSubquery() function. + ** In this case the ORDER BY clause (p->pOrderBy) should be resolved + ** as if it were part of the sub-query, not the parent. This block + ** moves the pOrderBy down to the sub-query. It will be moved back + ** after the names have been resolved. */ + if( p->selFlags & SF_Converted ){ + Select *pSub = p->pSrc->a[0].pSelect; + assert( p->pSrc->nSrc==1 && p->pOrderBy ); + assert( pSub->pPrior && pSub->pOrderBy==0 ); + pSub->pOrderBy = p->pOrderBy; + p->pOrderBy = 0; + } /* Recursively resolve names in all subqueries */ @@ -1261,12 +1283,30 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ sNC.pNext = 0; sNC.ncFlags |= NC_AllowAgg; + /* If this is a converted compound query, move the ORDER BY clause from + ** the sub-query back to the parent query. At this point each term + ** within the ORDER BY clause has been transformed to an integer value. + ** These integers will be replaced by copies of the corresponding result + ** set expressions by the call to resolveOrderGroupBy() below. */ + if( p->selFlags & SF_Converted ){ + Select *pSub = p->pSrc->a[0].pSelect; + p->pOrderBy = pSub->pOrderBy; + pSub->pOrderBy = 0; + } + /* Process the ORDER BY clause for singleton SELECT statements. ** The ORDER BY clause for compounds SELECT statements is handled ** below, after all of the result-sets for all of the elements of ** the compound have been resolved. + ** + ** If there is an ORDER BY clause on a term of a compound-select other + ** than the right-most term, then that is a syntax error. But the error + ** is not detected until much later, and so we need to go ahead and + ** resolve those symbols on the incorrect ORDER BY for consistency. */ - if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){ + if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */ + && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") + ){ return WRC_Abort; } if( db->mallocFailed ){ diff --git a/src/select.c b/src/select.c index 39a0550..beb52c7 100644 --- a/src/select.c +++ b/src/select.c @@ -111,7 +111,6 @@ Select *sqlite3SelectNew( Select standin; sqlite3 *db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); - assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */ if( pNew==0 ){ assert( db->mallocFailed ); pNew = &standin; @@ -131,7 +130,7 @@ Select *sqlite3SelectNew( pNew->op = TK_SELECT; pNew->pLimit = pLimit; pNew->pOffset = pOffset; - assert( pOffset==0 || pLimit!=0 ); + assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 ); pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; if( db->mallocFailed ) { @@ -563,20 +562,17 @@ static void pushOntoSorter( } sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); if( pSelect->iLimit ){ - int addr1, addr2; + int addr; int iLimit; if( pSelect->iOffset ){ iLimit = pSelect->iOffset+1; }else{ iLimit = pSelect->iLimit; } - addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); - addr2 = sqlite3VdbeAddOp0(v, OP_Goto); - sqlite3VdbeJumpHere(v, addr1); + addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v); sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); - sqlite3VdbeJumpHere(v, addr2); + sqlite3VdbeJumpHere(v, addr); } } @@ -973,7 +969,7 @@ static void selectInnerLoop( ** the output for us. */ if( pSort==0 && p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); } } @@ -1384,7 +1380,7 @@ static const char *columnTypeImpl( ** of the SELECT statement. Return the declaration type and origin ** data for the result-set column of the sub-select. */ - if( iCol>=0 && ALWAYS(iColpEList->nExpr) ){ + if( iCol>=0 && iColpEList->nExpr ){ /* If iCol is less than zero, then the expression requests the ** rowid of the sub-select or view. This expression is legal (see ** test case misc2.2.2) - it always evaluates to NULL. @@ -1704,12 +1700,14 @@ static void selectAddColumnTypeAndCollation( a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ p = a[i].pExpr; - pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst)); + if( pCol->zType==0 ){ + pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst)); + } szAll += pCol->szEst; pCol->affinity = sqlite3ExprAffinity(p); if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE; pColl = sqlite3ExprCollSeq(pParse, p); - if( pColl ){ + if( pColl && pCol->zColl==0 ){ pCol->zColl = sqlite3DbStrDup(db, pColl->zName); } } @@ -1826,7 +1824,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ sqlite3ExprCode(pParse, p->pLimit, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); VdbeComment((v, "LIMIT counter")); - sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); } if( p->pOffset ){ p->iOffset = iOffset = ++pParse->nMem; @@ -2045,7 +2043,7 @@ static void generateWithRecursiveQuery( selectInnerLoop(pParse, p, p->pEList, iCurrent, 0, 0, pDest, addrCont, addrBreak); if( regLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); VdbeCoverage(v); } sqlite3VdbeResolveLabel(v, addrCont); @@ -2111,8 +2109,7 @@ static int multiSelectValues( int nExpr = p->pEList->nExpr; int nRow = 1; int rc = 0; - assert( p->pNext==0 ); - assert( p->selFlags & SF_AllValues ); + assert( p->selFlags & SF_MultiValue ); do{ assert( p->selFlags & SF_Values ); assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); @@ -2221,7 +2218,7 @@ static int multiSelect( /* Special handling for a compound-select that originates as a VALUES clause. */ - if( p->selFlags & SF_AllValues ){ + if( p->selFlags & SF_MultiValue ){ rc = multiSelectValues(pParse, p, &dest); goto multi_select_end; } @@ -2270,7 +2267,7 @@ static int multiSelect( p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; if( p->iLimit ){ - addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v); + addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v); VdbeComment((v, "Jump ahead if LIMIT reached")); } explainSetInteger(iSub2, pParse->iNextSelectId); @@ -2606,7 +2603,7 @@ static int generateOutputSubroutine( */ case SRT_Set: { int r1; - assert( pIn->nSdst==1 ); + assert( pIn->nSdst==1 || pParse->nErr>0 ); pDest->affSdst = sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); r1 = sqlite3GetTempReg(pParse); @@ -2632,7 +2629,7 @@ static int generateOutputSubroutine( ** of the scan loop. */ case SRT_Mem: { - assert( pIn->nSdst==1 ); + assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 ); sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); /* The LIMIT clause will jump out of the loop for us */ break; @@ -2647,7 +2644,7 @@ static int generateOutputSubroutine( pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst); pDest->nSdst = pIn->nSdst; } - sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst); + sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); break; } @@ -2671,7 +2668,7 @@ static int generateOutputSubroutine( /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ - sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); } /* Generate the subroutine return @@ -2863,8 +2860,10 @@ static int multiSelectOrderBy( if( aPermute ){ struct ExprList_item *pItem; for(i=0, pItem=pOrderBy->a; iu.x.iOrderByCol>0 - && pItem->u.x.iOrderByCol<=p->pEList->nExpr ); + assert( pItem->u.x.iOrderByCol>0 ); + /* assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ) is also true + ** but only for well-formed SELECT statements. */ + testcase( pItem->u.x.iOrderByCol > p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; } pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); @@ -3074,7 +3073,7 @@ static int multiSelectOrderBy( /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ explainComposite(pParse, p->op, iSub1, iSub2, 0); - return SQLITE_OK; + return pParse->nErr!=0; } #endif @@ -3194,7 +3193,10 @@ static void substSelect( ** ** (1) The subquery and the outer query do not both use aggregates. ** -** (2) The subquery is not an aggregate or the outer query is not a join. +** (2) The subquery is not an aggregate or (2a) the outer query is not a join +** and (2b) the outer query does not use subqueries other than the one +** FROM-clause subquery that is a candidate for flattening. (2b is +** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) ** ** (3) The subquery is not the right operand of a left outer join ** (Originally ticket #306. Strengthened by ticket #3300) @@ -3331,8 +3333,17 @@ static int flattenSubquery( iParent = pSubitem->iCursor; pSub = pSubitem->pSelect; assert( pSub!=0 ); - if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ - if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ + if( subqueryIsAgg ){ + if( isAgg ) return 0; /* Restriction (1) */ + if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ + if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) + || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 + || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 + ){ + return 0; /* Restriction (2b) */ + } + } + pSubSrc = pSub->pSrc; assert( pSubSrc ); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, @@ -3874,7 +3885,10 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ pNew->pOrderBy = 0; p->pPrior = 0; p->pNext = 0; + p->pWith = 0; p->selFlags &= ~SF_Compound; + assert( (p->selFlags & SF_Converted)==0 ); + p->selFlags |= SF_Converted; assert( pNew->pPrior!=0 ); pNew->pPrior->pNext = pNew; pNew->pLimit = 0; @@ -4026,7 +4040,7 @@ static int withExpand( for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); pEList = pLeft->pEList; if( pCte->pCols ){ - if( pEList->nExpr!=pCte->pCols->nExpr ){ + if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){ sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", pCte->zName, pEList->nExpr, pCte->pCols->nExpr ); @@ -4153,7 +4167,7 @@ static int selectExpander(Walker *pWalker, Select *p){ /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); - sqlite3WalkSelect(pWalker, pSel); + if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; pTab->nRef = 1; @@ -4410,7 +4424,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; - if( (pSelect->selFlags & SF_AllValues)==0 ){ + if( (pSelect->selFlags & SF_MultiValue)==0 ){ w.xSelectCallback2 = selectPopWith; } sqlite3WalkSelect(&w, pSelect); @@ -4596,7 +4610,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ } if( pF->iDistinct>=0 ){ addrNext = sqlite3VdbeMakeLabel(v); - assert( nArg==1 ); + testcase( nArg==0 ); /* Error condition */ + testcase( nArg>1 ); /* Also an error */ codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); } if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ @@ -4752,6 +4767,13 @@ int sqlite3Select( } isAgg = (p->selFlags & SF_Aggregate)!=0; assert( pEList!=0 ); +#if SELECTTRACE_ENABLED + if( sqlite3SelectTrace & 0x100 ){ + SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif + /* Begin generating code. */ @@ -5464,10 +5486,9 @@ int sqlite3Select( */ sqlite3VdbeResolveLabel(v, iEnd); - /* The SELECT was successfully coded. Set the return code to 0 - ** to indicate no errors. - */ - rc = 0; + /* The SELECT has been coded. If there is an error in the Parse structure, + ** set the return code to 1. Otherwise 0. */ + rc = (pParse->nErr>0); /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. @@ -5497,9 +5518,9 @@ select_end: void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; pView = sqlite3TreeViewPush(pView, moreToFollow); - sqlite3TreeViewLine(pView, "SELECT%s%s", + sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p)", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), - ((p->selFlags & SF_Aggregate) ? " agg_flag" : "") + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p ); if( p->pSrc && p->pSrc->nSrc ) n++; if( p->pWhere ) n++; @@ -5518,7 +5539,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ struct SrcList_item *pItem = &p->pSrc->a[i]; StrAccum x; char zLine[100]; - sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0); + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); if( pItem->zDatabase ){ sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); diff --git a/src/shell.c b/src/shell.c index 02c27f4..7db8dbd 100644 --- a/src/shell.c +++ b/src/shell.c @@ -24,6 +24,13 @@ #include "msvc.h" #endif +/* +** No support for loadable extensions in VxWorks. +*/ +#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION +# define SQLITE_OMIT_LOAD_EXTENSION 1 +#endif + /* ** Enable large-file support for fopen() and friends on unix. */ @@ -107,10 +114,15 @@ */ extern int isatty(int); -/* popen and pclose are not C89 functions and so are sometimes omitted from -** the header */ -extern FILE *popen(const char*,const char*); -extern int pclose(FILE*); +#if !defined(__RTP__) && !defined(_WRS_KERNEL) + /* popen and pclose are not C89 functions and so are sometimes omitted from + ** the header */ + extern FILE *popen(const char*,const char*); + extern int pclose(FILE*); +#else +# define SQLITE_OMIT_POPEN 1 +#endif + #endif #if defined(_WIN32_WCE) @@ -126,6 +138,26 @@ extern int pclose(FILE*); #define IsDigit(X) isdigit((unsigned char)X) #define ToLower(X) (char)tolower((unsigned char)X) +/* On Windows, we normally run with output mode of TEXT so that \n characters +** are automatically translated into \r\n. However, this behavior needs +** to be disabled in some cases (ex: when generating CSV output and when +** rendering quoted strings that contain \n characters). The following +** routines take care of that. +*/ +#if defined(_WIN32) || defined(WIN32) +static void setBinaryMode(FILE *out){ + fflush(out); + _setmode(_fileno(out), _O_BINARY); +} +static void setTextMode(FILE *out){ + fflush(out); + _setmode(_fileno(out), _O_TEXT); +} +#else +# define setBinaryMode(X) +# define setTextMode(X) +#endif + /* True if the timer is enabled */ static int enableTimer = 0; @@ -145,11 +177,19 @@ static sqlite3_int64 timeOfDay(void){ return t; } -#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \ - && !defined(__minux) +#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) #include #include +/* VxWorks does not support getrusage() as far as we can determine */ +#if defined(_WRS_KERNEL) || defined(__RTP__) +struct rusage { + struct timeval ru_utime; /* user CPU time used */ + struct timeval ru_stime; /* system CPU time used */ +}; +#define getrusage(A,B) memset(B,0,sizeof(*B)) +#endif + /* Saved resource information for the beginning of an operation */ static struct rusage sBegin; /* CPU time at start */ static sqlite3_int64 iBegin; /* Wall-clock time at start */ @@ -175,8 +215,8 @@ static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ */ static void endTimer(void){ if( enableTimer ){ - struct rusage sEnd; sqlite3_int64 iEnd = timeOfDay(); + struct rusage sEnd; getrusage(RUSAGE_SELF, &sEnd); printf("Run Time: real %.3f user %f sys %f\n", (iEnd - iBegin)*0.001, @@ -296,7 +336,7 @@ static int stdin_is_interactive = 1; ** to this database a static variable so that it can be accessed ** by the SIGINT handler to interrupt database processing. */ -static sqlite3 *db = 0; +static sqlite3 *globalDb = 0; /* ** True if an interrupt (Control-C) has been received. @@ -330,7 +370,7 @@ static FILE *iotrace = 0; ** is written to iotrace. */ #ifdef SQLITE_ENABLE_IOTRACE -static void iotracePrintf(const char *zFormat, ...){ +static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ va_list ap; char *z; if( iotrace==0 ) return; @@ -487,6 +527,7 @@ struct ShellState { int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ int statsOn; /* True to display memory stats before each finalize */ int scanstatsOn; /* True to display scan stats before each finalize */ + int backslashOn; /* Resolve C-style \x escapes in SQL input text */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ @@ -604,6 +645,7 @@ static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ static void output_quoted_string(FILE *out, const char *z){ int i; int nSingle = 0; + setBinaryMode(out); for(i=0; z[i]; i++){ if( z[i]=='\'' ) nSingle++; } @@ -626,6 +668,7 @@ static void output_quoted_string(FILE *out, const char *z){ } fprintf(out,"'"); } + setTextMode(out); } /* @@ -762,7 +805,7 @@ static void interrupt_handler(int NotUsed){ UNUSED_PARAMETER(NotUsed); seenInterrupt++; if( seenInterrupt>2 ) exit(1); - if( db ) sqlite3_interrupt(db); + if( globalDb ) sqlite3_interrupt(globalDb); } #endif @@ -928,10 +971,7 @@ static int shell_callback( break; } case MODE_Csv: { -#if defined(WIN32) || defined(_WIN32) - fflush(p->out); - _setmode(_fileno(p->out), _O_BINARY); -#endif + setBinaryMode(p->out); if( p->cnt++==0 && p->showHeader ){ for(i=0; iout, "%s", p->rowSeparator); } -#if defined(WIN32) || defined(_WIN32) - fflush(p->out); - _setmode(_fileno(p->out), _O_TEXT); -#endif + setTextMode(p->out); break; } case MODE_Insert: { p->cnt++; if( azArg==0 ) break; - fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); + fprintf(p->out,"INSERT INTO %s",p->zDestTable); + if( p->showHeader ){ + fprintf(p->out,"("); + for(i=0; i0 ? ",": ""; + fprintf(p->out, "%s%s", zSep, azCol[i]); + } + fprintf(p->out,")"); + } + fprintf(p->out," VALUES("); for(i=0; i0 ? ",": ""; if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ @@ -1154,7 +1200,7 @@ static char *save_err_msg( sqlite3 *db /* Database to query */ ){ int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); - char *zErrMsg = sqlite3_malloc(nErrMsg); + char *zErrMsg = sqlite3_malloc64(nErrMsg); if( zErrMsg ){ memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); } @@ -1391,8 +1437,8 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){ /* Grow the p->aiIndent array as required */ if( iOp>=nAlloc ){ nAlloc += 100; - p->aiIndent = (int*)sqlite3_realloc(p->aiIndent, nAlloc*sizeof(int)); - abYield = (int*)sqlite3_realloc(abYield, nAlloc*sizeof(int)); + p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int)); + abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int)); } abYield[iOp] = str_in_array(zOp, azYield); p->aiIndent[iOp] = 0; @@ -1509,7 +1555,7 @@ static int shell_exec( if( xCallback ){ /* allocate space for col name ptr, value ptr, and type */ int nCol = sqlite3_column_count(pStmt); - void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1); + void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1); if( !pData ){ rc = SQLITE_NOMEM; }else{ @@ -1735,8 +1781,10 @@ static int run_schema_dump_query( static char zHelp[] = ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" ".bail on|off Stop after hitting an error. Default OFF\n" + ".binary on|off Turn binary output on or off. Default OFF\n" ".clone NEWDB Clone data into NEWDB from the existing database\n" ".databases List names and files of attached databases\n" + ".dbinfo ?DB? Show status information about the database\n" ".dump ?TABLE? ... Dump the database in an SQL text format\n" " If TABLE specified, only dump tables matching\n" " LIKE pattern TABLE.\n" @@ -1749,12 +1797,13 @@ static char zHelp[] = ".headers on|off Turn display of headers on or off\n" ".help Show this message\n" ".import FILE TABLE Import data from FILE into TABLE\n" - ".indices ?TABLE? Show names of all indices\n" - " If TABLE specified, only show indices for tables\n" + ".indexes ?TABLE? Show names of all indexes\n" + " If TABLE specified, only show indexes for tables\n" " matching LIKE pattern TABLE.\n" #ifdef SQLITE_ENABLE_IOTRACE ".iotrace FILE Enable I/O diagnostic logging to FILE\n" #endif + ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" #ifndef SQLITE_OMIT_LOAD_EXTENSION ".load FILE ?ENTRY? Load an extension library\n" #endif @@ -1824,7 +1873,7 @@ static void readfileFunc( fseek(in, 0, SEEK_END); nIn = ftell(in); rewind(in); - pBuf = sqlite3_malloc( nIn ); + pBuf = sqlite3_malloc64( nIn ); if( pBuf && 1==fread(pBuf, nIn, 1, in) ){ sqlite3_result_blob(context, pBuf, nIn, sqlite3_free); }else{ @@ -1871,23 +1920,23 @@ static void open_db(ShellState *p, int keepAlive){ if( p->db==0 ){ sqlite3_initialize(); sqlite3_open(p->zDbFilename, &p->db); - db = p->db; - if( db && sqlite3_errcode(db)==SQLITE_OK ){ - sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, + globalDb = p->db; + if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){ + sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0, shellstaticFunc, 0, 0); } - if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ + if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){ fprintf(stderr,"Error: unable to open database \"%s\": %s\n", - p->zDbFilename, sqlite3_errmsg(db)); + p->zDbFilename, sqlite3_errmsg(p->db)); if( keepAlive ) return; exit(1); } #ifndef SQLITE_OMIT_LOAD_EXTENSION sqlite3_enable_load_extension(p->db, 1); #endif - sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, + sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0, readfileFunc, 0, 0); - sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0, + sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0, writefileFunc, 0, 0); } } @@ -1895,26 +1944,44 @@ static void open_db(ShellState *p, int keepAlive){ /* ** Do C-language style dequoting. ** +** \a -> alarm +** \b -> backspace ** \t -> tab ** \n -> newline +** \v -> vertical tab +** \f -> form feed ** \r -> carriage return +** \s -> space ** \" -> " -** \NNN -> ascii character NNN in octal +** \' -> ' ** \\ -> backslash +** \NNN -> ascii character NNN in octal */ static void resolve_backslashes(char *z){ int i, j; char c; while( *z && *z!='\\' ) z++; for(i=j=0; (c = z[i])!=0; i++, j++){ - if( c=='\\' ){ + if( c=='\\' && z[i+1]!=0 ){ c = z[++i]; - if( c=='n' ){ - c = '\n'; + if( c=='a' ){ + c = '\a'; + }else if( c=='b' ){ + c = '\b'; }else if( c=='t' ){ c = '\t'; + }else if( c=='n' ){ + c = '\n'; + }else if( c=='v' ){ + c = '\v'; + }else if( c=='f' ){ + c = '\f'; }else if( c=='r' ){ c = '\r'; + }else if( c=='"' ){ + c = '"'; + }else if( c=='\'' ){ + c = '\''; }else if( c=='\\' ){ c = '\\'; }else if( c>='0' && c<='7' ){ @@ -2084,7 +2151,7 @@ struct ImportCtx { static void import_append_char(ImportCtx *p, int c){ if( p->n+1>=p->nAlloc ){ p->nAlloc += p->nAlloc + 100; - p->z = sqlite3_realloc(p->z, p->nAlloc); + p->z = sqlite3_realloc64(p->z, p->nAlloc); if( p->z==0 ){ fprintf(stderr, "out of memory\n"); exit(1); @@ -2098,7 +2165,7 @@ static void import_append_char(ImportCtx *p, int c){ ** ** + Input comes from p->in. ** + Store results in p->z of length p->n. Space to hold p->z comes -** from sqlite3_malloc(). +** from sqlite3_malloc64(). ** + Use p->cSep as the column separator. The default is ",". ** + Use p->rSep as the row separator. The default is "\n". ** + Keep track of the line number in p->nLine. @@ -2106,7 +2173,7 @@ static void import_append_char(ImportCtx *p, int c){ ** EOF on end-of-file. ** + Report syntax errors on stderr */ -static char *csv_read_one_field(ImportCtx *p){ +static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ int c; int cSep = p->cColSep; int rSep = p->cRowSep; @@ -2172,7 +2239,7 @@ static char *csv_read_one_field(ImportCtx *p){ ** ** + Input comes from p->in. ** + Store results in p->z of length p->n. Space to hold p->z comes -** from sqlite3_malloc(). +** from sqlite3_malloc64(). ** + Use p->cSep as the column separator. The default is "\x1F". ** + Use p->rSep as the row separator. The default is "\x1E". ** + Keep track of the row number in p->nLine. @@ -2180,7 +2247,7 @@ static char *csv_read_one_field(ImportCtx *p){ ** EOF on end-of-file. ** + Report syntax errors on stderr */ -static char *ascii_read_one_field(ImportCtx *p){ +static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ int c; int cSep = p->cColSep; int rSep = p->cRowSep; @@ -2232,7 +2299,7 @@ static void tryToCloneData( goto end_data_xfer; } n = sqlite3_column_count(pQuery); - zInsert = sqlite3_malloc(200 + nTable + n*3); + zInsert = sqlite3_malloc64(200 + nTable + n*3); if( zInsert==0 ){ fprintf(stderr, "out of memory\n"); goto end_data_xfer; @@ -2422,7 +2489,9 @@ static void tryToClone(ShellState *p, const char *zNewDb){ */ static void output_reset(ShellState *p){ if( p->outfile[0]=='|' ){ +#ifndef SQLITE_OMIT_POPEN pclose(p->out); +#endif }else{ output_file_close(p->out); } @@ -2430,6 +2499,115 @@ static void output_reset(ShellState *p){ p->out = stdout; } +/* +** Run an SQL command and return the single integer result. +*/ +static int db_int(ShellState *p, const char *zSql){ + sqlite3_stmt *pStmt; + int res = 0; + sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ + res = sqlite3_column_int(pStmt,0); + } + sqlite3_finalize(pStmt); + return res; +} + +/* +** Convert a 2-byte or 4-byte big-endian integer into a native integer +*/ +unsigned int get2byteInt(unsigned char *a){ + return (a[0]<<8) + a[1]; +} +unsigned int get4byteInt(unsigned char *a){ + return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; +} + +/* +** Implementation of the ".info" command. +** +** Return 1 on error, 2 to exit, and 0 otherwise. +*/ +static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){ + static const struct { const char *zName; int ofst; } aField[] = { + { "file change counter:", 24 }, + { "database page count:", 28 }, + { "freelist page count:", 36 }, + { "schema cookie:", 40 }, + { "schema format:", 44 }, + { "default cache size:", 48 }, + { "autovacuum top root:", 52 }, + { "incremental vacuum:", 64 }, + { "text encoding:", 56 }, + { "user version:", 60 }, + { "application id:", 68 }, + { "software version:", 96 }, + }; + static const struct { const char *zName; const char *zSql; } aQuery[] = { + { "number of tables:", + "SELECT count(*) FROM %s WHERE type='table'" }, + { "number of indexes:", + "SELECT count(*) FROM %s WHERE type='index'" }, + { "number of triggers:", + "SELECT count(*) FROM %s WHERE type='trigger'" }, + { "number of views:", + "SELECT count(*) FROM %s WHERE type='view'" }, + { "schema size:", + "SELECT total(length(sql)) FROM %s" }, + }; + sqlite3_file *pFile; + int i; + char *zSchemaTab; + char *zDb = nArg>=2 ? azArg[1] : "main"; + unsigned char aHdr[100]; + open_db(p, 0); + if( p->db==0 ) return 1; + sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile); + if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){ + return 1; + } + i = pFile->pMethods->xRead(pFile, aHdr, 100, 0); + if( i!=SQLITE_OK ){ + fprintf(stderr, "unable to read database header\n"); + return 1; + } + i = get2byteInt(aHdr+16); + if( i==1 ) i = 65536; + fprintf(p->out, "%-20s %d\n", "database page size:", i); + fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]); + fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]); + fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]); + for(i=0; iout, "%-20s %u", aField[i].zName, val); + switch( ofst ){ + case 56: { + if( val==1 ) fprintf(p->out, " (utf8)"); + if( val==2 ) fprintf(p->out, " (utf16le)"); + if( val==3 ) fprintf(p->out, " (utf16be)"); + } + } + fprintf(p->out, "\n"); + } + if( zDb==0 ){ + zSchemaTab = sqlite3_mprintf("main.sqlite_master"); + }else if( strcmp(zDb,"temp")==0 ){ + zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master"); + }else{ + zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb); + } + for(i=0; iout, "%-20s %d\n", aQuery[i].zName, val); + } + sqlite3_free(zSchemaTab); + return 0; +} + + /* ** If an input line begins with "." then invoke this routine to ** process that line. @@ -2437,7 +2615,7 @@ static void output_reset(ShellState *p){ ** Return 1 on error, 2 to exit, and 0 otherwise. */ static int do_meta_command(char *zLine, ShellState *p){ - int i = 1; + int h = 1; int nArg = 0; int n, c; int rc = 0; @@ -2445,24 +2623,24 @@ static int do_meta_command(char *zLine, ShellState *p){ /* Parse the input line into tokens. */ - while( zLine[i] && nArg=3 && strncmp(azArg[0], "binary", n)==0 ){ + if( nArg==2 ){ + if( booleanValue(azArg[1]) ){ + setBinaryMode(p->out); + }else{ + setTextMode(p->out); + } + }else{ + fprintf(stderr, "Usage: .binary on|off\n"); + rc = 1; + } + }else + /* The undocumented ".breakpoint" command causes a call to the no-op ** routine named test_breakpoint(). */ @@ -2572,6 +2763,10 @@ static int do_meta_command(char *zLine, ShellState *p){ } }else + if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){ + rc = shell_dbinfo_command(p, nArg, azArg); + }else + if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ open_db(p, 0); /* When playing back a "dump", the content might appear in an order @@ -2759,8 +2954,8 @@ static int do_meta_command(char *zLine, ShellState *p){ int nSep; /* Number of bytes in p->colSeparator[] */ char *zSql; /* An SQL statement */ ImportCtx sCtx; /* Reader context */ - char *(*xRead)(ImportCtx*); /* Procedure to read one value */ - int (*xCloser)(FILE*); /* Procedure to close th3 connection */ + char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */ + int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */ if( nArg!=3 ){ fprintf(stderr, "Usage: .import FILE TABLE\n"); @@ -2802,9 +2997,14 @@ static int do_meta_command(char *zLine, ShellState *p){ sCtx.zFile = zFile; sCtx.nLine = 1; if( sCtx.zFile[0]=='|' ){ +#ifdef SQLITE_OMIT_POPEN + fprintf(stderr, "Error: pipes are not supported in this OS\n"); + return 1; +#else sCtx.in = popen(sCtx.zFile+1, "r"); sCtx.zFile = ""; xCloser = pclose; +#endif }else{ sCtx.in = fopen(sCtx.zFile, "rb"); xCloser = fclose; @@ -2829,7 +3029,7 @@ static int do_meta_command(char *zLine, ShellState *p){ nByte = strlen30(zSql); rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */ - if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){ + if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){ char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable); char cSep = '('; while( xRead(&sCtx) ){ @@ -2849,7 +3049,7 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_free(zCreate); if( rc ){ fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable, - sqlite3_errmsg(db)); + sqlite3_errmsg(p->db)); sqlite3_free(sCtx.z); xCloser(sCtx.in); return 1; @@ -2859,7 +3059,7 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_free(zSql); if( rc ){ if (pStmt) sqlite3_finalize(pStmt); - fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); + fprintf(stderr,"Error: %s\n", sqlite3_errmsg(p->db)); xCloser(sCtx.in); return 1; } @@ -2867,7 +3067,7 @@ static int do_meta_command(char *zLine, ShellState *p){ sqlite3_finalize(pStmt); pStmt = 0; if( nCol==0 ) return 0; /* no columns, no error */ - zSql = sqlite3_malloc( nByte*2 + 20 + nCol*2 ); + zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 ); if( zSql==0 ){ fprintf(stderr, "Error: out of memory\n"); xCloser(sCtx.in); @@ -2884,13 +3084,13 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); if( rc ){ - fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); if (pStmt) sqlite3_finalize(pStmt); xCloser(sCtx.in); return 1; } - needCommit = sqlite3_get_autocommit(db); - if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0); + needCommit = sqlite3_get_autocommit(p->db); + if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0); do{ int startLine = sCtx.nLine; for(i=0; idb)); } } }while( sCtx.cTerm!=EOF ); @@ -2937,10 +3137,11 @@ static int do_meta_command(char *zLine, ShellState *p){ xCloser(sCtx.in); sqlite3_free(sCtx.z); sqlite3_finalize(pStmt); - if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0); + if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0); }else - if( c=='i' && strncmp(azArg[0], "indices", n)==0 ){ + if( c=='i' && (strncmp(azArg[0], "indices", n)==0 + || strncmp(azArg[0], "indexes", n)==0) ){ ShellState data; char *zErrMsg = 0; open_db(p, 0); @@ -2970,7 +3171,7 @@ static int do_meta_command(char *zLine, ShellState *p){ ); zShellStatic = 0; }else{ - fprintf(stderr, "Usage: .indices ?LIKE-PATTERN?\n"); + fprintf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n"); rc = 1; goto meta_command_exit; } @@ -2986,7 +3187,7 @@ static int do_meta_command(char *zLine, ShellState *p){ #ifdef SQLITE_ENABLE_IOTRACE if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ - extern void (*sqlite3IoTrace)(const char*, ...); + SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...); if( iotrace && iotrace!=stdout ) fclose(iotrace); iotrace = 0; if( nArg<2 ){ @@ -3006,6 +3207,64 @@ static int do_meta_command(char *zLine, ShellState *p){ } }else #endif + if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){ + static const struct { + const char *zLimitName; /* Name of a limit */ + int limitCode; /* Integer code for that limit */ + } aLimit[] = { + { "length", SQLITE_LIMIT_LENGTH }, + { "sql_length", SQLITE_LIMIT_SQL_LENGTH }, + { "column", SQLITE_LIMIT_COLUMN }, + { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH }, + { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT }, + { "vdbe_op", SQLITE_LIMIT_VDBE_OP }, + { "function_arg", SQLITE_LIMIT_FUNCTION_ARG }, + { "attached", SQLITE_LIMIT_ATTACHED }, + { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH }, + { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER }, + { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH }, + { "worker_threads", SQLITE_LIMIT_WORKER_THREADS }, + }; + int i, n2; + open_db(p, 0); + if( nArg==1 ){ + for(i=0; idb, aLimit[i].limitCode, -1)); + } + }else if( nArg>3 ){ + fprintf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n"); + rc = 1; + goto meta_command_exit; + }else{ + int iLimit = -1; + n2 = strlen30(azArg[1]); + for(i=0; idb, aLimit[iLimit].limitCode, + (int)integerValue(azArg[2])); + } + printf("%20s %d\n", aLimit[iLimit].zLimitName, + sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1)); + } + }else #ifndef SQLITE_OMIT_LOAD_EXTENSION if( c=='l' && strncmp(azArg[0], "load", n)==0 ){ @@ -3126,6 +3385,11 @@ static int do_meta_command(char *zLine, ShellState *p){ } output_reset(p); if( zFile[0]=='|' ){ +#ifdef SQLITE_OMIT_POPEN + fprintf(stderr,"Error: pipes are not supported in this OS\n"); + rc = 1; + p->out = stdout; +#else p->out = popen(zFile + 1, "w"); if( p->out==0 ){ fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1); @@ -3134,6 +3398,7 @@ static int do_meta_command(char *zLine, ShellState *p){ }else{ sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile); } +#endif }else{ p->out = output_file_open(zFile); if( p->out==0 ){ @@ -3333,7 +3598,7 @@ static int do_meta_command(char *zLine, ShellState *p){ #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE) if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){ extern int sqlite3SelectTrace; - sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff; + sqlite3SelectTrace = integerValue(azArg[1]); }else #endif @@ -3484,13 +3749,13 @@ static int do_meta_command(char *zLine, ShellState *p){ while( sqlite3_step(pStmt)==SQLITE_ROW ){ if( nRow>=nAlloc ){ char **azNew; - int n = nAlloc*2 + 10; - azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n); + int n2 = nAlloc*2 + 10; + azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2); if( azNew==0 ){ fprintf(stderr, "Error: out of memory\n"); break; } - nAlloc = n; + nAlloc = n2; azResult = azNew; } azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); @@ -3539,17 +3804,19 @@ static int do_meta_command(char *zLine, ShellState *p){ { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, { "byteorder", SQLITE_TESTCTRL_BYTEORDER }, + { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT }, + { "imposter", SQLITE_TESTCTRL_IMPOSTER }, }; int testctrl = -1; - int rc = 0; - int i, n; + int rc2 = 0; + int i, n2; open_db(p, 0); /* convert testctrl text option to value. allow any unique prefix ** of the option name, or a numerical value. */ - n = strlen30(azArg[1]); + n2 = strlen30(azArg[1]); for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){ - if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){ + if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){ if( testctrl<0 ){ testctrl = aCtrl[i].ctrlCode; }else{ @@ -3570,8 +3837,8 @@ static int do_meta_command(char *zLine, ShellState *p){ case SQLITE_TESTCTRL_RESERVE: if( nArg==3 ){ int opt = (int)strtol(azArg[2], 0, 0); - rc = sqlite3_test_control(testctrl, p->db, opt); - fprintf(p->out, "%d (0x%08x)\n", rc, rc); + rc2 = sqlite3_test_control(testctrl, p->db, opt); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); } else { fprintf(stderr,"Error: testctrl %s takes a single int option\n", azArg[1]); @@ -3584,8 +3851,8 @@ static int do_meta_command(char *zLine, ShellState *p){ case SQLITE_TESTCTRL_PRNG_RESET: case SQLITE_TESTCTRL_BYTEORDER: if( nArg==2 ){ - rc = sqlite3_test_control(testctrl); - fprintf(p->out, "%d (0x%08x)\n", rc, rc); + rc2 = sqlite3_test_control(testctrl); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); } else { fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]); } @@ -3595,8 +3862,8 @@ static int do_meta_command(char *zLine, ShellState *p){ case SQLITE_TESTCTRL_PENDING_BYTE: if( nArg==3 ){ unsigned int opt = (unsigned int)integerValue(azArg[2]); - rc = sqlite3_test_control(testctrl, opt); - fprintf(p->out, "%d (0x%08x)\n", rc, rc); + rc2 = sqlite3_test_control(testctrl, opt); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); } else { fprintf(stderr,"Error: testctrl %s takes a single unsigned" " int option\n", azArg[1]); @@ -3605,11 +3872,12 @@ static int do_meta_command(char *zLine, ShellState *p){ /* sqlite3_test_control(int, int) */ case SQLITE_TESTCTRL_ASSERT: - case SQLITE_TESTCTRL_ALWAYS: + case SQLITE_TESTCTRL_ALWAYS: + case SQLITE_TESTCTRL_NEVER_CORRUPT: if( nArg==3 ){ int opt = booleanValue(azArg[2]); - rc = sqlite3_test_control(testctrl, opt); - fprintf(p->out, "%d (0x%08x)\n", rc, rc); + rc2 = sqlite3_test_control(testctrl, opt); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); } else { fprintf(stderr,"Error: testctrl %s takes a single int option\n", azArg[1]); @@ -3621,8 +3889,8 @@ static int do_meta_command(char *zLine, ShellState *p){ case SQLITE_TESTCTRL_ISKEYWORD: if( nArg==3 ){ const char *opt = azArg[2]; - rc = sqlite3_test_control(testctrl, opt); - fprintf(p->out, "%d (0x%08x)\n", rc, rc); + rc2 = sqlite3_test_control(testctrl, opt); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); } else { fprintf(stderr,"Error: testctrl %s takes a single char * option\n", azArg[1]); @@ -3630,6 +3898,18 @@ static int do_meta_command(char *zLine, ShellState *p){ break; #endif + case SQLITE_TESTCTRL_IMPOSTER: + if( nArg==5 ){ + rc2 = sqlite3_test_control(testctrl, p->db, + azArg[2], + integerValue(azArg[3]), + integerValue(azArg[4])); + fprintf(p->out, "%d (0x%08x)\n", rc2, rc2); + }else{ + fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n"); + } + break; + case SQLITE_TESTCTRL_BITVEC_TEST: case SQLITE_TESTCTRL_FAULT_INSTALL: case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: @@ -3662,12 +3942,12 @@ static int do_meta_command(char *zLine, ShellState *p){ if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){ open_db(p, 0); - output_file_close(p->traceOut); if( nArg!=2 ){ fprintf(stderr, "Usage: .trace FILE|off\n"); rc = 1; goto meta_command_exit; } + output_file_close(p->traceOut); p->traceOut = output_file_open(azArg[1]); #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) if( p->traceOut==0 ){ @@ -3932,6 +4212,7 @@ static int process_input(ShellState *p, FILE *in){ && sqlite3_complete(zSql) ){ p->cnt = 0; open_db(p, 0); + if( p->backslashOn ) resolve_backslashes(zSql); BEGIN_TIMER; rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); END_TIMER; @@ -4043,7 +4324,7 @@ static char *find_home_dir(void){ ** ** Returns the number of errors. */ -static int process_sqliterc( +static void process_sqliterc( ShellState *p, /* Configuration data */ const char *sqliterc_override /* Name of config file. NULL to use default */ ){ @@ -4051,15 +4332,13 @@ static int process_sqliterc( const char *sqliterc = sqliterc_override; char *zBuf = 0; FILE *in = NULL; - int rc = 0; if (sqliterc == NULL) { home_dir = find_home_dir(); if( home_dir==0 ){ -#if !defined(__RTP__) && !defined(_WRS_KERNEL) - fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0); -#endif - return 1; + fprintf(stderr, "-- warning: cannot find home directory;" + " cannot read ~/.sqliterc\n"); + return; } sqlite3_initialize(); zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir); @@ -4070,11 +4349,10 @@ static int process_sqliterc( if( stdin_is_interactive ){ fprintf(stderr,"-- Loading resources from %s\n",sqliterc); } - rc = process_input(p,in); + process_input(p,in); fclose(in); } sqlite3_free(zBuf); - return rc; } /* @@ -4178,7 +4456,7 @@ static char *cmdline_option_value(int argc, char **argv, int i){ return argv[i]; } -int main(int argc, char **argv){ +int SQLITE_CDECL main(int argc, char **argv){ char *zErrMsg = 0; ShellState data; const char *zInitFile = 0; @@ -4196,6 +4474,8 @@ int main(int argc, char **argv){ exit(1); } #endif + setBinaryMode(stdin); + setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ Argv0 = argv[0]; main_init(&data); stdin_is_interactive = isatty(0); @@ -4348,10 +4628,7 @@ int main(int argc, char **argv){ ** is given on the command line, look for a file named ~/.sqliterc and ** try to process it. */ - rc = process_sqliterc(&data,zInitFile); - if( rc>0 ){ - return rc; - } + process_sqliterc(&data,zInitFile); /* Make a second pass through the command-line argument and set ** options. This second pass is delayed until after the initialization @@ -4402,6 +4679,13 @@ int main(int argc, char **argv){ data.statsOn = 1; }else if( strcmp(z,"-scanstats")==0 ){ data.scanstatsOn = 1; + }else if( strcmp(z,"-backslash")==0 ){ + /* Undocumented command-line option: -backslash + ** Causes C-style backslash escapes to be evaluated in SQL statements + ** prior to sending the SQL into SQLite. Useful for injecting + ** crazy bytes in the middle of SQL statements for testing and debugging. + */ + data.backslashOn = 1; }else if( strcmp(z,"-bail")==0 ){ bail_on_error = 1; }else if( strcmp(z,"-version")==0 ){ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index f2e802e..163bc69 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -43,11 +43,20 @@ extern "C" { /* -** Add the ability to override 'extern' +** Provide the ability to override linkage features of the interface. */ #ifndef SQLITE_EXTERN # define SQLITE_EXTERN extern #endif +#ifndef SQLITE_API +# define SQLITE_API +#endif +#ifndef SQLITE_CDECL +# define SQLITE_CDECL +#endif +#ifndef SQLITE_STDCALL +# define SQLITE_STDCALL +#endif /* ** These no-op macros are used in front of interfaces to mark those @@ -261,6 +270,7 @@ typedef sqlite_uint64 sqlite3_uint64; /* ** CAPI3REF: Closing A Database Connection +** DESTRUCTOR: sqlite3 ** ** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors ** for the [sqlite3] object. @@ -312,6 +322,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**); /* ** CAPI3REF: One-Step Query Execution Interface +** METHOD: sqlite3 ** ** The sqlite3_exec() interface is a convenience wrapper around ** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], @@ -751,14 +762,16 @@ struct sqlite3_io_methods { ** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] ** interface. ** +**
    +**
  • [[SQLITE_FCNTL_LOCKSTATE]] ** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This ** opcode causes the xFileControl method to write the current state of ** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], ** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) ** into an integer that the pArg argument points to. This capability -** is used during testing and only needs to be supported when SQLITE_TEST -** is defined. -**
      +** is used during testing and is only available when the SQLITE_TEST +** compile-time option is used. +** **
    • [[SQLITE_FCNTL_SIZE_HINT]] ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS ** layer a hint of how large the database file will grow to be during the @@ -883,7 +896,9 @@ struct sqlite3_io_methods { ** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] ** file control returns [SQLITE_OK], then the parser assumes that the ** VFS has handled the PRAGMA itself and the parser generates a no-op -** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** prepared statement if result string is NULL, or that returns a copy +** of the result string if the string is non-NULL. +** ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] @@ -941,12 +956,19 @@ struct sqlite3_io_methods { ** pointed to by the pArg argument. This capability is used during testing ** and only needs to be supported when SQLITE_TEST is defined. ** +**
    • [[SQLITE_FCNTL_WAL_BLOCK]] +** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might +** be advantageous to block on the next WAL lock if the lock is not immediately +** available. The WAL subsystem issues this signal during rare +** circumstances in order to fix a problem with priority inversion. +** Applications should not use this file-control. +** **
    */ #define SQLITE_FCNTL_LOCKSTATE 1 -#define SQLITE_GET_LOCKPROXYFILE 2 -#define SQLITE_SET_LOCKPROXYFILE 3 -#define SQLITE_LAST_ERRNO 4 +#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 +#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 +#define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 @@ -965,6 +987,13 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_SYNC 21 #define SQLITE_FCNTL_COMMIT_PHASETWO 22 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23 +#define SQLITE_FCNTL_WAL_BLOCK 24 + +/* deprecated names */ +#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE +#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE +#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO + /* ** CAPI3REF: Mutex Handle @@ -1351,6 +1380,7 @@ int sqlite3_config(int, ...); /* ** CAPI3REF: Configure database connections +** METHOD: sqlite3 ** ** The sqlite3_db_config() interface is used to make configuration ** changes to a [database connection]. The interface is similar to @@ -1525,7 +1555,7 @@ struct sqlite3_mem_methods { **
  • [sqlite3_memory_used()] **
  • [sqlite3_memory_highwater()] **
  • [sqlite3_soft_heap_limit64()] -**
  • [sqlite3_status()] +**
  • [sqlite3_status64()] **
)^ ** ^Memory allocation statistics are enabled by default unless SQLite is ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory @@ -1736,7 +1766,6 @@ struct sqlite3_mem_methods { ** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro ** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value ** that specifies the maximum size of the created heap. -** ** ** [[SQLITE_CONFIG_PCACHE_HDRSZ]] **
SQLITE_CONFIG_PCACHE_HDRSZ @@ -1849,6 +1878,7 @@ struct sqlite3_mem_methods { /* ** CAPI3REF: Enable Or Disable Extended Result Codes +** METHOD: sqlite3 ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result @@ -1858,6 +1888,7 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff); /* ** CAPI3REF: Last Insert Rowid +** METHOD: sqlite3 ** ** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables) ** has a unique 64-bit signed @@ -1909,6 +1940,7 @@ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); /* ** CAPI3REF: Count The Number Of Rows Modified +** METHOD: sqlite3 ** ** ^This function returns the number of rows modified, inserted or ** deleted by the most recently completed INSERT, UPDATE or DELETE @@ -1961,6 +1993,7 @@ int sqlite3_changes(sqlite3*); /* ** CAPI3REF: Total Number Of Rows Modified +** METHOD: sqlite3 ** ** ^This function returns the total number of rows inserted, modified or ** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed @@ -1984,6 +2017,7 @@ int sqlite3_total_changes(sqlite3*); /* ** CAPI3REF: Interrupt A Long-Running Query +** METHOD: sqlite3 ** ** ^This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically @@ -2060,6 +2094,7 @@ int sqlite3_complete16(const void *sql); /* ** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors ** KEYWORDS: {busy-handler callback} {busy handler} +** METHOD: sqlite3 ** ** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X ** that might be invoked with argument P whenever @@ -2119,6 +2154,7 @@ int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); /* ** CAPI3REF: Set A Busy Timeout +** METHOD: sqlite3 ** ** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps ** for a specified amount of time when a table is locked. ^The handler @@ -2141,6 +2177,7 @@ int sqlite3_busy_timeout(sqlite3*, int ms); /* ** CAPI3REF: Convenience Routines For Running Queries +** METHOD: sqlite3 ** ** This is a legacy interface that is preserved for backwards compatibility. ** Use of this interface is not recommended. @@ -2226,6 +2263,10 @@ void sqlite3_free_table(char **result); ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. +** These routines understand most of the common K&R formatting options, +** plus some additional non-standard formats, detailed below. +** Note that some of the more obscure formatting options from recent +** C-library standards are omitted from this implementation. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their ** results into memory obtained from [sqlite3_malloc()]. @@ -2258,7 +2299,7 @@ void sqlite3_free_table(char **result); ** These routines all implement some additional formatting ** options that are useful for constructing SQL statements. ** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", and "%z" options. +** is are "%q", "%Q", "%w" and "%z" options. ** ** ^(The %q option works like %s in that it substitutes a nul-terminated ** string from the argument list. But %q also doubles every '\'' character. @@ -2311,6 +2352,12 @@ void sqlite3_free_table(char **result); ** The code above will render a correct SQL statement in the zSQL ** variable even if the zText variable is a NULL pointer. ** +** ^(The "%w" formatting option is like "%q" except that it expects to +** be contained within double-quotes instead of single quotes, and it +** escapes the double-quote character instead of the single-quote +** character.)^ The "%w" formatting option is intended for safely inserting +** table and column names into a constructed SQL statement. +** ** ^(The "%z" formatting option works like "%s" but with the ** addition that after the string has been read and copied into ** the result, [sqlite3_free()] is called on the input string.)^ @@ -2466,6 +2513,7 @@ void sqlite3_randomness(int N, void *P); /* ** CAPI3REF: Compile-Time Authorization Callbacks +** METHOD: sqlite3 ** ** ^This routine registers an authorizer callback with a particular ** [database connection], supplied in the first argument. @@ -2622,6 +2670,7 @@ int sqlite3_set_authorizer( /* ** CAPI3REF: Tracing And Profiling Functions +** METHOD: sqlite3 ** ** These routines register callback functions that can be used for ** tracing and profiling the execution of SQL statements. @@ -2654,6 +2703,7 @@ SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, /* ** CAPI3REF: Query Progress Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback ** function X to be invoked periodically during long running calls to @@ -2687,6 +2737,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); /* ** CAPI3REF: Opening A New Database Connection +** CONSTRUCTOR: sqlite3 ** ** ^These routines open an SQLite database file as specified by the ** filename argument. ^The filename argument is interpreted as UTF-8 for @@ -2972,12 +3023,15 @@ sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); /* ** CAPI3REF: Error Codes And Messages +** METHOD: sqlite3 ** -** ^The sqlite3_errcode() interface returns the numeric [result code] or -** [extended result code] for the most recent failed sqlite3_* API call -** associated with a [database connection]. If a prior API call failed -** but the most recent API call succeeded, the return value from -** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() +** ^If the most recent sqlite3_* API call associated with +** [database connection] D failed, then the sqlite3_errcode(D) interface +** returns the numeric [result code] or [extended result code] for that +** API call. +** If the most recent API call was successful, +** then the return value from sqlite3_errcode() is undefined. +** ^The sqlite3_extended_errcode() ** interface is the same except that it always returns the ** [extended result code] even when extended result codes are ** disabled. @@ -3015,33 +3069,34 @@ const void *sqlite3_errmsg16(sqlite3*); const char *sqlite3_errstr(int); /* -** CAPI3REF: SQL Statement Object +** CAPI3REF: Prepared Statement Object ** KEYWORDS: {prepared statement} {prepared statements} ** -** An instance of this object represents a single SQL statement. -** This object is variously known as a "prepared statement" or a -** "compiled SQL statement" or simply as a "statement". +** An instance of this object represents a single SQL statement that +** has been compiled into binary form and is ready to be evaluated. ** -** The life of a statement object goes something like this: +** Think of each SQL statement as a separate computer program. The +** original SQL text is source code. A prepared statement object +** is the compiled object code. All SQL must be converted into a +** prepared statement before it can be run. +** +** The life-cycle of a prepared statement object usually goes like this: ** **
    -**
  1. Create the object using [sqlite3_prepare_v2()] or a related -** function. -**
  2. Bind values to [host parameters] using the sqlite3_bind_*() +**
  3. Create the prepared statement object using [sqlite3_prepare_v2()]. +**
  4. Bind values to [parameters] using the sqlite3_bind_*() ** interfaces. **
  5. Run the SQL by calling [sqlite3_step()] one or more times. -**
  6. Reset the statement using [sqlite3_reset()] then go back +**
  7. Reset the prepared statement using [sqlite3_reset()] then go back ** to step 2. Do this zero or more times. **
  8. Destroy the object using [sqlite3_finalize()]. **
-** -** Refer to documentation on individual methods above for additional -** information. */ typedef struct sqlite3_stmt sqlite3_stmt; /* ** CAPI3REF: Run-time Limits +** METHOD: sqlite3 ** ** ^(This interface allows the size of various constructs to be limited ** on a connection by connection basis. The first parameter is the @@ -3153,6 +3208,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal); /* ** CAPI3REF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_stmt ** ** To execute an SQL query, it must first be compiled into a byte-code ** program using one of these routines. @@ -3166,16 +3223,14 @@ int sqlite3_limit(sqlite3*, int id, int newVal); ** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() ** use UTF-16. ** -** ^If the nByte argument is less than zero, then zSql is read up to the -** first zero terminator. ^If nByte is non-negative, then it is the maximum -** number of bytes read from zSql. ^When nByte is non-negative, the -** zSql string ends at either the first '\000' or '\u0000' character or -** the nByte-th byte, whichever comes first. If the caller knows -** that the supplied string is nul-terminated, then there is a small -** performance advantage to be gained by passing an nByte parameter that -** is equal to the number of bytes in the input string including -** the nul-terminator bytes as this saves SQLite from having to -** make a copy of the input string. +** ^If the nByte argument is negative, then zSql is read up to the +** first zero terminator. ^If nByte is positive, then it is the +** number of bytes read from zSql. ^If nByte is zero, then no prepared +** statement is generated. +** If the caller knows that the supplied string is nul-terminated, then +** there is a small performance advantage to passing an nByte parameter that +** is the number of bytes in the input string including +** the nul-terminator. ** ** ^If pzTail is not NULL then *pzTail is made to point to the first byte ** past the end of the first SQL statement in zSql. These routines only @@ -3262,6 +3317,7 @@ int sqlite3_prepare16_v2( /* ** CAPI3REF: Retrieving Statement SQL +** METHOD: sqlite3_stmt ** ** ^This interface can be used to retrieve a saved copy of the original ** SQL text used to create a [prepared statement] if that statement was @@ -3271,6 +3327,7 @@ const char *sqlite3_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database +** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if ** and only if the [prepared statement] X makes no direct changes to @@ -3302,6 +3359,7 @@ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset +** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the ** [prepared statement] S has been stepped at least once using @@ -3376,6 +3434,7 @@ typedef struct sqlite3_context sqlite3_context; ** CAPI3REF: Binding Values To Prepared Statements ** KEYWORDS: {host parameter} {host parameters} {host parameter name} ** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** METHOD: sqlite3_stmt ** ** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, ** literals may be replaced by a [parameter] that matches one of following @@ -3494,6 +3553,7 @@ int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); /* ** CAPI3REF: Number Of SQL Parameters +** METHOD: sqlite3_stmt ** ** ^This routine can be used to find the number of [SQL parameters] ** in a [prepared statement]. SQL parameters are tokens of the @@ -3514,6 +3574,7 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** CAPI3REF: Name Of A Host Parameter +** METHOD: sqlite3_stmt ** ** ^The sqlite3_bind_parameter_name(P,N) interface returns ** the name of the N-th [SQL parameter] in the [prepared statement] P. @@ -3541,6 +3602,7 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); /* ** CAPI3REF: Index Of A Parameter With A Given Name +** METHOD: sqlite3_stmt ** ** ^Return the index of an SQL parameter given its name. ^The ** index value returned is suitable for use as the second @@ -3557,6 +3619,7 @@ int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); /* ** CAPI3REF: Reset All Bindings On A Prepared Statement +** METHOD: sqlite3_stmt ** ** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset ** the [sqlite3_bind_blob | bindings] on a [prepared statement]. @@ -3566,6 +3629,7 @@ int sqlite3_clear_bindings(sqlite3_stmt*); /* ** CAPI3REF: Number Of Columns In A Result Set +** METHOD: sqlite3_stmt ** ** ^Return the number of columns in the result set returned by the ** [prepared statement]. ^This routine returns 0 if pStmt is an SQL @@ -3577,6 +3641,7 @@ int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Column Names In A Result Set +** METHOD: sqlite3_stmt ** ** ^These routines return the name assigned to a particular column ** in the result set of a [SELECT] statement. ^The sqlite3_column_name() @@ -3606,6 +3671,7 @@ const void *sqlite3_column_name16(sqlite3_stmt*, int N); /* ** CAPI3REF: Source Of Data In A Query Result +** METHOD: sqlite3_stmt ** ** ^These routines provide a means to determine the database, table, and ** table column that is the origin of a particular result column in @@ -3658,6 +3724,7 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); /* ** CAPI3REF: Declared Datatype Of A Query Result +** METHOD: sqlite3_stmt ** ** ^(The first parameter is a [prepared statement]. ** If this statement is a [SELECT] statement and the Nth column of the @@ -3690,6 +3757,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int); /* ** CAPI3REF: Evaluate An SQL Statement +** METHOD: sqlite3_stmt ** ** After a [prepared statement] has been prepared using either ** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy @@ -3769,6 +3837,7 @@ int sqlite3_step(sqlite3_stmt*); /* ** CAPI3REF: Number of columns in a result set +** METHOD: sqlite3_stmt ** ** ^The sqlite3_data_count(P) interface returns the number of columns in the ** current row of the result set of [prepared statement] P. @@ -3822,6 +3891,7 @@ int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Result Values From A Query ** KEYWORDS: {column access functions} +** METHOD: sqlite3_stmt ** ** These routines form the "result set" interface. ** @@ -3994,6 +4064,7 @@ sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); /* ** CAPI3REF: Destroy A Prepared Statement Object +** DESTRUCTOR: sqlite3_stmt ** ** ^The sqlite3_finalize() function is called to delete a [prepared statement]. ** ^If the most recent evaluation of the statement encountered no errors @@ -4021,6 +4092,7 @@ int sqlite3_finalize(sqlite3_stmt *pStmt); /* ** CAPI3REF: Reset A Prepared Statement Object +** METHOD: sqlite3_stmt ** ** The sqlite3_reset() function is called to reset a [prepared statement] ** object back to its initial state, ready to be re-executed. @@ -4050,6 +4122,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt); ** KEYWORDS: {function creation routines} ** KEYWORDS: {application-defined SQL function} ** KEYWORDS: {application-defined SQL functions} +** METHOD: sqlite3 ** ** ^These functions (collectively known as "function creation routines") ** are used to add SQL functions or aggregates or to redefine the behavior @@ -4204,8 +4277,8 @@ int sqlite3_create_function_v2( ** These functions are [deprecated]. In order to maintain ** backwards compatibility with older code, these functions continue ** to be supported. However, new applications should avoid -** the use of these functions. To help encourage people to avoid -** using these functions, we are not going to tell you what they do. +** the use of these functions. To encourage programmers to avoid +** these functions, we will not explain what they do. */ #ifndef SQLITE_OMIT_DEPRECATED SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); @@ -4219,6 +4292,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), /* ** CAPI3REF: Obtaining SQL Function Parameter Values +** METHOD: sqlite3_value ** ** The C-language implementation of SQL functions and aggregates uses ** this set of interface routines to access the parameter values on @@ -4277,6 +4351,7 @@ int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Obtain Aggregate Function Context +** METHOD: sqlite3_context ** ** Implementations of aggregate SQL functions use this ** routine to allocate memory for storing their state. @@ -4321,6 +4396,7 @@ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** CAPI3REF: User Data For Functions +** METHOD: sqlite3_context ** ** ^The sqlite3_user_data() interface returns a copy of ** the pointer that was the pUserData parameter (the 5th parameter) @@ -4335,6 +4411,7 @@ void *sqlite3_user_data(sqlite3_context*); /* ** CAPI3REF: Database Connection For Functions +** METHOD: sqlite3_context ** ** ^The sqlite3_context_db_handle() interface returns a copy of ** the pointer to the [database connection] (the 1st parameter) @@ -4346,6 +4423,7 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context*); /* ** CAPI3REF: Function Auxiliary Data +** METHOD: sqlite3_context ** ** These functions may be used by (non-aggregate) SQL functions to ** associate metadata with argument values. If the same value is passed to @@ -4418,6 +4496,7 @@ typedef void (*sqlite3_destructor_type)(void*); /* ** CAPI3REF: Setting The Result Of An SQL Function +** METHOD: sqlite3_context ** ** These routines are used by the xFunc or xFinal callbacks that ** implement SQL functions and aggregates. See @@ -4553,6 +4632,7 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n); /* ** CAPI3REF: Define New Collating Sequences +** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. @@ -4655,6 +4735,7 @@ int sqlite3_create_collation16( /* ** CAPI3REF: Collation Needed Callbacks +** METHOD: sqlite3 ** ** ^To avoid having to register all collation sequences before a database ** can be used, a single callback function may be registered with the @@ -4862,6 +4943,7 @@ SQLITE_EXTERN char *sqlite3_data_directory; /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} +** METHOD: sqlite3 ** ** ^The sqlite3_get_autocommit() interface returns non-zero or ** zero if the given database connection is or is not in autocommit mode, @@ -4884,6 +4966,7 @@ int sqlite3_get_autocommit(sqlite3*); /* ** CAPI3REF: Find The Database Handle Of A Prepared Statement +** METHOD: sqlite3_stmt ** ** ^The sqlite3_db_handle interface returns the [database connection] handle ** to which a [prepared statement] belongs. ^The [database connection] @@ -4896,6 +4979,7 @@ sqlite3 *sqlite3_db_handle(sqlite3_stmt*); /* ** CAPI3REF: Return The Filename For A Database Connection +** METHOD: sqlite3 ** ** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename ** associated with database N of connection D. ^The main database file @@ -4912,6 +4996,7 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Determine if a database is read-only +** METHOD: sqlite3 ** ** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N ** of connection D is read-only, 0 if it is read/write, or -1 if N is not @@ -4921,6 +5006,7 @@ int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); /* ** CAPI3REF: Find the next prepared statement +** METHOD: sqlite3 ** ** ^This interface returns a pointer to the next [prepared statement] after ** pStmt associated with the [database connection] pDb. ^If pStmt is NULL @@ -4936,6 +5022,7 @@ sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); /* ** CAPI3REF: Commit And Rollback Notification Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_commit_hook() interface registers a callback ** function to be invoked whenever a transaction is [COMMIT | committed]. @@ -4985,6 +5072,7 @@ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* ** CAPI3REF: Data Change Notification Callbacks +** METHOD: sqlite3 ** ** ^The sqlite3_update_hook() interface registers a callback function ** with the [database connection] identified by the first argument @@ -5061,6 +5149,11 @@ void *sqlite3_update_hook( ** future releases of SQLite. Applications that care about shared ** cache setting should set it explicitly. ** +** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0 +** and will always return SQLITE_MISUSE. On those systems, +** shared cache mode should be enabled per-database connection via +** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE]. +** ** This interface is threadsafe on processors where writing a ** 32-bit integer is atomic. ** @@ -5086,6 +5179,7 @@ int sqlite3_release_memory(int); /* ** CAPI3REF: Free Memory Used By A Database Connection +** METHOD: sqlite3 ** ** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap ** memory as possible from database connection D. Unlike the @@ -5163,6 +5257,7 @@ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); /* ** CAPI3REF: Extract Metadata About A Column Of A Table +** METHOD: sqlite3 ** ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns ** information about column C of table T in database D @@ -5241,6 +5336,7 @@ int sqlite3_table_column_metadata( /* ** CAPI3REF: Load An Extension +** METHOD: sqlite3 ** ** ^This interface loads an SQLite extension library from the named file. ** @@ -5282,6 +5378,7 @@ int sqlite3_load_extension( /* ** CAPI3REF: Enable Or Disable Extension Loading +** METHOD: sqlite3 ** ** ^So as not to open security holes in older applications that are ** unprepared to deal with [extension loading], and as a means of disabling @@ -5531,6 +5628,7 @@ struct sqlite3_index_info { /* ** CAPI3REF: Register A Virtual Table Implementation +** METHOD: sqlite3 ** ** ^These routines are used to register a new [virtual table module] name. ** ^Module names must be registered before @@ -5588,7 +5686,7 @@ int sqlite3_create_module_v2( */ struct sqlite3_vtab { const sqlite3_module *pModule; /* The module for this virtual table */ - int nRef; /* NO LONGER USED */ + int nRef; /* Number of open cursors */ char *zErrMsg; /* Error message from sqlite3_mprintf() */ /* Virtual table implementations will typically add additional fields */ }; @@ -5627,6 +5725,7 @@ int sqlite3_declare_vtab(sqlite3*, const char *zSQL); /* ** CAPI3REF: Overload A Function For A Virtual Table +** METHOD: sqlite3 ** ** ^(Virtual tables can provide alternative implementations of functions ** using the [xFindFunction] method of the [virtual table module]. @@ -5669,6 +5768,8 @@ typedef struct sqlite3_blob sqlite3_blob; /* ** CAPI3REF: Open A BLOB For Incremental I/O +** METHOD: sqlite3 +** CONSTRUCTOR: sqlite3_blob ** ** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located ** in row iRow, column zColumn, table zTable in database zDb; @@ -5750,6 +5851,7 @@ int sqlite3_blob_open( /* ** CAPI3REF: Move a BLOB Handle to a New Row +** METHOD: sqlite3_blob ** ** ^This function is used to move an existing blob handle so that it points ** to a different row of the same database table. ^The new row is identified @@ -5774,6 +5876,7 @@ SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); /* ** CAPI3REF: Close A BLOB Handle +** DESTRUCTOR: sqlite3_blob ** ** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed ** unconditionally. Even if this routine returns an error code, the @@ -5796,6 +5899,7 @@ int sqlite3_blob_close(sqlite3_blob *); /* ** CAPI3REF: Return The Size Of An Open BLOB +** METHOD: sqlite3_blob ** ** ^Returns the size in bytes of the BLOB accessible via the ** successfully opened [BLOB handle] in its only argument. ^The @@ -5811,6 +5915,7 @@ int sqlite3_blob_bytes(sqlite3_blob *); /* ** CAPI3REF: Read Data From A BLOB Incrementally +** METHOD: sqlite3_blob ** ** ^(This function is used to read data from an open [BLOB handle] into a ** caller-supplied buffer. N bytes of data are copied into buffer Z @@ -5839,6 +5944,7 @@ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); /* ** CAPI3REF: Write Data Into A BLOB Incrementally +** METHOD: sqlite3_blob ** ** ^(This function is used to write data into an open [BLOB handle] from a ** caller-supplied buffer. N bytes of data are copied from the buffer Z @@ -6166,6 +6272,7 @@ int sqlite3_mutex_notheld(sqlite3_mutex*); /* ** CAPI3REF: Retrieve the mutex for a database connection +** METHOD: sqlite3 ** ** ^This interface returns a pointer the [sqlite3_mutex] object that ** serializes access to the [database connection] given in the argument @@ -6177,6 +6284,7 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3*); /* ** CAPI3REF: Low-Level Control Of Database Files +** METHOD: sqlite3 ** ** ^The [sqlite3_file_control()] interface makes a direct call to the ** xFileControl method for the [sqlite3_io_methods] object associated @@ -6260,12 +6368,13 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 -#define SQLITE_TESTCTRL_LAST 24 +#define SQLITE_TESTCTRL_IMPOSTER 25 +#define SQLITE_TESTCTRL_LAST 25 /* ** CAPI3REF: SQLite Runtime Status ** -** ^This interface is used to retrieve runtime status information +** ^These interfaces are used to retrieve runtime status information ** about the performance of SQLite, and optionally to reset various ** highwater marks. ^The first argument is an integer code for ** the specific parameter to measure. ^(Recognized integer codes @@ -6279,19 +6388,22 @@ int sqlite3_test_control(int op, ...); ** ^(Other parameters record only the highwater mark and not the current ** value. For these latter parameters nothing is written into *pCurrent.)^ ** -** ^The sqlite3_status() routine returns SQLITE_OK on success and a -** non-zero [error code] on failure. +** ^The sqlite3_status() and sqlite3_status64() routines return +** SQLITE_OK on success and a non-zero [error code] on failure. ** -** This routine is threadsafe but is not atomic. This routine can be -** called while other threads are running the same or different SQLite -** interfaces. However the values returned in *pCurrent and -** *pHighwater reflect the status of SQLite at different points in time -** and it is possible that another thread might change the parameter -** in between the times when *pCurrent and *pHighwater are written. +** If either the current value or the highwater mark is too large to +** be represented by a 32-bit integer, then the values returned by +** sqlite3_status() are undefined. ** ** See also: [sqlite3_db_status()] */ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); +int sqlite3_status64( + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag +); /* @@ -6389,6 +6501,7 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); /* ** CAPI3REF: Database Connection Status +** METHOD: sqlite3 ** ** ^This interface is used to retrieve runtime status information ** about a single [database connection]. ^The first argument is the @@ -6517,6 +6630,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); /* ** CAPI3REF: Prepared Statement Status +** METHOD: sqlite3_stmt ** ** ^(Each prepared statement maintains various ** [SQLITE_STMTSTATUS counters] that measure the number @@ -6961,20 +7075,20 @@ typedef struct sqlite3_backup sqlite3_backup; ** is not a permanent error and does not affect the return value of ** sqlite3_backup_finish(). ** -** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] +** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]] ** sqlite3_backup_remaining() and sqlite3_backup_pagecount() ** -** ^Each call to sqlite3_backup_step() sets two values inside -** the [sqlite3_backup] object: the number of pages still to be backed -** up and the total number of pages in the source database file. -** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces -** retrieve these two values, respectively. -** -** ^The values returned by these functions are only updated by -** sqlite3_backup_step(). ^If the source database is modified during a backup -** operation, then the values are not updated to account for any extra -** pages that need to be updated or the size of the source database file -** changing. +** ^The sqlite3_backup_remaining() routine returns the number of pages still +** to be backed up at the conclusion of the most recent sqlite3_backup_step(). +** ^The sqlite3_backup_pagecount() routine returns the total number of pages +** in the source database at the conclusion of the most recent +** sqlite3_backup_step(). +** ^(The values returned by these functions are only updated by +** sqlite3_backup_step(). If the source database is modified in a way that +** changes the size of the source database or the number of pages remaining, +** those changes are not reflected in the output of sqlite3_backup_pagecount() +** and sqlite3_backup_remaining() until after the next +** sqlite3_backup_step().)^ ** ** Concurrent Usage of Database Handles ** @@ -7020,6 +7134,7 @@ int sqlite3_backup_pagecount(sqlite3_backup *p); /* ** CAPI3REF: Unlock Notification +** METHOD: sqlite3 ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE_LOCKED] error if the required locks on the shared-cache or @@ -7190,6 +7305,7 @@ void sqlite3_log(int iErrCode, const char *zFormat, ...); /* ** CAPI3REF: Write-Ahead Log Commit Hook +** METHOD: sqlite3 ** ** ^The [sqlite3_wal_hook()] function is used to register a callback that ** is invoked each time data is committed to a database in wal mode. @@ -7229,6 +7345,7 @@ void *sqlite3_wal_hook( /* ** CAPI3REF: Configure an auto-checkpoint +** METHOD: sqlite3 ** ** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around ** [sqlite3_wal_hook()] that causes any database on [database connection] D @@ -7259,6 +7376,7 @@ int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); /* ** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to ** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^ @@ -7280,6 +7398,7 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); /* ** CAPI3REF: Checkpoint a database +** METHOD: sqlite3 ** ** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint ** operation on database X of [database connection] D in mode M. Status @@ -7534,6 +7653,7 @@ int sqlite3_vtab_on_conflict(sqlite3 *); /* ** CAPI3REF: Prepared Statement Scan Status +** METHOD: sqlite3_stmt ** ** This interface returns information about the predicted and measured ** performance for pStmt. Advanced applications can use this @@ -7571,6 +7691,7 @@ SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( /* ** CAPI3REF: Zero Scan-Status Counters +** METHOD: sqlite3_stmt ** ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 379456d..7b9542a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -23,6 +23,11 @@ */ #include "msvc.h" +/* +** Special setup for VxWorks +*/ +#include "vxworks.h" + /* ** These #defines should enable >2GB file support on POSIX if the ** underlying operating system supports it. If the OS lacks @@ -357,6 +362,32 @@ # define NEVER(X) (X) #endif +/* +** Declarations used for tracing the operating system interfaces. +*/ +#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \ + (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) + extern int sqlite3OSTrace; +# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X +# define SQLITE_HAVE_OS_TRACE +#else +# define OSTRACE(X) +# undef SQLITE_HAVE_OS_TRACE +#endif + +/* +** Is the sqlite3ErrName() function needed in the build? Currently, +** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when +** OSTRACE is enabled), and by several "test*.c" files (which are +** compiled using SQLITE_TEST). +*/ +#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \ + (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) +# define SQLITE_NEED_ERR_NAME +#else +# undef SQLITE_NEED_ERR_NAME +#endif + /* ** Return true (non-zero) if the input is an integer that is too large ** to fit in 32-bits. This macro is used inside of various testcase() @@ -589,6 +620,20 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */ */ typedef INT16_TYPE LogEst; +/* +** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer +*/ +#ifndef SQLITE_PTRSIZE +# if defined(__SIZEOF_POINTER__) +# define SQLITE_PTRSIZE __SIZEOF_POINTER__ +# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(_M_ARM) || defined(__arm__) || defined(__x86) +# define SQLITE_PTRSIZE 4 +# else +# define SQLITE_PTRSIZE 8 +# endif +#endif + /* ** Macros to determine whether the machine is big or little endian, ** and whether or not that determination is run-time or compile-time. @@ -1087,11 +1132,13 @@ struct sqlite3 { u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ + u8 imposterTable; /* Building an imposter table */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ int nVdbeWrite; /* Number of active VDBEs that read and write */ int nVdbeExec; /* Number of nested calls to VdbeExec() */ + int nVDestroy; /* Number of active OP_VDestroy operations */ int nExtension; /* Number of loaded extensions */ void **aExtension; /* Array of shared library handles */ void (*xTrace)(void*,const char*); /* Trace function */ @@ -1205,6 +1252,7 @@ struct sqlite3 { #define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */ #define SQLITE_QueryOnly 0x02000000 /* Disable database changes */ #define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */ +#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */ /* @@ -1535,34 +1583,8 @@ struct VTable { }; /* -** Each SQL table is represented in memory by an instance of the -** following structure. -** -** Table.zName is the name of the table. The case of the original -** CREATE TABLE statement is stored, but case is not significant for -** comparisons. -** -** Table.nCol is the number of columns in this table. Table.aCol is a -** pointer to an array of Column structures, one for each column. -** -** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of -** the column that is that key. Otherwise Table.iPKey is negative. Note -** that the datatype of the PRIMARY KEY must be INTEGER for this field to -** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of -** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid -** is generated for each row of the table. TF_HasPrimaryKey is set if -** the table has any PRIMARY KEY, INTEGER or otherwise. -** -** Table.tnum is the page number for the root BTree page of the table in the -** database file. If Table.iDb is the index of the database table backend -** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that -** holds temporary tables and indices. If TF_Ephemeral is set -** then the table is stored in a file that is automatically deleted -** when the VDBE cursor to the table is closed. In this case Table.tnum -** refers VDBE cursor number that holds the table open, not to the root -** page number. Transient tables are used to hold the results of a -** sub-query that appears instead of a real table name in the FROM clause -** of a SELECT statement. +** The schema for each SQL table and view is represented in memory +** by an instance of the following structure. */ struct Table { char *zName; /* Name of the table or view */ @@ -1574,11 +1596,11 @@ struct Table { #ifndef SQLITE_OMIT_CHECK ExprList *pCheck; /* All CHECK constraints */ #endif - LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ - int tnum; /* Root BTree node for this table (see note above) */ - i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ + int tnum; /* Root BTree page for this table */ + i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ + LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ #ifdef SQLITE_ENABLE_COSTMULT LogEst costMult; /* Cost multiplier for using this table */ @@ -1600,6 +1622,12 @@ struct Table { /* ** Allowed values for Table.tabFlags. +** +** TF_OOOHidden applies to virtual tables that have hidden columns that are +** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING +** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden, +** the TF_OOOHidden attribute would apply in this case. Such tables require +** special handling during INSERT processing. */ #define TF_Readonly 0x01 /* Read-only system table */ #define TF_Ephemeral 0x02 /* An ephemeral table */ @@ -1607,6 +1635,7 @@ struct Table { #define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ #define TF_Virtual 0x10 /* Is a virtual table */ #define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */ +#define TF_OOOHidden 0x40 /* Out-of-Order hidden columns */ /* @@ -2043,8 +2072,14 @@ struct Expr { #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ -#define EP_Constant 0x080000 /* Node is a constant */ +#define EP_ConstFunc 0x080000 /* Node is a SQLITE_FUNC_CONSTANT function */ #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ +#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ + +/* +** Combinations of two or more EP_* flags +*/ +#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */ /* ** These macros can be used to test, set, or clear bits in the @@ -2243,7 +2278,7 @@ struct SrcList { #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ #define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */ #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ - /* 0x0080 // not currently used */ +#define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */ #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */ #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */ #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */ @@ -2357,11 +2392,12 @@ struct Select { #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_Compound 0x0040 /* Part of a compound query */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ -#define SF_AllValues 0x0100 /* All terms of compound are VALUES */ +#define SF_MultiValue 0x0100 /* Single VALUES term with multiple rows */ #define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */ #define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */ #define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */ #define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */ +#define SF_Converted 0x2000 /* By convertCompoundSelectToSubquery() */ /* @@ -2680,7 +2716,8 @@ struct AuthContext { #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ -#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ +#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */ +#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ /* @@ -2739,7 +2776,7 @@ struct Trigger { * orconf -> stores the ON CONFLICT algorithm * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then * this stores a pointer to the SELECT statement. Otherwise NULL. - * target -> A token holding the quoted name of the table to insert into. + * zTarget -> Dequoted name of the table to insert into. * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then * this stores values to be inserted. Otherwise NULL. * pIdList -> If this is an INSERT INTO ... () VALUES ... @@ -2747,12 +2784,12 @@ struct Trigger { * inserted into. * * (op == TK_DELETE) - * target -> A token holding the quoted name of the table to delete from. + * zTarget -> Dequoted name of the table to delete from. * pWhere -> The WHERE clause of the DELETE statement if one is specified. * Otherwise NULL. * * (op == TK_UPDATE) - * target -> A token holding the quoted name of the table to update rows of. + * zTarget -> Dequoted name of the table to update. * pWhere -> The WHERE clause of the UPDATE statement if one is specified. * Otherwise NULL. * pExprList -> A list of the columns to update and the expressions to update @@ -2764,8 +2801,8 @@ struct TriggerStep { u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */ u8 orconf; /* OE_Rollback etc. */ Trigger *pTrig; /* The trigger that this step is a part of */ - Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */ - Token target; /* Target table for DELETE, UPDATE, INSERT */ + Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */ + char *zTarget; /* Target table for DELETE, UPDATE, INSERT */ Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ ExprList *pExprList; /* SET clause for UPDATE. */ IdList *pIdList; /* Column names for INSERT */ @@ -2798,8 +2835,7 @@ struct StrAccum { char *zText; /* The string collected so far */ int nChar; /* Length of the string so far */ int nAlloc; /* Amount of space allocated in zText */ - int mxAlloc; /* Maximum allowed string length */ - u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */ + int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */ u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */ }; #define STRACCUM_NOMEM 1 @@ -3084,10 +3120,15 @@ const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); int sqlite3MutexEnd(void); #endif -int sqlite3StatusValue(int); -void sqlite3StatusAdd(int, int); +sqlite3_int64 sqlite3StatusValue(int); +void sqlite3StatusUp(int, int); +void sqlite3StatusDown(int, int); void sqlite3StatusSet(int, int); +/* Access to mutexes used by sqlite3_status() */ +sqlite3_mutex *sqlite3Pcache1Mutex(void); +sqlite3_mutex *sqlite3MallocMutex(void); + #ifndef SQLITE_OMIT_FLOATING_POINT int sqlite3IsNaN(double); #else @@ -3111,7 +3152,7 @@ void sqlite3XPrintf(StrAccum*, u32, const char*, ...); char *sqlite3MPrintf(sqlite3*,const char*, ...); char *sqlite3VMPrintf(sqlite3*,const char*, va_list); char *sqlite3MAppendf(sqlite3*,char*,const char*,...); -#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) +#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) void sqlite3DebugPrintf(const char*, ...); #endif #if defined(SQLITE_TEST) @@ -3152,6 +3193,7 @@ ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); void sqlite3ExprListDelete(sqlite3*, ExprList*); +u32 sqlite3ExprListFlags(const ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); @@ -3457,7 +3499,7 @@ void *sqlite3HexToBlob(sqlite3*, const char *z, int n); u8 sqlite3HexToInt(int h); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); -#if defined(SQLITE_TEST) +#if defined(SQLITE_NEED_ERR_NAME) const char *sqlite3ErrName(int); #endif @@ -3466,7 +3508,7 @@ int sqlite3ReadSchema(Parse *pParse); CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); -Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*); +Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); Expr *sqlite3ExprSkipCollate(Expr*); int sqlite3CheckCollSeq(Parse *, CollSeq *); @@ -3551,7 +3593,7 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, int sqlite3ApiExit(sqlite3 *db, int); int sqlite3OpenTempDatabase(Parse *); -void sqlite3StrAccumInit(StrAccum*, char*, int, int); +void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); void sqlite3StrAccumAppend(StrAccum*,const char*,int); void sqlite3StrAccumAppendAll(StrAccum*,const char*); void sqlite3AppendChar(StrAccum*,int,char); @@ -3735,12 +3777,11 @@ void sqlite3MemJournalOpen(sqlite3_file *); int sqlite3MemJournalSize(void); int sqlite3IsMemJournal(sqlite3_file *); +void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p); #if SQLITE_MAX_EXPR_DEPTH>0 - void sqlite3ExprSetHeight(Parse *pParse, Expr *p); int sqlite3SelectExprHeight(Select *); int sqlite3ExprCheckHeight(Parse*, int); #else - #define sqlite3ExprSetHeight(x,y) #define sqlite3SelectExprHeight(x) 0 #define sqlite3ExprCheckHeight(x,y) #endif @@ -3770,7 +3811,7 @@ void sqlite3Put4byte(u8*, u32); #ifdef SQLITE_ENABLE_IOTRACE # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } void sqlite3VdbeIOTraceSql(Vdbe*); -SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...); +SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...); #else # define IOTRACE(A) # define sqlite3VdbeIOTraceSql(X) diff --git a/src/sqliteLimit.h b/src/sqliteLimit.h index c7aee53..75cad12 100644 --- a/src/sqliteLimit.h +++ b/src/sqliteLimit.h @@ -98,15 +98,17 @@ #endif /* -** The maximum number of in-memory pages to use for the main database -** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE +** The suggested maximum number of in-memory pages to use for +** the main database table and for temporary tables. +** +** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size +** is 2000 pages. +** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be +** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options. */ #ifndef SQLITE_DEFAULT_CACHE_SIZE # define SQLITE_DEFAULT_CACHE_SIZE 2000 #endif -#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE -# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 -#endif /* ** The default number of frames to accumulate in the log file before diff --git a/src/status.c b/src/status.c index 4c2eabb..ac32753 100644 --- a/src/status.c +++ b/src/status.c @@ -21,10 +21,32 @@ */ typedef struct sqlite3StatType sqlite3StatType; static SQLITE_WSD struct sqlite3StatType { - int nowValue[10]; /* Current value */ - int mxValue[10]; /* Maximum value */ +#if SQLITE_PTRSIZE>4 + sqlite3_int64 nowValue[10]; /* Current value */ + sqlite3_int64 mxValue[10]; /* Maximum value */ +#else + u32 nowValue[10]; /* Current value */ + u32 mxValue[10]; /* Maximum value */ +#endif } sqlite3Stat = { {0,}, {0,} }; +/* +** Elements of sqlite3Stat[] are protected by either the memory allocator +** mutex, or by the pcache1 mutex. The following array determines which. +*/ +static const char statMutex[] = { + 0, /* SQLITE_STATUS_MEMORY_USED */ + 1, /* SQLITE_STATUS_PAGECACHE_USED */ + 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */ + 0, /* SQLITE_STATUS_SCRATCH_USED */ + 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */ + 0, /* SQLITE_STATUS_MALLOC_SIZE */ + 0, /* SQLITE_STATUS_PARSER_STACK */ + 1, /* SQLITE_STATUS_PAGECACHE_SIZE */ + 0, /* SQLITE_STATUS_SCRATCH_SIZE */ + 0, /* SQLITE_STATUS_MALLOC_COUNT */ +}; + /* The "wsdStat" macro will resolve to the status information ** state vector. If writable static data is unsupported on the target, @@ -41,33 +63,60 @@ static SQLITE_WSD struct sqlite3StatType { #endif /* -** Return the current value of a status parameter. +** Return the current value of a status parameter. The caller must +** be holding the appropriate mutex. */ -int sqlite3StatusValue(int op){ +sqlite3_int64 sqlite3StatusValue(int op){ wsdStatInit; assert( op>=0 && op=0 && op=0 && op=0 && opwsdStat.mxValue[op] ){ wsdStat.mxValue[op] = wsdStat.nowValue[op]; } } +void sqlite3StatusDown(int op, int N){ + wsdStatInit; + assert( N>=0 ); + assert( op>=0 && op=0 && op=0 && op=0 && opwsdStat.mxValue[op] ){ wsdStat.mxValue[op] = wsdStat.nowValue[op]; @@ -76,12 +125,14 @@ void sqlite3StatusSet(int op, int X){ /* ** Query status information. -** -** This implementation assumes that reading or writing an aligned -** 32-bit integer is an atomic operation. If that assumption is not true, -** then this routine is not threadsafe. */ -int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ +int sqlite3_status64( + int op, + sqlite3_int64 *pCurrent, + sqlite3_int64 *pHighwater, + int resetFlag +){ + sqlite3_mutex *pMutex; wsdStatInit; if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ return SQLITE_MISUSE_BKPT; @@ -89,13 +140,30 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ #ifdef SQLITE_ENABLE_API_ARMOR if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; #endif + pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex(); + sqlite3_mutex_enter(pMutex); *pCurrent = wsdStat.nowValue[op]; *pHighwater = wsdStat.mxValue[op]; if( resetFlag ){ wsdStat.mxValue[op] = wsdStat.nowValue[op]; } + sqlite3_mutex_leave(pMutex); + (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */ return SQLITE_OK; } +int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ + sqlite3_int64 iCur, iHwtr; + int rc; +#ifdef SQLITE_ENABLE_API_ARMOR + if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; +#endif + rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag); + if( rc==0 ){ + *pCurrent = (int)iCur; + *pHighwater = (int)iHwtr; + } + return rc; +} /* ** Query status information for a single database connection diff --git a/src/table.c b/src/table.c index 235d8dd..153bfb3 100644 --- a/src/table.c +++ b/src/table.c @@ -90,7 +90,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ z = 0; }else{ int n = sqlite3Strlen30(argv[i])+1; - z = sqlite3_malloc( n ); + z = sqlite3_malloc64( n ); if( z==0 ) goto malloc_failed; memcpy(z, argv[i], n); } @@ -139,7 +139,7 @@ int sqlite3_get_table( res.nData = 1; res.nAlloc = 20; res.rc = SQLITE_OK; - res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc ); + res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc ); if( res.azResult==0 ){ db->errCode = SQLITE_NOMEM; return SQLITE_NOMEM; @@ -167,7 +167,7 @@ int sqlite3_get_table( } if( res.nAlloc>res.nData ){ char **azNew; - azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData ); + azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData ); if( azNew==0 ){ sqlite3_free_table(&res.azResult[1]); db->errCode = SQLITE_NOMEM; diff --git a/src/tclsqlite.c b/src/tclsqlite.c index a912e8a..3e9c986 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -661,9 +661,9 @@ static int DbWalHandler( #if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY) static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){ char zBuf[64]; - sprintf(zBuf, "%d", iArg); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", iArg); Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY); - sprintf(zBuf, "%d", nArg); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nArg); Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY); } #else @@ -1191,7 +1191,7 @@ static int dbPrepareAndBind( int n; u8 *data; const char *zType = (pVar->typePtr ? pVar->typePtr->name : ""); - char c = zType[0]; + c = zType[0]; if( zVar[0]=='@' || (c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){ /* Load a BLOB type if the Tcl variable is a bytearray and @@ -2298,7 +2298,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ } Tcl_DecrRefCount(pRet); }else{ - ClientData cd[2]; + ClientData cd2[2]; DbEvalContext *p; Tcl_Obj *pArray = 0; Tcl_Obj *pScript; @@ -2312,42 +2312,57 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext)); dbEvalInit(p, pDb, objv[2], pArray); - cd[0] = (void *)p; - cd[1] = (void *)pScript; - rc = DbEvalNextCmd(cd, interp, TCL_OK); + cd2[0] = (void *)p; + cd2[1] = (void *)pScript; + rc = DbEvalNextCmd(cd2, interp, TCL_OK); } break; } /* - ** $db function NAME [-argcount N] SCRIPT + ** $db function NAME [-argcount N] [-deterministic] SCRIPT ** ** Create a new SQL function called NAME. Whenever that function is ** called, invoke SCRIPT to evaluate the function. */ case DB_FUNCTION: { + int flags = SQLITE_UTF8; SqlFunc *pFunc; Tcl_Obj *pScript; char *zName; int nArg = -1; - if( objc==6 ){ - const char *z = Tcl_GetString(objv[3]); + int i; + if( objc<4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT"); + return TCL_ERROR; + } + for(i=3; i<(objc-1); i++){ + const char *z = Tcl_GetString(objv[i]); int n = strlen30(z); if( n>2 && strncmp(z, "-argcount",n)==0 ){ - if( Tcl_GetIntFromObj(interp, objv[4], &nArg) ) return TCL_ERROR; + if( i==(objc-2) ){ + Tcl_AppendResult(interp, "option requires an argument: ", z, 0); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[i+1], &nArg) ) return TCL_ERROR; if( nArg<0 ){ Tcl_AppendResult(interp, "number of arguments must be non-negative", (char*)0); return TCL_ERROR; } + i++; + }else + if( n>2 && strncmp(z, "-deterministic",n)==0 ){ + flags |= SQLITE_DETERMINISTIC; + }else{ + Tcl_AppendResult(interp, "bad option \"", z, + "\": must be -argcount or -deterministic", 0 + ); + return TCL_ERROR; } - pScript = objv[5]; - }else if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME [-argcount N] SCRIPT"); - return TCL_ERROR; - }else{ - pScript = objv[3]; } + + pScript = objv[objc-1]; zName = Tcl_GetStringFromObj(objv[2], 0); pFunc = findSqlFunc(pDb, zName); if( pFunc==0 ) return TCL_ERROR; @@ -2357,7 +2372,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ pFunc->pScript = pScript; Tcl_IncrRefCount(pScript); pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); - rc = sqlite3_create_function(pDb->db, zName, nArg, SQLITE_UTF8, + rc = sqlite3_create_function(pDb->db, zName, nArg, flags, pFunc, tclSqlFunc, 0, 0); if( rc!=SQLITE_OK ){ rc = TCL_ERROR; @@ -3429,7 +3444,7 @@ static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){ for(i=j=0; i<16; i+=2){ x = digest[i]*256 + digest[i+1]; if( i>0 ) zDigest[j++] = '-'; - sprintf(&zDigest[j], "%05u", x); + sqlite3_snprintf(50-j, &zDigest[j], "%05u", x); j += 5; } zDigest[j] = 0; @@ -3689,7 +3704,44 @@ static int db_last_stmt_ptr( return TCL_OK; } -#endif +#endif /* SQLITE_TEST */ + +#if defined(SQLITE_TEST) || defined(SQLITE_ENABLE_DBSTAT_VTAB) +/* +** tclcmd: register_dbstat_vtab DB +** +** Cause the dbstat virtual table to be available on the connection DB +*/ +static int sqlite3RegisterDbstatCmd( + void *clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ +#ifdef SQLITE_OMIT_VIRTUALTABLE + Tcl_AppendResult(interp, "dbstat not available because of " + "SQLITE_OMIT_VIRTUALTABLE", (void*)0); + return TCL_ERROR; +#else + struct SqliteDb { sqlite3 *db; }; + char *zDb; + Tcl_CmdInfo cmdInfo; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + + zDb = Tcl_GetString(objv[1]); + if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){ + int sqlite3_dbstat_register(sqlite3*); + sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db; + sqlite3_dbstat_register(db); + } + return TCL_OK; +#endif /* SQLITE_OMIT_VIRTUALTABLE */ +} +#endif /* defined(SQLITE_TEST) || defined(SQLITE_ENABLE_DBSTAT_VTAB) */ /* ** Configure the interpreter passed as the first argument to have access @@ -3713,11 +3765,10 @@ static void init_all(Tcl_Interp *interp){ ** of virtual table dbstat (source file test_stat.c). This command is ** required for testfixture and sqlite3_analyzer, but not by the production ** Tcl extension. */ -#if defined(SQLITE_TEST) || TCLSH==2 - { - extern int SqlitetestStat_Init(Tcl_Interp*); - SqlitetestStat_Init(interp); - } +#if defined(SQLITE_TEST) || defined(SQLITE_ENABLE_DBSTAT_VTAB) + Tcl_CreateObjCommand( + interp, "register_dbstat_vtab", sqlite3RegisterDbstatCmd, 0, 0 + ); #endif #ifdef SQLITE_TEST diff --git a/src/test1.c b/src/test1.c index 8f21660..a87fcd8 100644 --- a/src/test1.c +++ b/src/test1.c @@ -94,10 +94,7 @@ static int get_sqlite_pointer( return TCL_ERROR; } p = (struct SqliteDb*)cmdInfo.objClientData; - sprintf(zBuf, "%p", p->db); - if( strncmp(zBuf,"0x",2) ){ - sprintf(zBuf, "0x%p", p->db); - } + sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p->db); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } @@ -145,7 +142,8 @@ int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){ && sqlite3_errcode(db)!=rc ){ char zBuf[200]; int r2 = sqlite3_errcode(db); - sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)", + sqlite3_snprintf(sizeof(zBuf), zBuf, + "error code %s (%d) does not match sqlite3_errcode %s (%d)", t1ErrorName(rc), rc, t1ErrorName(r2), r2); Tcl_ResetResult(interp); Tcl_AppendResult(interp, zBuf, 0); @@ -310,7 +308,7 @@ static int test_exec_printf( zSql = sqlite3_mprintf(argv[2], argv[3]); rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); sqlite3_free(zSql); - sprintf(zBuf, "%d", rc); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); Tcl_AppendElement(interp, zBuf); Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); Tcl_DStringFree(&str); @@ -357,7 +355,7 @@ static int test_exec_hex( zSql[i] = 0; Tcl_DStringInit(&str); rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); - sprintf(zBuf, "%d", rc); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); Tcl_AppendElement(interp, zBuf); Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); Tcl_DStringFree(&str); @@ -442,7 +440,7 @@ static int test_exec( zSql[j] = 0; rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr); sqlite3_free(zSql); - sprintf(zBuf, "%d", rc); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); Tcl_AppendElement(interp, zBuf); Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr); Tcl_DStringFree(&str); @@ -591,13 +589,13 @@ static int test_get_table_printf( resCount = (nRow+1)*nCol; } sqlite3_free(zSql); - sprintf(zBuf, "%d", rc); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc); Tcl_AppendElement(interp, zBuf); if( rc==SQLITE_OK ){ if( argc==4 ){ - sprintf(zBuf, "%d", nRow); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nRow); Tcl_AppendElement(interp, zBuf); - sprintf(zBuf, "%d", nCol); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nCol); Tcl_AppendElement(interp, zBuf); } for(i=0; i9 || n1<1 ){ - sprintf(zErr, "putVarint returned %d - should be between 1 and 9", n1); + sqlite3_snprintf(sizeof(zErr), zErr, + "putVarint returned %d - should be between 1 and 9", n1); Tcl_AppendResult(interp, zErr, 0); return TCL_ERROR; } n2 = getVarint(zBuf, &out); if( n1!=n2 ){ - sprintf(zErr, "putVarint returned %d and getVarint returned %d", n1, n2); + sqlite3_snprintf(sizeof(zErr), zErr, + "putVarint returned %d and getVarint returned %d", n1, n2); Tcl_AppendResult(interp, zErr, 0); return TCL_ERROR; } if( in!=out ){ - sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx", in, out); + sqlite3_snprintf(sizeof(zErr), zErr, + "Wrote 0x%016llx and got back 0x%016llx", in, out); Tcl_AppendResult(interp, zErr, 0); return TCL_ERROR; } @@ -465,13 +468,15 @@ static int btree_varint_test( n2 = getVarint32(zBuf, out32); out = out32; if( n1!=n2 ){ - sprintf(zErr, "putVarint returned %d and GetVarint32 returned %d", + sqlite3_snprintf(sizeof(zErr), zErr, + "putVarint returned %d and GetVarint32 returned %d", n1, n2); Tcl_AppendResult(interp, zErr, 0); return TCL_ERROR; } if( in!=out ){ - sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx from GetVarint32", + sqlite3_snprintf(sizeof(zErr), zErr, + "Wrote 0x%016llx and got back 0x%016llx from GetVarint32", in, out); Tcl_AppendResult(interp, zErr, 0); return TCL_ERROR; diff --git a/src/test4.c b/src/test4.c index a6375c7..d689030 100644 --- a/src/test4.c +++ b/src/test4.c @@ -270,7 +270,7 @@ static int tcl_thread_argc( return TCL_ERROR; } thread_wait(&threadset[i]); - sprintf(zBuf, "%d", threadset[i].argc); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", threadset[i].argc); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } diff --git a/src/test7.c b/src/test7.c index 93bf1e4..6ba3631 100644 --- a/src/test7.c +++ b/src/test7.c @@ -315,7 +315,7 @@ static int tcl_client_argc( return TCL_ERROR; } client_wait(&threadset[i]); - sprintf(zBuf, "%d", threadset[i].argc); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", threadset[i].argc); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } diff --git a/src/test8.c b/src/test8.c index f37a28c..2107710 100644 --- a/src/test8.c +++ b/src/test8.c @@ -206,8 +206,8 @@ static int getColumnNames( zSpace = (char *)(&aCol[nCol]); for(ii=0; ii +#include "sqlite3.h" #include /* These functions are implemented in main.c. */ diff --git a/src/test_blob.c b/src/test_blob.c index d88c913..4a7075a 100644 --- a/src/test_blob.c +++ b/src/test_blob.c @@ -16,6 +16,7 @@ #include #include #include +#ifndef SQLITE_OMIT_INCRBLOB /* These functions are implemented in main.c. */ extern const char *sqlite3ErrName(int); @@ -295,12 +296,13 @@ static int test_blob_write( return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); } - +#endif /* SQLITE_OMIT_INCRBLOB */ /* ** Register commands with the TCL interpreter. */ int Sqlitetest_blob_Init(Tcl_Interp *interp){ +#ifndef SQLITE_OMIT_INCRBLOB static struct { char *zName; Tcl_ObjCmdProc *xProc; @@ -315,5 +317,6 @@ int Sqlitetest_blob_Init(Tcl_Interp *interp){ for(i=0; i +#include "sqlite3.h" #include #include diff --git a/src/test_func.c b/src/test_func.c index c785063..2e34fa0 100644 --- a/src/test_func.c +++ b/src/test_func.c @@ -600,12 +600,26 @@ static void test_decode( Tcl_DecrRefCount(pRet); } +/* +** The implementation of scalar SQL function "test_zeroblob()". This is +** similar to the built-in zeroblob() function, except that it does not +** check that the integer parameter is within range before passing it +** to sqlite3_result_zeroblob(). +*/ +static void test_zeroblob( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int nZero = sqlite3_value_int(argv[0]); + sqlite3_result_zeroblob(context, nZero); +} static int registerTestFunctions(sqlite3 *db){ static const struct { char *zName; signed char nArg; - unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */ + unsigned int eTextRep; /* 1: UTF-16. 0: UTF-8 */ void (*xFunc)(sqlite3_context*,int,sqlite3_value **); } aFuncs[] = { { "randstr", 2, SQLITE_UTF8, randStr }, @@ -626,6 +640,7 @@ static int registerTestFunctions(sqlite3 *db){ { "real2hex", 1, SQLITE_UTF8, real2hex}, { "test_decode", 1, SQLITE_UTF8, test_decode}, { "test_extract", 2, SQLITE_UTF8, test_extract}, + { "test_zeroblob", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob}, }; int i; diff --git a/src/test_intarray.c b/src/test_intarray.c index 7235fbc..70e34db 100644 --- a/src/test_intarray.c +++ b/src/test_intarray.c @@ -85,7 +85,7 @@ static int intarrayCreate( char **pzErr /* Put error message text here */ ){ int rc = SQLITE_NOMEM; - intarray_vtab *pVtab = sqlite3_malloc(sizeof(intarray_vtab)); + intarray_vtab *pVtab = sqlite3_malloc64(sizeof(intarray_vtab)); if( pVtab ){ memset(pVtab, 0, sizeof(intarray_vtab)); @@ -102,7 +102,7 @@ static int intarrayCreate( static int intarrayOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ int rc = SQLITE_NOMEM; intarray_cursor *pCur; - pCur = sqlite3_malloc(sizeof(intarray_cursor)); + pCur = sqlite3_malloc64(sizeof(intarray_cursor)); if( pCur ){ memset(pCur, 0, sizeof(intarray_cursor)); *ppCursor = (sqlite3_vtab_cursor *)pCur; @@ -225,7 +225,7 @@ SQLITE_API int sqlite3_intarray_create( #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3_intarray *p; - *ppReturn = p = sqlite3_malloc( sizeof(*p) ); + *ppReturn = p = sqlite3_malloc64( sizeof(*p) ); if( p==0 ){ return SQLITE_NOMEM; } @@ -340,7 +340,7 @@ static int test_intarray_bind( pArray = (sqlite3_intarray*)sqlite3TestTextToPtr(Tcl_GetString(objv[1])); n = objc - 2; #ifndef SQLITE_OMIT_VIRTUALTABLE - a = sqlite3_malloc( sizeof(a[0])*n ); + a = sqlite3_malloc64( sizeof(a[0])*n ); if( a==0 ){ Tcl_AppendResult(interp, "SQLITE_NOMEM", (char*)0); return TCL_ERROR; diff --git a/src/test_malloc.c b/src/test_malloc.c index 1ea4de5..94a2282 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -211,15 +211,15 @@ static int faultsimInstall(int install){ faultsimBeginBenign, faultsimEndBenign ); }else{ - sqlite3_mem_methods m; + sqlite3_mem_methods m2; assert(memfault.m.xMalloc); /* One should be able to reset the default memory allocator by storing ** a zeroed allocator then calling GETMALLOC. */ - memset(&m, 0, sizeof(m)); - sqlite3_config(SQLITE_CONFIG_MALLOC, &m); - sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m); - assert( memcmp(&m, &memfault.m, sizeof(m))==0 ); + memset(&m2, 0, sizeof(m2)); + sqlite3_config(SQLITE_CONFIG_MALLOC, &m2); + sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2); + assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 ); rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m); sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0); diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 8f204c6..843a92c 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -286,7 +286,7 @@ static void multiplexFilename( static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ if( iChunk>=pGroup->nReal ){ struct multiplexReal *p; - p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p)); + p = sqlite3_realloc64(pGroup->aReal, (iChunk+1)*sizeof(*p)); if( p==0 ){ return SQLITE_NOMEM; } @@ -297,7 +297,7 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){ if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){ char *z; int n = pGroup->nName; - pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+5 ); + pGroup->aReal[iChunk].z = z = sqlite3_malloc64( n+5 ); if( z==0 ){ return SQLITE_NOMEM; } @@ -357,7 +357,7 @@ static sqlite3_file *multiplexSubOpen( } flags &= ~SQLITE_OPEN_CREATE; } - pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile ); + pSubOpen = sqlite3_malloc64( pOrigVfs->szOsFile ); if( pSubOpen==0 ){ *rc = SQLITE_IOERR_NOMEM; return 0; @@ -524,7 +524,7 @@ static int multiplexOpen( nName = zName ? multiplexStrlen30(zName) : 0; sz = sizeof(multiplexGroup) /* multiplexGroup */ + nName + 1; /* zName */ - pGroup = sqlite3_malloc( sz ); + pGroup = sqlite3_malloc64( sz ); if( pGroup==0 ){ rc = SQLITE_NOMEM; } @@ -568,12 +568,15 @@ static int multiplexOpen( if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN; } if( rc==SQLITE_OK ){ - sqlite3_int64 sz; + sqlite3_int64 sz64; - rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz); + rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz64); if( rc==SQLITE_OK && zName ){ int bExists; - if( sz==0 ){ + if( flags & SQLITE_OPEN_MASTER_JOURNAL ){ + pGroup->bEnabled = 0; + }else + if( sz64==0 ){ if( flags & SQLITE_OPEN_MAIN_JOURNAL ){ /* If opening a main journal file and the first chunk is zero ** bytes in size, delete any subsequent chunks from the @@ -604,10 +607,10 @@ static int multiplexOpen( rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z, SQLITE_ACCESS_EXISTS, &bExists); bExists = multiplexSubSize(pGroup, 1, &rc)>0; - if( rc==SQLITE_OK && bExists && sz==(sz&0xffff0000) && sz>0 - && sz!=pGroup->szChunk ){ - pGroup->szChunk = (int)sz; - }else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){ + if( rc==SQLITE_OK && bExists && sz64==(sz64&0xffff0000) && sz64>0 + && sz64!=pGroup->szChunk ){ + pGroup->szChunk = (int)sz64; + }else if( rc==SQLITE_OK && !bExists && sz64>pGroup->szChunk ){ pGroup->bEnabled = 0; } } @@ -652,7 +655,7 @@ static int multiplexDelete( */ int nName = (int)strlen(zName); char *z; - z = sqlite3_malloc(nName + 5); + z = sqlite3_malloc64(nName + 5); if( z==0 ){ rc = SQLITE_IOERR_NOMEM; }else{ @@ -1004,6 +1007,13 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ break; case SQLITE_FCNTL_PRAGMA: { char **aFcntl = (char**)pArg; + /* + ** EVIDENCE-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA + ** file control is an array of pointers to strings (char**) in which the + ** second element of the array is the name of the pragma and the third + ** element is the argument to the pragma or NULL if the pragma has no + ** argument. + */ if( aFcntl[1] && sqlite3_stricmp(aFcntl[1],"multiplex_truncate")==0 ){ if( aFcntl[2] && aFcntl[2][0] ){ if( sqlite3_stricmp(aFcntl[2], "on")==0 @@ -1015,6 +1025,12 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){ pGroup->bTruncate = 0; } } + /* EVIDENCE-OF: R-27806-26076 The handler for an SQLITE_FCNTL_PRAGMA + ** file control can optionally make the first element of the char** + ** argument point to a string obtained from sqlite3_mprintf() or the + ** equivalent and that string will become the result of the pragma + ** or the error message if the pragma fails. + */ aFcntl[0] = sqlite3_mprintf(pGroup->bTruncate ? "on" : "off"); rc = SQLITE_OK; break; diff --git a/src/test_onefile.c b/src/test_onefile.c index 6986744..122be70 100644 --- a/src/test_onefile.c +++ b/src/test_onefile.c @@ -595,9 +595,9 @@ static int fsOpen( int rc = SQLITE_OK; if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){ - tmp_file *p = (tmp_file *)pFile; - memset(p, 0, sizeof(*p)); - p->base.pMethods = &tmp_io_methods; + tmp_file *p2 = (tmp_file *)pFile; + memset(p2, 0, sizeof(*p2)); + p2->base.pMethods = &tmp_io_methods; return SQLITE_OK; } diff --git a/src/test_osinst.c b/src/test_osinst.c index 1701def..4ae23a8 100644 --- a/src/test_osinst.c +++ b/src/test_osinst.c @@ -1131,7 +1131,6 @@ static int test_vfslog( switch( (enum VL_enum)iSub ){ case VL_ANNOTATE: { - int rc; char *zVfs; char *zMsg; if( objc!=4 ){ @@ -1148,7 +1147,6 @@ static int test_vfslog( break; } case VL_FINALIZE: { - int rc; char *zVfs; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "VFS"); @@ -1164,7 +1162,6 @@ static int test_vfslog( }; case VL_NEW: { - int rc; char *zVfs; char *zParent; char *zLog; diff --git a/src/test_rtree.c b/src/test_rtree.c index 9d19fa0..7beec66 100644 --- a/src/test_rtree.c +++ b/src/test_rtree.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. */ -#include +#include "sqlite3.h" #include /* Solely for the UNUSED_PARAMETER() macro. */ diff --git a/src/test_sqllog.c b/src/test_sqllog.c index 4aa68b7..6c0bf95 100644 --- a/src/test_sqllog.c +++ b/src/test_sqllog.c @@ -365,8 +365,10 @@ static void sqllogOpenlog(struct SLConn *p){ FILE *fd; char *zVar = getenv(ENVIRONMENT_VARIABLE1_NAME); if( zVar==0 || strlen(zVar)+10>=(sizeof(sqllogglobal.zPrefix)) ) return; - sprintf(sqllogglobal.zPrefix, "%s/sqllog_%d", zVar, getProcessId()); - sprintf(sqllogglobal.zIdx, "%s.idx", sqllogglobal.zPrefix); + sqlite3_snprintf(sizeof(sqllogglobal.zPrefix), sqllogglobal.zPrefix, + "%s/sqllog_%d", zVar, getProcessId()); + sqlite3_snprintf(sizeof(sqllogglobal.zIdx), sqllogglobal.zIdx, + "%s.idx", sqllogglobal.zPrefix); if( getenv(ENVIRONMENT_VARIABLE2_NAME) ){ sqllogglobal.bReuse = atoi(getenv(ENVIRONMENT_VARIABLE2_NAME)); } diff --git a/src/test_superlock.c b/src/test_superlock.c index 936fcad..cac7898 100644 --- a/src/test_superlock.c +++ b/src/test_superlock.c @@ -18,7 +18,7 @@ ** sqlite3demo_superunlock() */ -#include +#include "sqlite3.h" #include /* memset(), strlen() */ #include /* assert() */ diff --git a/src/test_thread.c b/src/test_thread.c index 2f9363b..a4d96e1 100644 --- a/src/test_thread.c +++ b/src/test_thread.c @@ -608,7 +608,7 @@ static int blocking_prepare_v2_proc( } if( rc!=SQLITE_OK ){ assert( pStmt==0 ); - sprintf(zBuf, "%s ", (char *)sqlite3ErrName(rc)); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%s ", (char *)sqlite3ErrName(rc)); Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); return TCL_ERROR; } diff --git a/src/test_vfs.c b/src/test_vfs.c index 37081af..a8c6ae7 100644 --- a/src/test_vfs.c +++ b/src/test_vfs.c @@ -823,11 +823,12 @@ static int tvfsShmOpen(sqlite3_file *pFile){ if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break; } if( !pBuffer ){ - int nByte = sizeof(TestvfsBuffer) + (int)strlen(pFd->zFilename) + 1; + int szName = (int)strlen(pFd->zFilename); + int nByte = sizeof(TestvfsBuffer) + szName + 1; pBuffer = (TestvfsBuffer *)ckalloc(nByte); memset(pBuffer, 0, nByte); pBuffer->zFile = (char *)&pBuffer[1]; - strcpy(pBuffer->zFile, pFd->zFilename); + memcpy(pBuffer->zFile, pFd->zFilename, szName+1); pBuffer->pNext = p->pBuffer; p->pBuffer = pBuffer; } @@ -966,16 +967,15 @@ static void tvfsShmBarrier(sqlite3_file *pFile){ TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); + if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ + const char *z = pFd->pShm ? pFd->pShm->zFile : ""; + tvfsExecTcl(p, "xShmBarrier", Tcl_NewStringObj(z, -1), pFd->pShmId, 0, 0); + } + if( p->isFullshm ){ sqlite3OsShmBarrier(pFd->pReal); return; } - - if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ - tvfsExecTcl(p, "xShmBarrier", - Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 - ); - } } static int tvfsShmUnmap( @@ -1080,7 +1080,7 @@ static int testvfs_obj_cmd( switch( aSubcmd[i].eCmd ){ case CMD_SHM: { Tcl_Obj *pObj; - int i, rc; + int rc; TestvfsBuffer *pBuffer; char *zName; if( objc!=3 && objc!=4 ){ @@ -1160,7 +1160,6 @@ static int testvfs_obj_cmd( }; Tcl_Obj **apElem = 0; int nElem = 0; - int i; int mask = 0; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "LIST"); @@ -1531,7 +1530,7 @@ static int testvfs_cmd( return TCL_OK; bad_args: - Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?"); + Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-fullshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?"); return TCL_ERROR; } diff --git a/src/threads.c b/src/threads.c index 16f5249..4ce6122 100644 --- a/src/threads.c +++ b/src/threads.c @@ -101,7 +101,7 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ /********************************* Win32 Threads ****************************/ -#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0 +#if SQLITE_OS_WIN_THREADS #define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */ #include @@ -194,7 +194,7 @@ int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){ return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR; } -#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */ +#endif /* SQLITE_OS_WIN_THREADS */ /******************************** End Win32 Threads *************************/ diff --git a/src/tokenize.c b/src/tokenize.c index f0360ee..78baee3 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -390,10 +390,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ - -#ifdef SQLITE_ENABLE_API_ARMOR - if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT; -#endif + assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( db->nVdbeActive==0 ){ db->u1.isInterrupted = 0; @@ -433,10 +430,8 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ break; } case TK_ILLEGAL: { - sqlite3DbFree(db, *pzErrMsg); - *pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"", + sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &pParse->sLastToken); - nErr++; goto abort_parse; } case TK_SEMI: { @@ -454,17 +449,22 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ } } abort_parse: - if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ + assert( nErr==0 ); + if( zSql[i]==0 && pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ if( lastTokenParsed!=TK_SEMI ){ sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); pParse->zTail = &zSql[i]; } - sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); + if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ + sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); + } } #ifdef YYTRACKMAXSTACKDEPTH + sqlite3_mutex_enter(sqlite3MallocMutex()); sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(pEngine) ); + sqlite3_mutex_leave(sqlite3MallocMutex()); #endif /* YYDEBUG */ sqlite3ParserFree(pEngine, sqlite3_free); db->lookaside.bEnabled = enableLookaside; @@ -518,8 +518,6 @@ abort_parse: pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(db, p); } - if( nErr>0 && pParse->rc==SQLITE_OK ){ - pParse->rc = SQLITE_ERROR; - } + assert( nErr==0 || pParse->rc!=SQLITE_OK ); return nErr; } diff --git a/src/trigger.c b/src/trigger.c index d2e7b5a..2eba0cf 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -193,7 +193,6 @@ void sqlite3BeginTrigger( /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); - pParse->nErr++; goto trigger_cleanup; } @@ -373,12 +372,12 @@ static TriggerStep *triggerStepAllocate( ){ TriggerStep *pTriggerStep; - pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n); + pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); if( pTriggerStep ){ char *z = (char*)&pTriggerStep[1]; memcpy(z, pName->z, pName->n); - pTriggerStep->target.z = z; - pTriggerStep->target.n = pName->n; + sqlite3Dequote(z); + pTriggerStep->zTarget = z; pTriggerStep->op = op; } return pTriggerStep; @@ -661,7 +660,7 @@ Trigger *sqlite3TriggersExist( } /* -** Convert the pStep->target token into a SrcList and return a pointer +** Convert the pStep->zTarget string into a SrcList and return a pointer ** to that SrcList. ** ** This routine adds a specific database name, if needed, to the target when @@ -674,17 +673,17 @@ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ + sqlite3 *db = pParse->db; int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ - pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); + pSrc = sqlite3SrcListAppend(db, 0, 0, 0); if( pSrc ){ assert( pSrc->nSrc>0 ); - assert( pSrc->a!=0 ); - iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); + pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); + iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); if( iDb==0 || iDb>=2 ){ - sqlite3 *db = pParse->db; - assert( iDbdb->nDb ); + assert( iDbnDb ); pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); } } @@ -796,6 +795,7 @@ static void transferParseError(Parse *pTo, Parse *pFrom){ if( pTo->nErr==0 ){ pTo->zErrMsg = pFrom->zErrMsg; pTo->nErr = pFrom->nErr; + pTo->rc = pFrom->rc; }else{ sqlite3DbFree(pFrom->db, pFrom->zErrMsg); } diff --git a/src/util.c b/src/util.c index 6e64242..0bc1eea 100644 --- a/src/util.c +++ b/src/util.c @@ -655,6 +655,7 @@ int sqlite3GetInt32(const char *zNum, int *pValue){ } } #endif + while( zNum[0]=='0' ) zNum++; for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){ v = v*10 + c; } diff --git a/src/vacuum.c b/src/vacuum.c index 9df8e08..adc802e 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -184,7 +184,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** cause problems for the call to BtreeSetPageSize() below. */ sqlite3BtreeCommit(pTemp); - nRes = sqlite3BtreeGetReserve(pMain); + nRes = sqlite3BtreeGetOptimalReserve(pMain); /* A VACUUM cannot change the pagesize of an encrypted database. */ #ifdef SQLITE_HAS_CODEC @@ -250,6 +250,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ ** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy ** the contents to the temporary database. */ + assert( (db->flags & SQLITE_Vacuum)==0 ); + db->flags |= SQLITE_Vacuum; rc = execExecSql(db, pzErrMsg, "SELECT 'INSERT INTO vacuum_db.' || quote(name) " "|| ' SELECT * FROM main.' || quote(name) || ';'" @@ -257,6 +259,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ "WHERE type = 'table' AND name!='sqlite_sequence' " " AND coalesce(rootpage,1)>0" ); + assert( (db->flags & SQLITE_Vacuum)!=0 ); + db->flags &= ~SQLITE_Vacuum; if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Copy over the sequence table diff --git a/src/vdbe.c b/src/vdbe.c index 1e0ff96..e47a3ac 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -296,6 +296,7 @@ static void applyAffinity( if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){ sqlite3VdbeMemStringify(pRec, enc, 1); } + pRec->flags &= ~(MEM_Real|MEM_Int); } } @@ -514,6 +515,21 @@ static int checkSavepointCount(sqlite3 *db){ } #endif +/* +** Return the register of pOp->p2 after first preparing it to be +** overwritten with an integer value. +*/ +static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ + Mem *pOut; + assert( pOp->p2>0 ); + assert( pOp->p2<=(p->nMem-p->nCursor) ); + pOut = &p->aMem[pOp->p2]; + memAboutToChange(p, pOut); + if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); + pOut->flags = MEM_Int; + return pOut; +} + /* ** Execute as much of a VDBE program as we can. @@ -522,9 +538,11 @@ static int checkSavepointCount(sqlite3 *db){ int sqlite3VdbeExec( Vdbe *p /* The VDBE */ ){ - int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ - Op *pOp; /* Current operation */ + Op *pOp = aOp; /* Current operation */ +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + Op *pOrigOp; /* Value of pOp at the top of the loop */ +#endif int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ @@ -600,23 +618,22 @@ int sqlite3VdbeExec( } sqlite3EndBenignMalloc(); #endif - for(pc=p->pc; rc==SQLITE_OK; pc++){ - assert( pc>=0 && pcnOp ); + for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){ + assert( pOp>=aOp && pOp<&aOp[p->nOp]); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif nVmStep++; - pOp = &aOp[pc]; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS - if( p->anExec ) p->anExec[pc]++; + if( p->anExec ) p->anExec[(int)(pOp-aOp)]++; #endif /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ - sqlite3VdbePrintOp(stdout, pc, pOp); + sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp); } #endif @@ -633,23 +650,9 @@ int sqlite3VdbeExec( } #endif - /* On any opcode with the "out2-prerelease" tag, free any - ** external allocations out of mem[p2] and set mem[p2] to be - ** an undefined integer. Opcodes will either fill in the integer - ** value or convert mem[p2] to a different type. - */ - assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); - if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){ - assert( pOp->p2>0 ); - assert( pOp->p2<=(p->nMem-p->nCursor) ); - pOut = &aMem[pOp->p2]; - memAboutToChange(p, pOut); - if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); - pOut->flags = MEM_Int; - } - /* Sanity checking on other operands */ #ifdef SQLITE_DEBUG + assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] ); if( (pOp->opflags & OPFLG_IN1)!=0 ){ assert( pOp->p1>0 ); assert( pOp->p1<=(p->nMem-p->nCursor) ); @@ -682,6 +685,9 @@ int sqlite3VdbeExec( memAboutToChange(p, &aMem[pOp->p3]); } #endif +#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) + pOrigOp = pOp; +#endif switch( pOp->opcode ){ @@ -705,7 +711,7 @@ int sqlite3VdbeExec( ** ** Other keywords in the comment that follows each case are used to ** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[]. -** Keywords include: in1, in2, in3, out2_prerelease, out2, out3. See +** Keywords include: in1, in2, in3, out2, out3. See ** the mkopcodeh.awk script for additional information. ** ** Documentation about VDBE opcodes is generated by scanning this file @@ -733,7 +739,8 @@ int sqlite3VdbeExec( ** to the current line should be indented for EXPLAIN output. */ case OP_Goto: { /* jump */ - pc = pOp->p2 - 1; +jump_to_p2_and_check_for_interrupt: + pOp = &aOp[pOp->p2 - 1]; /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon @@ -778,9 +785,13 @@ case OP_Gosub: { /* jump */ assert( VdbeMemDynamic(pIn1)==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; - pIn1->u.i = pc; + pIn1->u.i = (int)(pOp-aOp); REGISTER_TRACE(pOp->p1, pIn1); - pc = pOp->p2 - 1; + + /* Most jump operations do a goto to this spot in order to update + ** the pOp pointer. */ +jump_to_p2: + pOp = &aOp[pOp->p2 - 1]; break; } @@ -792,7 +803,7 @@ case OP_Gosub: { /* jump */ case OP_Return: { /* in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags==MEM_Int ); - pc = (int)pIn1->u.i; + pOp = &aOp[pIn1->u.i]; pIn1->flags = MEM_Undefined; break; } @@ -816,7 +827,7 @@ case OP_InitCoroutine: { /* jump */ assert( !VdbeMemDynamic(pOut) ); pOut->u.i = pOp->p3 - 1; pOut->flags = MEM_Int; - if( pOp->p2 ) pc = pOp->p2 - 1; + if( pOp->p2 ) goto jump_to_p2; break; } @@ -836,7 +847,7 @@ case OP_EndCoroutine: { /* in1 */ pCaller = &aOp[pIn1->u.i]; assert( pCaller->opcode==OP_Yield ); assert( pCaller->p2>=0 && pCaller->p2nOp ); - pc = pCaller->p2 - 1; + pOp = &aOp[pCaller->p2 - 1]; pIn1->flags = MEM_Undefined; break; } @@ -860,9 +871,9 @@ case OP_Yield: { /* in1, jump */ assert( VdbeMemDynamic(pIn1)==0 ); pIn1->flags = MEM_Int; pcDest = (int)pIn1->u.i; - pIn1->u.i = pc; + pIn1->u.i = (int)(pOp - aOp); REGISTER_TRACE(pOp->p1, pIn1); - pc = pcDest; + pOp = &aOp[pcDest]; break; } @@ -913,30 +924,34 @@ case OP_HaltIfNull: { /* in3 */ case OP_Halt: { const char *zType; const char *zLogFmt; + VdbeFrame *pFrame; + int pcx; + pcx = (int)(pOp - aOp); if( pOp->p1==SQLITE_OK && p->pFrame ){ /* Halt the sub-program. Return control to the parent frame. */ - VdbeFrame *pFrame = p->pFrame; + pFrame = p->pFrame; p->pFrame = pFrame->pParent; p->nFrame--; sqlite3VdbeSetChanges(db, p->nChange); - pc = sqlite3VdbeFrameRestore(pFrame); + pcx = sqlite3VdbeFrameRestore(pFrame); lastRowid = db->lastRowid; if( pOp->p2==OE_Ignore ){ - /* Instruction pc is the OP_Program that invoked the sub-program + /* Instruction pcx is the OP_Program that invoked the sub-program ** currently being halted. If the p2 instruction of this OP_Halt ** instruction is set to OE_Ignore, then the sub-program is throwing ** an IGNORE exception. In this case jump to the address specified ** as the p2 of the calling OP_Program. */ - pc = p->aOp[pc].p2-1; + pcx = p->aOp[pcx].p2-1; } aOp = p->aOp; aMem = p->aMem; + pOp = &aOp[pcx]; break; } p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; - p->pc = pc; + p->pc = pcx; if( p->rc ){ if( pOp->p5 ){ static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK", @@ -960,7 +975,7 @@ case OP_Halt: { }else{ sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType); } - sqlite3_log(pOp->p1, zLogFmt, pc, p->zSql, p->zErrMsg); + sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR ); @@ -979,7 +994,8 @@ case OP_Halt: { ** ** The 32-bit integer value P1 is written into register P2. */ -case OP_Integer: { /* out2-prerelease */ +case OP_Integer: { /* out2 */ + pOut = out2Prerelease(p, pOp); pOut->u.i = pOp->p1; break; } @@ -990,7 +1006,8 @@ case OP_Integer: { /* out2-prerelease */ ** P4 is a pointer to a 64-bit integer value. ** Write that value into register P2. */ -case OP_Int64: { /* out2-prerelease */ +case OP_Int64: { /* out2 */ + pOut = out2Prerelease(p, pOp); assert( pOp->p4.pI64!=0 ); pOut->u.i = *pOp->p4.pI64; break; @@ -1003,7 +1020,8 @@ case OP_Int64: { /* out2-prerelease */ ** P4 is a pointer to a 64-bit floating point value. ** Write that value into register P2. */ -case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ +case OP_Real: { /* same as TK_FLOAT, out2 */ + pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Real; assert( !sqlite3IsNaN(*pOp->p4.pReal) ); pOut->u.r = *pOp->p4.pReal; @@ -1015,12 +1033,13 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */ ** Synopsis: r[P2]='P4' ** ** P4 points to a nul terminated UTF-8 string. This opcode is transformed -** into a String before it is executed for the first time. During +** into a String opcode before it is executed for the first time. During ** this transformation, the length of string P4 is computed and stored ** as the P1 parameter. */ -case OP_String8: { /* same as TK_STRING, out2-prerelease */ +case OP_String8: { /* same as TK_STRING, out2 */ assert( pOp->p4.z!=0 ); + pOut = out2Prerelease(p, pOp); pOp->opcode = OP_String; pOp->p1 = sqlite3Strlen30(pOp->p4.z); @@ -1047,18 +1066,31 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */ /* Fall through to the next case, OP_String */ } -/* Opcode: String P1 P2 * P4 * +/* Opcode: String P1 P2 P3 P4 P5 ** Synopsis: r[P2]='P4' (len=P1) ** ** The string value P4 of length P1 (bytes) is stored in register P2. +** +** If P5!=0 and the content of register P3 is greater than zero, then +** the datatype of the register P2 is converted to BLOB. The content is +** the same sequence of bytes, it is merely interpreted as a BLOB instead +** of a string, as if it had been CAST. */ -case OP_String: { /* out2-prerelease */ +case OP_String: { /* out2 */ assert( pOp->p4.z!=0 ); + pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = pOp->p4.z; pOut->n = pOp->p1; pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); + if( pOp->p5 ){ + assert( pOp->p3>0 ); + assert( pOp->p3<=(p->nMem-p->nCursor) ); + pIn3 = &aMem[pOp->p3]; + assert( pIn3->flags & MEM_Int ); + if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term; + } break; } @@ -1074,9 +1106,10 @@ case OP_String: { /* out2-prerelease */ ** NULL values will not compare equal even if SQLITE_NULLEQ is set on ** OP_Ne or OP_Eq. */ -case OP_Null: { /* out2-prerelease */ +case OP_Null: { /* out2 */ int cnt; u16 nullFlag; + pOut = out2Prerelease(p, pOp); cnt = pOp->p3-pOp->p2; assert( pOp->p3<=(p->nMem-p->nCursor) ); pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null; @@ -1111,8 +1144,9 @@ case OP_SoftNull: { ** P4 points to a blob of data P1 bytes long. Store this ** blob in register P2. */ -case OP_Blob: { /* out2-prerelease */ +case OP_Blob: { /* out2 */ assert( pOp->p1 <= SQLITE_MAX_LENGTH ); + pOut = out2Prerelease(p, pOp); sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); @@ -1127,7 +1161,7 @@ case OP_Blob: { /* out2-prerelease */ ** If the parameter is named, then its name appears in P4. ** The P4 value is used by sqlite3_bind_parameter_name(). */ -case OP_Variable: { /* out2-prerelease */ +case OP_Variable: { /* out2 */ Mem *pVar; /* Value being transferred */ assert( pOp->p1>0 && pOp->p1<=p->nVar ); @@ -1136,6 +1170,7 @@ case OP_Variable: { /* out2-prerelease */ if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; } + pOut = out2Prerelease(p, pOp); sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); UPDATE_MAX_BLOBSIZE(pOut); break; @@ -1170,10 +1205,11 @@ case OP_Move: { memAboutToChange(p, pOut); sqlite3VdbeMemMove(pOut, pIn1); #ifdef SQLITE_DEBUG - if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){ - pOut->pScopyFrom += p1 - pOp->p2; + if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrompScopyFrom += pOp->p2 - p1; } #endif + Deephemeralize(pOut); REGISTER_TRACE(p2++, pOut); pIn1++; pOut++; @@ -1312,7 +1348,7 @@ case OP_ResultRow: { /* Return SQLITE_ROW */ - p->pc = pc + 1; + p->pc = (int)(pOp - aOp) + 1; rc = SQLITE_ROW; goto vdbe_return; } @@ -1505,7 +1541,7 @@ arithmetic_result_is_null: ** ** The interface used by the implementation of the aforementioned functions ** to retrieve the collation sequence set by this opcode is not available -** publicly, only to user functions defined in func.c. +** publicly. Only built-in functions have access to this feature. */ case OP_CollSeq: { assert( pOp->p4type==P4_COLLSEQ ); @@ -1558,7 +1594,7 @@ case OP_Function: { assert( pOp->p4type==P4_FUNCDEF ); ctx.pFunc = pOp->p4.pFunc; - ctx.iOp = pc; + ctx.iOp = (int)(pOp - aOp); ctx.pVdbe = p; MemSetTypeFlag(ctx.pOut, MEM_Null); ctx.fErrorOrAux = 0; @@ -1572,7 +1608,7 @@ case OP_Function: { sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(ctx.pOut)); rc = ctx.isError; } - sqlite3VdbeDeleteAuxData(p, pc, pOp->p1); + sqlite3VdbeDeleteAuxData(p, (int)(pOp - aOp), pOp->p1); } /* Copy the result of the function into register P3 */ @@ -1701,8 +1737,7 @@ case OP_MustBeInt: { /* jump, in1 */ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ - pc = pOp->p2 - 1; - break; + goto jump_to_p2; } } } @@ -1888,7 +1923,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ }else{ VdbeBranchTaken(2,3); if( pOp->p5 & SQLITE_JUMPIFNULL ){ - pc = pOp->p2-1; + goto jump_to_p2; } } break; @@ -1908,11 +1943,15 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_Real ); sqlite3VdbeMemStringify(pIn1, encoding, 1); + testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); + flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); } if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){ testcase( pIn3->flags & MEM_Int ); testcase( pIn3->flags & MEM_Real ); sqlite3VdbeMemStringify(pIn3, encoding, 1); + testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) ); + flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask); } } assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 ); @@ -1936,6 +1975,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ default: res = res>=0; break; } + /* Undo any changes made by applyAffinity() to the input registers. */ + assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); + pIn1->flags = flags1; + assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) ); + pIn3->flags = flags3; + if( pOp->p5 & SQLITE_STOREP2 ){ pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); @@ -1945,12 +1990,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ }else{ VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); if( res ){ - pc = pOp->p2-1; + goto jump_to_p2; } } - /* Undo any changes made by applyAffinity() to the input registers. */ - pIn1->flags = flags1; - pIn3->flags = flags3; break; } @@ -2045,11 +2087,11 @@ case OP_Compare: { */ case OP_Jump: { /* jump */ if( iCompare<0 ){ - pc = pOp->p1 - 1; VdbeBranchTaken(0,3); + VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1]; }else if( iCompare==0 ){ - pc = pOp->p2 - 1; VdbeBranchTaken(1,3); + VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1]; }else{ - pc = pOp->p3 - 1; VdbeBranchTaken(2,3); + VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1]; } break; } @@ -2159,7 +2201,7 @@ case OP_Once: { /* jump */ assert( pOp->p1nOnceFlag ); VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); if( p->aOnceFlag[pOp->p1] ){ - pc = pOp->p2-1; + goto jump_to_p2; }else{ p->aOnceFlag[pOp->p1] = 1; } @@ -2194,7 +2236,7 @@ case OP_IfNot: { /* jump, in1 */ } VdbeBranchTaken(c!=0, 2); if( c ){ - pc = pOp->p2-1; + goto jump_to_p2; } break; } @@ -2208,7 +2250,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2); if( (pIn1->flags & MEM_Null)!=0 ){ - pc = pOp->p2 - 1; + goto jump_to_p2; } break; } @@ -2222,7 +2264,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ pIn1 = &aMem[pOp->p1]; VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2); if( (pIn1->flags & MEM_Null)==0 ){ - pc = pOp->p2 - 1; + goto jump_to_p2; } break; } @@ -2436,7 +2478,7 @@ case OP_Column: { } } - /* If after trying to extra new entries from the header, nHdrParsed is + /* If after trying to extract new entries from the header, nHdrParsed is ** still not up to p2, that means that the record has fewer than p2 ** columns. So the result will be either the default value or a NULL. */ @@ -2560,7 +2602,7 @@ case OP_MakeRecord: { u64 nData; /* Number of bytes of data space */ int nHdr; /* Number of bytes of header space */ i64 nByte; /* Data space required for this record */ - int nZero; /* Number of zero bytes at the end of the record */ + i64 nZero; /* Number of zero bytes at the end of the record */ int nVarint; /* Number of bytes in a varint */ u32 serial_type; /* Type field */ Mem *pData0; /* First field to be combined into the record */ @@ -2652,7 +2694,7 @@ case OP_MakeRecord: { if( nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){ + if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } @@ -2703,7 +2745,7 @@ case OP_MakeRecord: { ** opened by cursor P1 in register P2 */ #ifndef SQLITE_OMIT_BTREECOUNT -case OP_Count: { /* out2-prerelease */ +case OP_Count: { /* out2 */ i64 nEntry; BtCursor *pCrsr; @@ -2711,6 +2753,7 @@ case OP_Count: { /* out2-prerelease */ assert( pCrsr ); nEntry = 0; /* Not needed. Only used to silence a warning. */ rc = sqlite3BtreeCount(pCrsr, &nEntry); + pOut = out2Prerelease(p, pOp); pOut->u.i = nEntry; break; } @@ -2824,7 +2867,7 @@ case OP_Savepoint: { } db->autoCommit = 1; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = pc; + p->pc = (int)(pOp - aOp); db->autoCommit = 0; p->rc = rc = SQLITE_BUSY; goto vdbe_return; @@ -2883,7 +2926,7 @@ case OP_Savepoint: { db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } - if( !isTransaction ){ + if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){ rc = sqlite3VtabSavepoint(db, p1, iSavepoint); if( rc!=SQLITE_OK ) goto abort_due_to_error; } @@ -2943,7 +2986,7 @@ case OP_AutoCommit: { }else{ db->autoCommit = (u8)desiredAutoCommit; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pc = pc; + p->pc = (int)(pOp - aOp); db->autoCommit = (u8)(1-desiredAutoCommit); p->rc = rc = SQLITE_BUSY; goto vdbe_return; @@ -3020,7 +3063,7 @@ case OP_Transaction: { if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ - p->pc = pc; + p->pc = (int)(pOp - aOp); p->rc = rc = SQLITE_BUSY; goto vdbe_return; } @@ -3050,7 +3093,12 @@ case OP_Transaction: { p->nStmtDefImmCons = db->nDeferredImmCons; } - /* Gather the schema version number for checking */ + /* Gather the schema version number for checking: + ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite + ** each time a query is executed to ensure that the internal cache of the + ** schema used when compiling the SQL query matches the schema of the + ** database against which the compiled query is actually executed. + */ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); iGen = db->aDb[pOp->p1].pSchema->iGeneration; }else{ @@ -3094,7 +3142,7 @@ case OP_Transaction: { ** must be started or there must be an open cursor) before ** executing this instruction. */ -case OP_ReadCookie: { /* out2-prerelease */ +case OP_ReadCookie: { /* out2 */ int iMeta; int iDb; int iCookie; @@ -3108,6 +3156,7 @@ case OP_ReadCookie: { /* out2-prerelease */ assert( DbMaskTest(p->btreeMask, iDb) ); sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta); + pOut = out2Prerelease(p, pOp); pOut->u.i = iMeta; break; } @@ -3218,20 +3267,6 @@ case OP_SetCookie: { /* in3 */ ** See also OpenRead. */ case OP_ReopenIdx: { - VdbeCursor *pCur; - - assert( pOp->p5==0 ); - assert( pOp->p4type==P4_KEYINFO ); - pCur = p->apCsr[pOp->p1]; - if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ - assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ - break; - } - /* If the cursor is not currently open or is open on a different - ** index, then fall through into OP_OpenRead to force a reopen */ -} -case OP_OpenRead: -case OP_OpenWrite: { int nField; KeyInfo *pKeyInfo; int p2; @@ -3241,8 +3276,20 @@ case OP_OpenWrite: { VdbeCursor *pCur; Db *pDb; - assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); - assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); + assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); + assert( pOp->p4type==P4_KEYINFO ); + pCur = p->apCsr[pOp->p1]; + if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ + assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ + goto open_cursor_set_hints; + } + /* If the cursor is not currently open or is open on a different + ** index, then fall through into OP_OpenRead to force a reopen */ +case OP_OpenRead: +case OP_OpenWrite: + + assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 ); + assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ ); assert( p->bIsReader ); assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx || p->readOnly==0 ); @@ -3305,14 +3352,17 @@ case OP_OpenWrite: { pCur->pgnoRoot = p2; rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); pCur->pKeyInfo = pKeyInfo; - assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); - sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR)); - /* Set the VdbeCursor.isTable variable. Previous versions of ** SQLite used to check if the root-page flags were sane at this point ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; + +open_cursor_set_hints: + assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); + assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ ); + sqlite3BtreeCursorHints(pCur->pCursor, + (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ))); break; } @@ -3428,7 +3478,7 @@ case OP_SequenceTest: { pC = p->apCsr[pOp->p1]; assert( pC->pSorter ); if( (pC->seqCount++)==0 ){ - pc = pOp->p2 - 1; + goto jump_to_p2; } break; } @@ -3573,6 +3623,22 @@ case OP_SeekGT: { /* jump, in3 */ #ifdef SQLITE_DEBUG pC->seekOp = pOp->opcode; #endif + + /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and + ** OP_SeekLE opcodes are allowed, and these must be immediately followed + ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key. + */ +#ifdef SQLITE_DEBUG + if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){ + assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE ); + assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT ); + assert( pOp[1].p1==pOp[0].p1 ); + assert( pOp[1].p2==pOp[0].p2 ); + assert( pOp[1].p3==pOp[0].p3 ); + assert( pOp[1].p4.i==pOp[0].p4.i ); + } +#endif + if( pC->isTable ){ /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do @@ -3589,7 +3655,7 @@ case OP_SeekGT: { /* jump, in3 */ if( (pIn3->flags & MEM_Real)==0 ){ /* If the P3 value cannot be converted into any kind of a number, ** then the seek is not possible, so jump to P2 */ - pc = pOp->p2 - 1; VdbeBranchTaken(1,2); + VdbeBranchTaken(1,2); goto jump_to_p2; break; } @@ -3680,7 +3746,7 @@ case OP_SeekGT: { /* jump, in3 */ assert( pOp->p2>0 ); VdbeBranchTaken(res!=0,2); if( res ){ - pc = pOp->p2 - 1; + goto jump_to_p2; } break; } @@ -3774,6 +3840,7 @@ case OP_NoConflict: /* jump, in3 */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int alreadyExists; + int takeJump; int ii; VdbeCursor *pC; int res; @@ -3796,7 +3863,7 @@ case OP_Found: { /* jump, in3 */ pIn3 = &aMem[pOp->p3]; assert( pC->pCursor!=0 ); assert( pC->isTable==0 ); - pFree = 0; /* Not needed. Only used to suppress a compiler warning. */ + pFree = 0; if( pOp->p4.i>0 ){ r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; @@ -3819,21 +3886,20 @@ case OP_Found: { /* jump, in3 */ sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); } pIdxKey->default_rc = 0; + takeJump = 0; if( pOp->opcode==OP_NoConflict ){ /* For the OP_NoConflict opcode, take the jump if any of the ** input fields are NULL, since any key with a NULL will not ** conflict */ for(ii=0; iinField; ii++){ if( pIdxKey->aMem[ii].flags & MEM_Null ){ - pc = pOp->p2 - 1; VdbeBranchTaken(1,2); + takeJump = 1; break; } } } rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res); - if( pOp->p4.i==0 ){ - sqlite3DbFree(db, pFree); - } + sqlite3DbFree(db, pFree); if( rc!=SQLITE_OK ){ break; } @@ -3844,10 +3910,10 @@ case OP_Found: { /* jump, in3 */ pC->cacheStatus = CACHE_STALE; if( pOp->opcode==OP_Found ){ VdbeBranchTaken(alreadyExists!=0,2); - if( alreadyExists ) pc = pOp->p2 - 1; + if( alreadyExists ) goto jump_to_p2; }else{ - VdbeBranchTaken(alreadyExists==0,2); - if( !alreadyExists ) pc = pOp->p2 - 1; + VdbeBranchTaken(takeJump||alreadyExists==0,2); + if( takeJump || !alreadyExists ) goto jump_to_p2; } break; } @@ -3896,10 +3962,8 @@ case OP_NotExists: { /* jump, in3 */ pC->cacheStatus = CACHE_STALE; pC->deferredMoveto = 0; VdbeBranchTaken(res!=0,2); - if( res!=0 ){ - pc = pOp->p2 - 1; - } pC->seekResult = res; + if( res!=0 ) goto jump_to_p2; break; } @@ -3911,9 +3975,10 @@ case OP_NotExists: { /* jump, in3 */ ** The sequence number on the cursor is incremented after this ** instruction. */ -case OP_Sequence: { /* out2-prerelease */ +case OP_Sequence: { /* out2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( p->apCsr[pOp->p1]!=0 ); + pOut = out2Prerelease(p, pOp); pOut->u.i = p->apCsr[pOp->p1]->seqCount++; break; } @@ -3934,7 +3999,7 @@ case OP_Sequence: { /* out2-prerelease */ ** generated record number. This P3 mechanism is used to help implement the ** AUTOINCREMENT feature. */ -case OP_NewRowid: { /* out2-prerelease */ +case OP_NewRowid: { /* out2 */ i64 v; /* The new rowid */ VdbeCursor *pC; /* Cursor of table to get the new rowid */ int res; /* Result of an sqlite3BtreeLast() */ @@ -3944,6 +4009,7 @@ case OP_NewRowid: { /* out2-prerelease */ v = 0; res = 0; + pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -4257,9 +4323,7 @@ case OP_SorterCompare: { res = 0; rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res); VdbeBranchTaken(res!=0,2); - if( res ){ - pc = pOp->p2-1; - } + if( res ) goto jump_to_p2; break; }; @@ -4388,12 +4452,13 @@ case OP_RowData: { ** be a separate OP_VRowid opcode for use with virtual tables, but this ** one opcode now works for both table types. */ -case OP_Rowid: { /* out2-prerelease */ +case OP_Rowid: { /* out2 */ VdbeCursor *pC; i64 v; sqlite3_vtab *pVtab; const sqlite3_module *pModule; + pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -4446,7 +4511,7 @@ case OP_NullRow: { break; } -/* Opcode: Last P1 P2 * * * +/* Opcode: Last P1 P2 P3 * * ** ** The next use of the Rowid or Column or Prev instruction for P1 ** will refer to the last entry in the database table or index. @@ -4473,12 +4538,13 @@ case OP_Last: { /* jump */ pC->nullRow = (u8)res; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; + pC->seekResult = pOp->p3; #ifdef SQLITE_DEBUG pC->seekOp = OP_Last; #endif if( pOp->p2>0 ){ VdbeBranchTaken(res!=0,2); - if( res ) pc = pOp->p2 - 1; + if( res ) goto jump_to_p2; } break; } @@ -4542,9 +4608,7 @@ case OP_Rewind: { /* jump */ pC->nullRow = (u8)res; assert( pOp->p2>0 && pOp->p2nOp ); VdbeBranchTaken(res!=0,2); - if( res ){ - pc = pOp->p2 - 1; - } + if( res ) goto jump_to_p2; break; } @@ -4655,11 +4719,11 @@ next_tail: VdbeBranchTaken(res==0,2); if( res==0 ){ pC->nullRow = 0; - pc = pOp->p2 - 1; p->aCounter[pOp->p5]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif + goto jump_to_p2_and_check_for_interrupt; }else{ pC->nullRow = 1; } @@ -4767,11 +4831,12 @@ case OP_IdxDelete: { ** ** See also: Rowid, MakeRecord. */ -case OP_IdxRowid: { /* out2-prerelease */ +case OP_IdxRowid: { /* out2 */ BtCursor *pCrsr; VdbeCursor *pC; i64 rowid; + pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); @@ -4884,9 +4949,7 @@ case OP_IdxGE: { /* jump */ res++; } VdbeBranchTaken(res>0,2); - if( res>0 ){ - pc = pOp->p2 - 1 ; - } + if( res>0 ) goto jump_to_p2; break; } @@ -4910,32 +4973,18 @@ case OP_IdxGE: { /* jump */ ** ** See also: Clear */ -case OP_Destroy: { /* out2-prerelease */ +case OP_Destroy: { /* out2 */ int iMoved; - int iCnt; - Vdbe *pVdbe; int iDb; assert( p->readOnly==0 ); -#ifndef SQLITE_OMIT_VIRTUALTABLE - iCnt = 0; - for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ - if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader - && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 - ){ - iCnt++; - } - } -#else - iCnt = db->nVdbeRead; -#endif + pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Null; - if( iCnt>1 ){ + if( db->nVdbeRead > db->nVDestroy+1 ){ rc = SQLITE_LOCKED; p->errorAction = OE_Abort; }else{ iDb = pOp->p3; - assert( iCnt==1 ); assert( DbMaskTest(p->btreeMask, iDb) ); iMoved = 0; /* Not needed. Only to silence a warning. */ rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved); @@ -5038,12 +5087,13 @@ case OP_ResetSorter: { ** ** See documentation on OP_CreateTable for additional information. */ -case OP_CreateIndex: /* out2-prerelease */ -case OP_CreateTable: { /* out2-prerelease */ +case OP_CreateIndex: /* out2 */ +case OP_CreateTable: { /* out2 */ int pgno; int flags; Db *pDb; + pOut = out2Prerelease(p, pOp); pgno = 0; assert( pOp->p1>=0 && pOp->p1nDb ); assert( DbMaskTest(p->btreeMask, pOp->p1) ); @@ -5269,12 +5319,12 @@ case OP_RowSetRead: { /* jump, in1, out3 */ ){ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); - pc = pOp->p2 - 1; VdbeBranchTaken(1,2); + goto jump_to_p2_and_check_for_interrupt; }else{ /* A value was pulled from the index */ - sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); VdbeBranchTaken(0,2); + sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); } goto check_for_interrupt; } @@ -5325,10 +5375,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */ if( iSet ){ exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i); VdbeBranchTaken(exists!=0,2); - if( exists ){ - pc = pOp->p2 - 1; - break; - } + if( exists ) goto jump_to_p2; } if( iSet>=0 ){ sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i); @@ -5417,7 +5464,7 @@ case OP_Program: { /* jump */ pFrame->v = p; pFrame->nChildMem = nMem; pFrame->nChildCsr = pProgram->nCsr; - pFrame->pc = pc; + pFrame->pc = (int)(pOp - aOp); pFrame->aMem = p->aMem; pFrame->nMem = p->nMem; pFrame->apCsr = p->apCsr; @@ -5440,7 +5487,7 @@ case OP_Program: { /* jump */ pFrame = pRt->u.pFrame; assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem ); assert( pProgram->nCsr==pFrame->nChildCsr ); - assert( pc==pFrame->pc ); + assert( (int)(pOp - aOp)==pFrame->pc ); } p->nFrame++; @@ -5461,7 +5508,7 @@ case OP_Program: { /* jump */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS p->anExec = 0; #endif - pc = -1; + pOp = &aOp[-1]; memset(p->aOnceFlag, 0, p->nOnceFlag); break; @@ -5479,9 +5526,10 @@ case OP_Program: { /* jump */ ** the value of the P1 argument to the value of the P1 argument to the ** calling OP_Program instruction. */ -case OP_Param: { /* out2-prerelease */ +case OP_Param: { /* out2 */ VdbeFrame *pFrame; Mem *pIn; + pOut = out2Prerelease(p, pOp); pFrame = p->pFrame; pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1]; sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem); @@ -5525,10 +5573,10 @@ case OP_FkCounter: { case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2); - if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; }else{ VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2); - if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2; } break; } @@ -5568,18 +5616,18 @@ case OP_MemMax: { /* in2 */ /* Opcode: IfPos P1 P2 * * * ** Synopsis: if r[P1]>0 goto P2 ** -** If the value of register P1 is 1 or greater, jump to P2. +** Register P1 must contain an integer. +** If the value of register P1 is 1 or greater, jump to P2 and +** add the literal value P3 to register P1. ** -** It is illegal to use this instruction on a register that does -** not contain an integer. An assertion fault will result if you try. +** If the initial value of register P1 is less than 1, then the +** value is unchanged and control passes through to the next instruction. */ case OP_IfPos: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); VdbeBranchTaken( pIn1->u.i>0, 2); - if( pIn1->u.i>0 ){ - pc = pOp->p2 - 1; - } + if( pIn1->u.i>0 ) goto jump_to_p2; break; } @@ -5594,26 +5642,56 @@ case OP_IfNeg: { /* jump, in1 */ assert( pIn1->flags&MEM_Int ); pIn1->u.i += pOp->p3; VdbeBranchTaken(pIn1->u.i<0, 2); - if( pIn1->u.i<0 ){ - pc = pOp->p2 - 1; + if( pIn1->u.i<0 ) goto jump_to_p2; + break; +} + +/* Opcode: IfNotZero P1 P2 P3 * * +** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2 +** +** Register P1 must contain an integer. If the content of register P1 is +** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is +** initially zero, leave it unchanged and fall through. +*/ +case OP_IfNotZero: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken(pIn1->u.i<0, 2); + if( pIn1->u.i ){ + pIn1->u.i += pOp->p3; + goto jump_to_p2; } break; } -/* Opcode: IfZero P1 P2 P3 * * -** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2 +/* Opcode: DecrJumpZero P1 P2 * * * +** Synopsis: if (--r[P1])==0 goto P2 ** -** The register P1 must contain an integer. Add literal P3 to the -** value in register P1. If the result is exactly 0, jump to P2. +** Register P1 must hold an integer. Decrement the value in register P1 +** then jump to P2 if the new value is exactly zero. */ -case OP_IfZero: { /* jump, in1 */ +case OP_DecrJumpZero: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; assert( pIn1->flags&MEM_Int ); - pIn1->u.i += pOp->p3; + pIn1->u.i--; VdbeBranchTaken(pIn1->u.i==0, 2); - if( pIn1->u.i==0 ){ - pc = pOp->p2 - 1; - } + if( pIn1->u.i==0 ) goto jump_to_p2; + break; +} + + +/* Opcode: JumpZeroIncr P1 P2 * * * +** Synopsis: if (r[P1]++)==0 ) goto P2 +** +** The register P1 must contain an integer. If register P1 is initially +** zero, then jump to P2. Increment register P1 regardless of whether or +** not the jump is taken. +*/ +case OP_JumpZeroIncr: { /* jump, in1 */ + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags&MEM_Int ); + VdbeBranchTaken(pIn1->u.i==0, 2); + if( (pIn1->u.i++)==0 ) goto jump_to_p2; break; } @@ -5655,7 +5733,7 @@ case OP_AggStep: { ctx.pOut = &t; ctx.isError = 0; ctx.pVdbe = p; - ctx.iOp = pc; + ctx.iOp = (int)(pOp - aOp); ctx.skipFlag = 0; (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */ if( ctx.isError ){ @@ -5750,7 +5828,7 @@ case OP_Checkpoint: { ** ** Write a string containing the final journal-mode to register P2. */ -case OP_JournalMode: { /* out2-prerelease */ +case OP_JournalMode: { /* out2 */ Btree *pBt; /* Btree to change journal mode of */ Pager *pPager; /* Pager associated with pBt */ int eNew; /* New journal mode */ @@ -5759,6 +5837,7 @@ case OP_JournalMode: { /* out2-prerelease */ const char *zFilename; /* Name of database file for pPager */ #endif + pOut = out2Prerelease(p, pOp); eNew = pOp->p3; assert( eNew==PAGER_JOURNALMODE_DELETE || eNew==PAGER_JOURNALMODE_TRUNCATE @@ -5834,7 +5913,6 @@ case OP_JournalMode: { /* out2-prerelease */ } eNew = sqlite3PagerSetJournalMode(pPager, eNew); - pOut = &aMem[pOp->p2]; pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = (char *)sqlite3JournalModename(eNew); pOut->n = sqlite3Strlen30(pOut->z); @@ -5875,8 +5953,8 @@ case OP_IncrVacuum: { /* jump */ rc = sqlite3BtreeIncrVacuum(pBt); VdbeBranchTaken(rc==SQLITE_DONE,2); if( rc==SQLITE_DONE ){ - pc = pOp->p2 - 1; rc = SQLITE_OK; + goto jump_to_p2; } break; } @@ -5954,13 +6032,29 @@ case OP_VBegin: { #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE -/* Opcode: VCreate P1 * * P4 * +/* Opcode: VCreate P1 P2 * * * ** -** P4 is the name of a virtual table in database P1. Call the xCreate method -** for that table. +** P2 is a register that holds the name of a virtual table in database +** P1. Call the xCreate method for that table. */ case OP_VCreate: { - rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg); + Mem sMem; /* For storing the record being decoded */ + const char *zTab; /* Name of the virtual table */ + + memset(&sMem, 0, sizeof(sMem)); + sMem.db = db; + /* Because P2 is always a static string, it is impossible for the + ** sqlite3VdbeMemCopy() to fail */ + assert( (aMem[pOp->p2].flags & MEM_Str)!=0 ); + assert( (aMem[pOp->p2].flags & MEM_Static)!=0 ); + rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]); + assert( rc==SQLITE_OK ); + zTab = (const char*)sqlite3_value_text(&sMem); + assert( zTab || db->mallocFailed ); + if( zTab ){ + rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg); + } + sqlite3VdbeMemRelease(&sMem); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -5972,9 +6066,9 @@ case OP_VCreate: { ** of that table. */ case OP_VDestroy: { - p->inVtabMethod = 2; + db->nVDestroy++; rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z); - p->inVtabMethod = 0; + db->nVDestroy--; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -5990,14 +6084,17 @@ case OP_VOpen: { VdbeCursor *pCur; sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; - sqlite3_module *pModule; + const sqlite3_module *pModule; assert( p->bIsReader ); pCur = 0; pVtabCursor = 0; pVtab = pOp->p4.pVtab->pVtab; - pModule = (sqlite3_module *)pVtab->pModule; - assert(pVtab && pModule); + if( pVtab==0 || NEVER(pVtab->pModule==0) ){ + rc = SQLITE_LOCKED; + break; + } + pModule = pVtab->pModule; rc = pModule->xOpen(pVtab, &pVtabCursor); sqlite3VtabImportErrmsg(p, pVtab); if( SQLITE_OK==rc ){ @@ -6008,9 +6105,11 @@ case OP_VOpen: { pCur = allocateCursor(p, pOp->p1, 0, -1, 0); if( pCur ){ pCur->pVtabCursor = pVtabCursor; + pVtab->nRef++; }else{ - db->mallocFailed = 1; + assert( db->mallocFailed ); pModule->xClose(pVtabCursor); + goto no_mem; } } break; @@ -6066,27 +6165,19 @@ case OP_VFilter: { /* jump */ iQuery = (int)pQuery->u.i; /* Invoke the xFilter method */ - { - res = 0; - apArg = p->apArg; - for(i = 0; iinVtabMethod = 1; - rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); - p->inVtabMethod = 0; - sqlite3VtabImportErrmsg(p, pVtab); - if( rc==SQLITE_OK ){ - res = pModule->xEof(pVtabCursor); - } - VdbeBranchTaken(res!=0,2); - if( res ){ - pc = pOp->p2 - 1; - } + res = 0; + apArg = p->apArg; + for(i = 0; ixFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg); + sqlite3VtabImportErrmsg(p, pVtab); + if( rc==SQLITE_OK ){ + res = pModule->xEof(pVtabCursor); } pCur->nullRow = 0; - + VdbeBranchTaken(res!=0,2); + if( res ) goto jump_to_p2; break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -6165,9 +6256,7 @@ case OP_VNext: { /* jump */ ** data is available) and the error code returned when xColumn or ** some other method is next invoked on the save virtual table cursor. */ - p->inVtabMethod = 1; rc = pModule->xNext(pCur->pVtabCursor); - p->inVtabMethod = 0; sqlite3VtabImportErrmsg(p, pVtab); if( rc==SQLITE_OK ){ res = pModule->xEof(pCur->pVtabCursor); @@ -6175,7 +6264,7 @@ case OP_VNext: { /* jump */ VdbeBranchTaken(!res,2); if( !res ){ /* If there is data, jump to P2 */ - pc = pOp->p2 - 1; + goto jump_to_p2_and_check_for_interrupt; } goto check_for_interrupt; } @@ -6242,7 +6331,7 @@ case OP_VRename: { */ case OP_VUpdate: { sqlite3_vtab *pVtab; - sqlite3_module *pModule; + const sqlite3_module *pModule; int nArg; int i; sqlite_int64 rowid; @@ -6254,7 +6343,11 @@ case OP_VUpdate: { ); assert( p->readOnly==0 ); pVtab = pOp->p4.pVtab->pVtab; - pModule = (sqlite3_module *)pVtab->pModule; + if( pVtab==0 || NEVER(pVtab->pModule==0) ){ + rc = SQLITE_LOCKED; + break; + } + pModule = pVtab->pModule; nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); if( ALWAYS(pModule->xUpdate) ){ @@ -6294,7 +6387,8 @@ case OP_VUpdate: { ** ** Write the current number of pages in database P1 to memory cell P2. */ -case OP_Pagecount: { /* out2-prerelease */ +case OP_Pagecount: { /* out2 */ + pOut = out2Prerelease(p, pOp); pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt); break; } @@ -6310,10 +6404,11 @@ case OP_Pagecount: { /* out2-prerelease */ ** ** Store the maximum page count after the change in register P2. */ -case OP_MaxPgcnt: { /* out2-prerelease */ +case OP_MaxPgcnt: { /* out2 */ unsigned int newMax; Btree *pBt; + pOut = out2Prerelease(p, pOp); pBt = db->aDb[pOp->p1].pBt; newMax = 0; if( pOp->p3 ){ @@ -6342,9 +6437,6 @@ case OP_Init: { /* jump */ char *zTrace; char *z; - if( pOp->p2 ){ - pc = pOp->p2 - 1; - } #ifndef SQLITE_OMIT_TRACE if( db->xTrace && !p->doingRerun @@ -6372,6 +6464,7 @@ case OP_Init: { /* jump */ } #endif /* SQLITE_DEBUG */ #endif /* SQLITE_OMIT_TRACE */ + if( pOp->p2 ) goto jump_to_p2; break; } @@ -6403,8 +6496,8 @@ default: { /* This is really OP_Noop and OP_Explain */ #ifdef VDBE_PROFILE { u64 endTime = sqlite3Hwtime(); - if( endTime>start ) pOp->cycles += endTime - start; - pOp->cnt++; + if( endTime>start ) pOrigOp->cycles += endTime - start; + pOrigOp->cnt++; } #endif @@ -6414,16 +6507,16 @@ default: { /* This is really OP_Noop and OP_Explain */ ** the evaluator loop. So we can leave it out when NDEBUG is defined. */ #ifndef NDEBUG - assert( pc>=-1 && pcnOp ); + assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] ); #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ if( rc!=0 ) printf("rc=%d\n",rc); - if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){ - registerTrace(pOp->p2, &aMem[pOp->p2]); + if( pOrigOp->opflags & (OPFLG_OUT2) ){ + registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]); } - if( pOp->opflags & OPFLG_OUT3 ){ - registerTrace(pOp->p3, &aMem[pOp->p3]); + if( pOrigOp->opflags & OPFLG_OUT3 ){ + registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]); } } #endif /* SQLITE_DEBUG */ @@ -6438,7 +6531,7 @@ vdbe_error_halt: p->rc = rc; testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3_log(rc, "statement aborts at %d: [%s] %s", - pc, p->zSql, p->zErrMsg); + (int)(pOp - aOp), p->zSql, p->zErrMsg); sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; diff --git a/src/vdbe.h b/src/vdbe.h index b715241..bb597b6 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -213,6 +213,7 @@ int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 1a7297e..d3955af 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -313,14 +313,6 @@ struct ScanStatus { ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() ** is really a pointer to an instance of this structure. -** -** The Vdbe.inVtabMethod variable is set to non-zero for the duration of -** any virtual table method invocations made by the vdbe program. It is -** set to 2 for xDestroy method calls and 1 for all other methods. This -** variable is used for two purposes: to allow xDestroy methods to execute -** "DROP TABLE" statements and to prevent some nasty side effects of -** malloc failure when SQLite is invoked recursively by a virtual table -** method function. */ struct Vdbe { sqlite3 *db; /* The database connection that owns this statement */ @@ -344,11 +336,13 @@ struct Vdbe { u32 cacheCtr; /* VdbeCursor row cache generation counter */ int pc; /* The program counter */ int rc; /* Value to return */ +#ifdef SQLITE_DEBUG + int rcApp; /* errcode set by sqlite3_result_error_code() */ +#endif u16 nResColumn; /* Number of columns in one row of the result set */ u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ bft explain:2; /* True if EXPLAIN present on SQL command */ - bft inVtabMethod:2; /* See comments above */ bft changeCntOn:1; /* True to update the change-counter */ bft expired:1; /* True if the VM needs to be recompiled */ bft runOnlyOnce:1; /* Automatically expire on reset */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 21c537d..e03640d 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -170,6 +170,10 @@ const void *sqlite3_value_text16le(sqlite3_value *pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16LE); } #endif /* SQLITE_OMIT_UTF16 */ +/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five +** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating +** point number string BLOB NULL +*/ int sqlite3_value_type(sqlite3_value* pVal){ static const u8 aType[] = { SQLITE_BLOB, /* 0x00 */ @@ -365,6 +369,9 @@ void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode; pCtx->fErrorOrAux = 1; +#ifdef SQLITE_DEBUG + if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; +#endif if( pCtx->pOut->flags & MEM_Null ){ sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1, SQLITE_UTF8, SQLITE_STATIC); @@ -445,7 +452,7 @@ static int sqlite3Step(Vdbe *p){ ** or SQLITE_BUSY error. */ #ifdef SQLITE_OMIT_AUTORESET - if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){ + if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){ sqlite3_reset((sqlite3_stmt*)p); }else{ return SQLITE_MISUSE_BKPT; @@ -491,6 +498,9 @@ static int sqlite3Step(Vdbe *p){ if( p->bIsReader ) db->nVdbeRead++; p->pc = 0; } +#ifdef SQLITE_DEBUG + p->rcApp = SQLITE_OK; +#endif #ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); @@ -535,7 +545,7 @@ end_of_step: assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR || rc==SQLITE_BUSY || rc==SQLITE_MISUSE ); - assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE ); + assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp ); if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ /* If this statement was prepared using sqlite3_prepare_v2(), and an ** error has occurred, then return the error code in p->rc to the @@ -623,16 +633,26 @@ sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ } /* -** Return the current time for a statement +** Return the current time for a statement. If the current time +** is requested more than once within the same run of a single prepared +** statement, the exact same time is returned for each invocation regardless +** of the amount of time that elapses between invocations. In other words, +** the time returned is always the time of the first call. */ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){ - Vdbe *v = p->pVdbe; int rc; - if( v->iCurrentTime==0 ){ - rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, &v->iCurrentTime); - if( rc ) v->iCurrentTime = 0; +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 + sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime; + assert( p->pVdbe!=0 ); +#else + sqlite3_int64 iTime = 0; + sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime; +#endif + if( *piTime==0 ){ + rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime); + if( rc ) *piTime = 0; } - return v->iCurrentTime; + return *piTime; } /* @@ -702,6 +722,11 @@ void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ AuxData *pAuxData; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); +#if SQLITE_ENABLE_STAT3_OR_STAT4 + if( pCtx->pVdbe==0 ) return 0; +#else + assert( pCtx->pVdbe!=0 ); +#endif for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break; } @@ -725,6 +750,11 @@ void sqlite3_set_auxdata( assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); if( iArg<0 ) goto failed; +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + if( pVdbe==0 ) goto failed; +#else + assert( pVdbe!=0 ); +#endif for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e07aacb..2c32038 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1118,7 +1118,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ #ifndef SQLITE_OMIT_VIRTUALTABLE case P4_VTAB: { sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab; - sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule); + sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab); break; } #endif @@ -1782,13 +1782,29 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ else if( pCx->pVtabCursor ){ sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; const sqlite3_module *pModule = pVtabCursor->pVtab->pModule; - p->inVtabMethod = 1; + assert( pVtabCursor->pVtab->nRef>0 ); + pVtabCursor->pVtab->nRef--; pModule->xClose(pVtabCursor); - p->inVtabMethod = 0; } #endif } +/* +** Close all cursors in the current frame. +*/ +static void closeCursorsInFrame(Vdbe *p){ + if( p->apCsr ){ + int i; + for(i=0; inCursor; i++){ + VdbeCursor *pC = p->apCsr[i]; + if( pC ){ + sqlite3VdbeFreeCursor(p, pC); + p->apCsr[i] = 0; + } + } + } +} + /* ** Copy the values stored in the VdbeFrame structure to its Vdbe. This ** is used, for example, when a trigger sub-program is halted to restore @@ -1796,6 +1812,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ */ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){ Vdbe *v = pFrame->v; + closeCursorsInFrame(v); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS v->anExec = pFrame->anExec; #endif @@ -1830,17 +1847,7 @@ static void closeAllCursors(Vdbe *p){ p->nFrame = 0; } assert( p->nFrame==0 ); - - if( p->apCsr ){ - int i; - for(i=0; inCursor; i++){ - VdbeCursor *pC = p->apCsr[i]; - if( pC ){ - sqlite3VdbeFreeCursor(p, pC); - p->apCsr[i] = 0; - } - } - } + closeCursorsInFrame(p); if( p->aMem ){ releaseMemArray(&p->aMem[1], p->nMem); } @@ -2143,7 +2150,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){ ** doing this the directory is synced again before any individual ** transaction files are deleted. */ - rc = sqlite3OsDelete(pVfs, zMaster, 1); + rc = sqlite3OsDelete(pVfs, zMaster, needSync); sqlite3DbFree(db, zMaster); zMaster = 0; if( rc ){ @@ -3373,7 +3380,8 @@ static void vdbeAssertFieldCountWithinLimits( if( CORRUPT_DB ) return; idx = getVarint32(aKey, szHdr); - assert( szHdr<=nKey ); + assert( nKey>=0 ); + assert( szHdr<=(u32)nKey ); while( idxerrCode is set to SQLITE_NOMEM and, if it is not NULL, the ** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db). */ -static int vdbeRecordCompareWithSkip( +int sqlite3VdbeRecordCompareWithSkip( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2, /* Right key */ int bSkip /* If true, skip the first field */ @@ -3770,7 +3778,7 @@ int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ - return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0); } @@ -3858,7 +3866,7 @@ static int vdbeRecordCompareInt( }else if( pPKey2->nField>1 ){ /* The first fields of the two keys are equal. Compare the trailing ** fields. */ - res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ /* The first fields of the two keys are equal and there are no trailing ** fields. Return pPKey2->default_rc in this case. */ @@ -3906,7 +3914,7 @@ static int vdbeRecordCompareString( res = nStr - pPKey2->aMem[0].n; if( res==0 ){ if( pPKey2->nField>1 ){ - res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); + res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); }else{ res = pPKey2->default_rc; } diff --git a/src/vdbeblob.c b/src/vdbeblob.c index cf1eb59..ea01f5c 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -154,12 +154,17 @@ int sqlite3_blob_open( Incrblob *pBlob = 0; #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) || ppBlob==0 || zTable==0 ){ + if( ppBlob==0 ){ + return SQLITE_MISUSE_BKPT; + } +#endif + *ppBlob = 0; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif flags = !!flags; /* flags = (flags ? 1 : 0); */ - *ppBlob = 0; sqlite3_mutex_enter(db->mutex); @@ -373,7 +378,7 @@ static int blobReadWrite( sqlite3_mutex_enter(db->mutex); v = (Vdbe*)p->pStmt; - if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){ + if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){ /* Request is out of range. Return a transient error. */ rc = SQLITE_ERROR; }else if( v==0 ){ diff --git a/src/vdbemem.c b/src/vdbemem.c index 870fb5b..2fd6a71 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -200,10 +200,11 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){ pMem->z[pMem->n] = 0; pMem->z[pMem->n+1] = 0; pMem->flags |= MEM_Term; -#ifdef SQLITE_DEBUG - pMem->pScopyFrom = 0; -#endif } + pMem->flags &= ~MEM_Ephem; +#ifdef SQLITE_DEBUG + pMem->pScopyFrom = 0; +#endif return SQLITE_OK; } @@ -1090,7 +1091,7 @@ struct ValueNewStat4Ctx { ** Otherwise, if the second argument is non-zero, then this function is ** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not ** already been allocated, allocate the UnpackedRecord structure that -** that function will return to its caller here. Then return a pointer +** that function will return to its caller here. Then return a pointer to ** an sqlite3_value within the UnpackedRecord.a[] array. */ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ @@ -1134,6 +1135,113 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){ return sqlite3ValueNew(db); } +/* +** The expression object indicated by the second argument is guaranteed +** to be a scalar SQL function. If +** +** * all function arguments are SQL literals, +** * the SQLITE_FUNC_CONSTANT function flag is set, and +** * the SQLITE_FUNC_NEEDCOLL function flag is not set, +** +** then this routine attempts to invoke the SQL function. Assuming no +** error occurs, output parameter (*ppVal) is set to point to a value +** object containing the result before returning SQLITE_OK. +** +** Affinity aff is applied to the result of the function before returning. +** If the result is a text value, the sqlite3_value object uses encoding +** enc. +** +** If the conditions above are not met, this function returns SQLITE_OK +** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to +** NULL and an SQLite error code returned. +*/ +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 +static int valueFromFunction( + sqlite3 *db, /* The database connection */ + Expr *p, /* The expression to evaluate */ + u8 enc, /* Encoding to use */ + u8 aff, /* Affinity to use */ + sqlite3_value **ppVal, /* Write the new value here */ + struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */ +){ + sqlite3_context ctx; /* Context object for function invocation */ + sqlite3_value **apVal = 0; /* Function arguments */ + int nVal = 0; /* Size of apVal[] array */ + FuncDef *pFunc = 0; /* Function definition */ + sqlite3_value *pVal = 0; /* New value */ + int rc = SQLITE_OK; /* Return code */ + int nName; /* Size of function name in bytes */ + ExprList *pList = 0; /* Function arguments */ + int i; /* Iterator variable */ + + assert( pCtx!=0 ); + assert( (p->flags & EP_TokenOnly)==0 ); + pList = p->x.pList; + if( pList ) nVal = pList->nExpr; + nName = sqlite3Strlen30(p->u.zToken); + pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0); + assert( pFunc ); + if( (pFunc->funcFlags & SQLITE_FUNC_CONSTANT)==0 + || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) + ){ + return SQLITE_OK; + } + + if( pList ){ + apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal); + if( apVal==0 ){ + rc = SQLITE_NOMEM; + goto value_from_function_out; + } + for(i=0; ia[i].pExpr, enc, aff, &apVal[i]); + if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out; + } + } + + pVal = valueNew(db, pCtx); + if( pVal==0 ){ + rc = SQLITE_NOMEM; + goto value_from_function_out; + } + + assert( pCtx->pParse->rc==SQLITE_OK ); + memset(&ctx, 0, sizeof(ctx)); + ctx.pOut = pVal; + ctx.pFunc = pFunc; + pFunc->xFunc(&ctx, nVal, apVal); + if( ctx.isError ){ + rc = ctx.isError; + sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal)); + }else{ + sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); + assert( rc==SQLITE_OK ); + rc = sqlite3VdbeChangeEncoding(pVal, enc); + if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){ + rc = SQLITE_TOOBIG; + pCtx->pParse->nErr++; + } + } + pCtx->pParse->rc = rc; + + value_from_function_out: + if( rc!=SQLITE_OK ){ + pVal = 0; + } + if( apVal ){ + for(i=0; iop)==TK_UPLUS ) pExpr = pExpr->pLeft; if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; + /* Compressed expressions only appear when parsing the DEFAULT clause + ** on a table column definition, and hence only when pCtx==0. This + ** check ensures that an EP_TokenOnly expression is never passed down + ** into valueFromFunction(). */ + assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 ); + if( op==TK_CAST ){ u8 aff = sqlite3AffinityType(pExpr->u.zToken,0); rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); @@ -1242,6 +1356,12 @@ static int valueFromExpr( } #endif +#ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + else if( op==TK_FUNCTION && pCtx!=0 ){ + rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx); + } +#endif + *ppVal = pVal; return rc; @@ -1528,7 +1648,7 @@ void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){ Mem *aMem = pRec->aMem; sqlite3 *db = aMem[0].db; for(i=0; ipKeyInfo); sqlite3DbFree(db, pRec); diff --git a/src/vdbesort.c b/src/vdbesort.c index 5a43a10..afc4d6a 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -291,6 +291,7 @@ struct MergeEngine { ** after the thread has finished are not dire. So we don't worry about ** memory barriers and such here. */ +typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int); struct SortSubtask { SQLiteThread *pThread; /* Background thread, if any */ int bDone; /* Set if thread is finished but not joined */ @@ -298,10 +299,12 @@ struct SortSubtask { UnpackedRecord *pUnpacked; /* Space to unpack a record */ SorterList list; /* List for thread to write to a PMA */ int nPMA; /* Number of PMAs currently in file */ + SorterCompare xCompare; /* Compare function to use */ SorterFile file; /* Temp file for level-0 PMAs */ SorterFile file2; /* Space for other PMAs */ }; + /* ** Main sorter structure. A single instance of this is allocated for each ** sorter cursor created by the VDBE. @@ -328,9 +331,13 @@ struct VdbeSorter { u8 bUseThreads; /* True to use background threads */ u8 iPrev; /* Previous thread used to flush PMA */ u8 nTask; /* Size of aTask[] array */ + u8 typeMask; SortSubtask aTask[1]; /* One or more subtasks */ }; +#define SORTER_TYPE_INTEGER 0x01 +#define SORTER_TYPE_TEXT 0x02 + /* ** An instance of the following object is used to read records out of a ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. @@ -742,32 +749,162 @@ static int vdbePmaReaderInit( return rc; } +/* +** A version of vdbeSorterCompare() that assumes that it has already been +** determined that the first field of key1 is equal to the first field of +** key2. +*/ +static int vdbeSorterCompareTail( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + UnpackedRecord *r2 = pTask->pUnpacked; + if( *pbKey2Cached==0 ){ + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; + } + return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1); +} /* ** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2, ** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences ** used by the comparison. Return the result of the comparison. ** -** Before returning, object (pTask->pUnpacked) is populated with the -** unpacked version of key2. Or, if pKey2 is passed a NULL pointer, then it -** is assumed that the (pTask->pUnpacked) structure already contains the -** unpacked key to use as key2. +** If IN/OUT parameter *pbKey2Cached is true when this function is called, +** it is assumed that (pTask->pUnpacked) contains the unpacked version +** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked +** version of key2 and *pbKey2Cached set to true before returning. ** ** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set ** to SQLITE_NOMEM. */ static int vdbeSorterCompare( SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ const void *pKey1, int nKey1, /* Left side of comparison */ const void *pKey2, int nKey2 /* Right side of comparison */ ){ UnpackedRecord *r2 = pTask->pUnpacked; - if( pKey2 ){ + if( !*pbKey2Cached ){ sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); + *pbKey2Cached = 1; } return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); } +/* +** A specially optimized version of vdbeSorterCompare() that assumes that +** the first field of each key is a TEXT value and that the collation +** sequence to compare them with is BINARY. +*/ +static int vdbeSorterCompareText( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + const u8 * const p1 = (const u8 * const)pKey1; + const u8 * const p2 = (const u8 * const)pKey2; + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ + + int n1; + int n2; + int res; + + getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2; + getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2; + res = memcmp(v1, v2, MIN(n1, n2)); + if( res==0 ){ + res = n1 - n2; + } + + if( res==0 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); + } + }else{ + if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + res = res * -1; + } + } + + return res; +} + +/* +** A specially optimized version of vdbeSorterCompare() that assumes that +** the first field of each key is an INTEGER value. +*/ +static int vdbeSorterCompareInt( + SortSubtask *pTask, /* Subtask context (for pKeyInfo) */ + int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */ + const void *pKey1, int nKey1, /* Left side of comparison */ + const void *pKey2, int nKey2 /* Right side of comparison */ +){ + const u8 * const p1 = (const u8 * const)pKey1; + const u8 * const p2 = (const u8 * const)pKey2; + const int s1 = p1[1]; /* Left hand serial type */ + const int s2 = p2[1]; /* Right hand serial type */ + const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */ + const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */ + int res; /* Return value */ + + assert( (s1>0 && s1<7) || s1==8 || s1==9 ); + assert( (s2>0 && s2<7) || s2==8 || s2==9 ); + + if( s1>7 && s2>7 ){ + res = s1 - s2; + }else{ + if( s1==s2 ){ + if( (*v1 ^ *v2) & 0x80 ){ + /* The two values have different signs */ + res = (*v1 & 0x80) ? -1 : +1; + }else{ + /* The two values have the same sign. Compare using memcmp(). */ + static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 }; + int i; + res = 0; + for(i=0; i7 ){ + res = +1; + }else if( s1>7 ){ + res = -1; + }else{ + res = s1 - s2; + } + assert( res!=0 ); + + if( res>0 ){ + if( *v1 & 0x80 ) res = -1; + }else{ + if( *v2 & 0x80 ) res = +1; + } + } + } + + if( res==0 ){ + if( pTask->pSorter->pKeyInfo->nField>1 ){ + res = vdbeSorterCompareTail( + pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 + ); + } + }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + res = res * -1; + } + + return res; +} + /* ** Initialize the temporary index cursor just opened as a sorter cursor. ** @@ -835,9 +972,13 @@ int sqlite3VdbeSorterInit( pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); pKeyInfo->db = 0; - if( nField && nWorker==0 ) pKeyInfo->nField = nField; + if( nField && nWorker==0 ){ + pKeyInfo->nXField += (pKeyInfo->nField - nField); + pKeyInfo->nField = nField; + } pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); pSorter->nTask = nWorker + 1; + pSorter->iPrev = nWorker-1; pSorter->bUseThreads = (pSorter->nTask>1); pSorter->db = db; for(i=0; inTask; i++){ @@ -863,6 +1004,12 @@ int sqlite3VdbeSorterInit( if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM; } } + + if( (pKeyInfo->nField+pKeyInfo->nXField)<13 + && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) + ){ + pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; + } } return rc; @@ -887,30 +1034,24 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){ */ static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){ sqlite3DbFree(db, pTask->pUnpacked); - pTask->pUnpacked = 0; #if SQLITE_MAX_WORKER_THREADS>0 /* pTask->list.aMemory can only be non-zero if it was handed memory ** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */ if( pTask->list.aMemory ){ sqlite3_free(pTask->list.aMemory); - pTask->list.aMemory = 0; }else #endif { assert( pTask->list.aMemory==0 ); vdbeSorterRecordFree(0, pTask->list.pList); } - pTask->list.pList = 0; if( pTask->file.pFd ){ sqlite3OsCloseFree(pTask->file.pFd); - pTask->file.pFd = 0; - pTask->file.iEof = 0; } if( pTask->file2.pFd ){ sqlite3OsCloseFree(pTask->file2.pFd); - pTask->file2.pFd = 0; - pTask->file2.iEof = 0; } + memset(pTask, 0, sizeof(SortSubtask)); } #ifdef SQLITE_DEBUG_SORTER_THREADS @@ -1090,6 +1231,7 @@ void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){ for(i=0; inTask; i++){ SortSubtask *pTask = &pSorter->aTask[i]; vdbeSortSubtaskCleanup(db, pTask); + pTask->pSorter = pSorter; } if( pSorter->list.aMemory==0 ){ vdbeSorterRecordFree(0, pSorter->list.pList); @@ -1151,6 +1293,7 @@ static int vdbeSorterOpenTempFile( sqlite3_file **ppFd ){ int rc; + if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS; rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd, SQLITE_OPEN_TEMP_JOURNAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | @@ -1198,28 +1341,42 @@ static void vdbeSorterMerge( ){ SorterRecord *pFinal = 0; SorterRecord **pp = &pFinal; - void *pVal2 = p2 ? SRVAL(p2) : 0; + int bCached = 0; while( p1 && p2 ){ int res; - res = vdbeSorterCompare(pTask, SRVAL(p1), p1->nVal, pVal2, p2->nVal); + res = pTask->xCompare( + pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal + ); + if( res<=0 ){ *pp = p1; pp = &p1->u.pNext; p1 = p1->u.pNext; - pVal2 = 0; }else{ *pp = p2; - pp = &p2->u.pNext; + pp = &p2->u.pNext; p2 = p2->u.pNext; - if( p2==0 ) break; - pVal2 = SRVAL(p2); + bCached = 0; } } *pp = p1 ? p1 : p2; *ppOut = pFinal; } +/* +** Return the SorterCompare function to compare values collected by the +** sorter object passed as the only argument. +*/ +static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){ + if( p->typeMask==SORTER_TYPE_INTEGER ){ + return vdbeSorterCompareInt; + }else if( p->typeMask==SORTER_TYPE_TEXT ){ + return vdbeSorterCompareText; + } + return vdbeSorterCompare; +} + /* ** Sort the linked list of records headed at pTask->pList. Return ** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if @@ -1234,12 +1391,14 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ rc = vdbeSortAllocUnpacked(pTask); if( rc!=SQLITE_OK ) return rc; + p = pList->pList; + pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter); + aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); if( !aSlot ){ return SQLITE_NOMEM; } - p = pList->pList; while( p ){ SorterRecord *pNext; if( pList->aMemory ){ @@ -1453,13 +1612,12 @@ static int vdbeMergeEngineStep( int i; /* Index of aTree[] to recalculate */ PmaReader *pReadr1; /* First PmaReader to compare */ PmaReader *pReadr2; /* Second PmaReader to compare */ - u8 *pKey2; /* To pReadr2->aKey, or 0 if record cached */ + int bCached = 0; /* Find the first two PmaReaders to compare. The one that was just ** advanced (iPrev) and the one next to it in the array. */ pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)]; pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)]; - pKey2 = pReadr2->aKey; for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){ /* Compare pReadr1 and pReadr2. Store the result in variable iRes. */ @@ -1469,8 +1627,8 @@ static int vdbeMergeEngineStep( }else if( pReadr2->pFd==0 ){ iRes = -1; }else{ - iRes = vdbeSorterCompare(pTask, - pReadr1->aKey, pReadr1->nKey, pKey2, pReadr2->nKey + iRes = pTask->xCompare(pTask, &bCached, + pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey ); } @@ -1492,9 +1650,9 @@ static int vdbeMergeEngineStep( if( iRes<0 || (iRes==0 && pReadr1aTree[i] = (int)(pReadr1 - pMerger->aReadr); pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; - pKey2 = pReadr2->aKey; + bCached = 0; }else{ - if( pReadr1->pFd ) pKey2 = 0; + if( pReadr1->pFd ) bCached = 0; pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr); pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ]; } @@ -1601,6 +1759,16 @@ int sqlite3VdbeSorterWrite( int bFlush; /* True to flush contents of memory to PMA */ int nReq; /* Bytes of memory required */ int nPMA; /* Bytes of PMA space required */ + int t; /* serial type of first record field */ + + getVarint32((const u8*)&pVal->z[1], t); + if( t>0 && t<10 && t!=7 ){ + pSorter->typeMask &= SORTER_TYPE_INTEGER; + }else if( t>10 && (t & 0x01) ){ + pSorter->typeMask &= SORTER_TYPE_TEXT; + }else{ + pSorter->typeMask = 0; + } assert( pSorter ); @@ -1866,10 +2034,12 @@ static void vdbeMergeEngineCompare( }else if( p2->pFd==0 ){ iRes = i1; }else{ + SortSubtask *pTask = pMerger->pTask; + int bCached = 0; int res; - assert( pMerger->pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ - res = vdbeSorterCompare( - pMerger->pTask, p1->aKey, p1->nKey, p2->aKey, p2->nKey + assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */ + res = pTask->xCompare( + pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey ); if( res<=0 ){ iRes = i1; @@ -1893,11 +2063,12 @@ static void vdbeMergeEngineCompare( #define INCRINIT_TASK 1 #define INCRINIT_ROOT 2 -/* Forward reference. -** The vdbeIncrMergeInit() and vdbePmaReaderIncrMergeInit() routines call each -** other (when building a merge tree). +/* +** Forward reference required as the vdbeIncrMergeInit() and +** vdbePmaReaderIncrInit() routines are called mutually recursively when +** building a merge tree. */ -static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode); +static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode); /* ** Initialize the MergeEngine object passed as the second argument. Once this @@ -1944,7 +2115,7 @@ static int vdbeMergeEngineInit( ** better advantage of multi-processor hardware. */ rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]); }else{ - rc = vdbePmaReaderIncrMergeInit(&pMerger->aReadr[i], INCRINIT_NORMAL); + rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL); } if( rc!=SQLITE_OK ) return rc; } @@ -1956,17 +2127,15 @@ static int vdbeMergeEngineInit( } /* -** Initialize the IncrMerge field of a PmaReader. -** -** If the PmaReader passed as the first argument is not an incremental-reader -** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it serves -** to open and/or initialize the temp file related fields of the IncrMerge +** The PmaReader passed as the first argument is guaranteed to be an +** incremental-reader (pReadr->pIncr!=0). This function serves to open +** and/or initialize the temp file related fields of the IncrMerge ** object at (pReadr->pIncr). ** ** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders -** in the sub-tree headed by pReadr are also initialized. Data is then loaded -** into the buffers belonging to pReadr and it is set to -** point to the first key in its range. +** in the sub-tree headed by pReadr are also initialized. Data is then +** loaded into the buffers belonging to pReadr and it is set to point to +** the first key in its range. ** ** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed ** to be a multi-threaded PmaReader and this function is being called in a @@ -1993,59 +2162,62 @@ static int vdbeMergeEngineInit( static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ int rc = SQLITE_OK; IncrMerger *pIncr = pReadr->pIncr; + SortSubtask *pTask = pIncr->pTask; + sqlite3 *db = pTask->pSorter->db; /* eMode is always INCRINIT_NORMAL in single-threaded mode */ assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL ); - if( pIncr ){ - SortSubtask *pTask = pIncr->pTask; - sqlite3 *db = pTask->pSorter->db; + rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode); - - /* Set up the required files for pIncr. A multi-theaded IncrMerge object - ** requires two temp files to itself, whereas a single-threaded object - ** only requires a region of pTask->file2. */ - if( rc==SQLITE_OK ){ - int mxSz = pIncr->mxSz; + /* Set up the required files for pIncr. A multi-theaded IncrMerge object + ** requires two temp files to itself, whereas a single-threaded object + ** only requires a region of pTask->file2. */ + if( rc==SQLITE_OK ){ + int mxSz = pIncr->mxSz; #if SQLITE_MAX_WORKER_THREADS>0 - if( pIncr->bUseThread ){ - rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd); - if( rc==SQLITE_OK ){ - rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd); - } - }else + if( pIncr->bUseThread ){ + rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd); + if( rc==SQLITE_OK ){ + rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd); + } + }else #endif - /*if( !pIncr->bUseThread )*/{ - if( pTask->file2.pFd==0 ){ - assert( pTask->file2.iEof>0 ); - rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd); - pTask->file2.iEof = 0; - } - if( rc==SQLITE_OK ){ - pIncr->aFile[1].pFd = pTask->file2.pFd; - pIncr->iStartOff = pTask->file2.iEof; - pTask->file2.iEof += mxSz; - } + /*if( !pIncr->bUseThread )*/{ + if( pTask->file2.pFd==0 ){ + assert( pTask->file2.iEof>0 ); + rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd); + pTask->file2.iEof = 0; + } + if( rc==SQLITE_OK ){ + pIncr->aFile[1].pFd = pTask->file2.pFd; + pIncr->iStartOff = pTask->file2.iEof; + pTask->file2.iEof += mxSz; } } + } #if SQLITE_MAX_WORKER_THREADS>0 - if( rc==SQLITE_OK && pIncr->bUseThread ){ - /* Use the current thread to populate aFile[1], even though this - ** PmaReader is multi-threaded. The reason being that this function - ** is already running in background thread pIncr->pTask->thread. */ - assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK ); - rc = vdbeIncrPopulate(pIncr); - } + if( rc==SQLITE_OK && pIncr->bUseThread ){ + /* Use the current thread to populate aFile[1], even though this + ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object, + ** then this function is already running in background thread + ** pIncr->pTask->thread. + ** + ** If this is the INCRINIT_ROOT object, then it is running in the + ** main VDBE thread. But that is Ok, as that thread cannot return + ** control to the VDBE or proceed with anything useful until the + ** first results are ready from this merger object anyway. + */ + assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK ); + rc = vdbeIncrPopulate(pIncr); + } #endif - if( rc==SQLITE_OK - && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) - ){ - rc = vdbePmaReaderNext(pReadr); - } + if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){ + rc = vdbePmaReaderNext(pReadr); } + return rc; } @@ -2054,7 +2226,7 @@ static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){ ** The main routine for vdbePmaReaderIncrMergeInit() operations run in ** background threads. */ -static void *vdbePmaReaderBgInit(void *pCtx){ +static void *vdbePmaReaderBgIncrInit(void *pCtx){ PmaReader *pReader = (PmaReader*)pCtx; void *pRet = SQLITE_INT_TO_PTR( vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK) @@ -2062,20 +2234,36 @@ static void *vdbePmaReaderBgInit(void *pCtx){ pReader->pIncr->pTask->bDone = 1; return pRet; } +#endif /* -** Use a background thread to invoke vdbePmaReaderIncrMergeInit(INCRINIT_TASK) -** on the PmaReader object passed as the first argument. -** -** This call will initialize the various fields of the pReadr->pIncr -** structure and, if it is a multi-threaded IncrMerger, launch a -** background thread to populate aFile[1]. +** If the PmaReader passed as the first argument is not an incremental-reader +** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes +** the vdbePmaReaderIncrMergeInit() function with the parameters passed to +** this routine to initialize the incremental merge. +** +** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1), +** then a background thread is launched to call vdbePmaReaderIncrMergeInit(). +** Or, if the IncrMerger is single threaded, the same function is called +** using the current thread. */ -static int vdbePmaReaderBgIncrInit(PmaReader *pReadr){ - void *pCtx = (void*)pReadr; - return vdbeSorterCreateThread(pReadr->pIncr->pTask, vdbePmaReaderBgInit, pCtx); -} +static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){ + IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */ + int rc = SQLITE_OK; /* Return code */ + if( pIncr ){ +#if SQLITE_MAX_WORKER_THREADS>0 + assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK ); + if( pIncr->bUseThread ){ + void *pCtx = (void*)pReadr; + rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx); + }else #endif + { + rc = vdbePmaReaderIncrMergeInit(pReadr, eMode); + } + } + return rc; +} /* ** Allocate a new MergeEngine object to merge the contents of nPMA level-0 @@ -2287,6 +2475,11 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ MergeEngine *pMain = 0; #if SQLITE_MAX_WORKER_THREADS sqlite3 *db = pTask0->pSorter->db; + int i; + SorterCompare xCompare = vdbeSorterGetCompare(pSorter); + for(i=0; inTask; i++){ + pSorter->aTask[i].xCompare = xCompare; + } #endif rc = vdbeSorterMergeTreeBuild(pSorter, &pMain); @@ -2315,15 +2508,21 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ } } for(iTask=0; rc==SQLITE_OK && iTasknTask; iTask++){ + /* Check that: + ** + ** a) The incremental merge object is configured to use the + ** right task, and + ** b) If it is using task (nTask-1), it is configured to run + ** in single-threaded mode. This is important, as the + ** root merge (INCRINIT_ROOT) will be using the same task + ** object. + */ PmaReader *p = &pMain->aReadr[iTask]; - assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] ); - if( p->pIncr ){ - if( iTask==pSorter->nTask-1 ){ - rc = vdbePmaReaderIncrMergeInit(p, INCRINIT_TASK); - }else{ - rc = vdbePmaReaderBgIncrInit(p); - } - } + assert( p->pIncr==0 || ( + (p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */ + && (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */ + )); + rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK); } } pMain = 0; diff --git a/src/vdbetrace.c b/src/vdbetrace.c index 507c2f1..c230b50 100644 --- a/src/vdbetrace.c +++ b/src/vdbetrace.c @@ -84,9 +84,8 @@ char *sqlite3VdbeExpandSql( char zBase[100]; /* Initial working space */ db = p->db; - sqlite3StrAccumInit(&out, zBase, sizeof(zBase), + sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase), db->aLimit[SQLITE_LIMIT_LENGTH]); - out.db = db; if( db->nVdbeExec>1 ){ while( *zRawSql ){ const char *zStart = zRawSql; @@ -95,6 +94,8 @@ char *sqlite3VdbeExpandSql( assert( (zRawSql - zStart) > 0 ); sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart)); } + }else if( p->nVar==0 ){ + sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql)); }else{ while( zRawSql[0] ){ n = findNextHostParameter(zRawSql, &nToken); @@ -111,10 +112,12 @@ char *sqlite3VdbeExpandSql( idx = nextIndex; } }else{ - assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' ); + assert( zRawSql[0]==':' || zRawSql[0]=='$' || + zRawSql[0]=='@' || zRawSql[0]=='#' ); testcase( zRawSql[0]==':' ); testcase( zRawSql[0]=='$' ); testcase( zRawSql[0]=='@' ); + testcase( zRawSql[0]=='#' ); idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken); assert( idx>0 ); } diff --git a/src/vtab.c b/src/vtab.c index 00d0882..1989391 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -24,6 +24,8 @@ struct VtabCtx { VTable *pVTable; /* The virtual table being constructed */ Table *pTab; /* The Table object to which the virtual table belongs */ + VtabCtx *pPrior; /* Parent context (if any) */ + int bDeclared; /* True after sqlite3_declare_vtab() is called */ }; /* @@ -389,6 +391,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ char *zStmt; char *zWhere; int iDb; + int iReg; Vdbe *v; /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ @@ -423,8 +426,10 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); - sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, - pTab->zName, sqlite3Strlen30(pTab->zName) + 1); + + iReg = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, iReg, 0, pTab->zName, 0); + sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg); } /* If we are rereading the sqlite_master table create the in-memory @@ -467,7 +472,7 @@ void sqlite3VtabArgExtend(Parse *pParse, Token *p){ pArg->z = p->z; pArg->n = p->n; }else{ - assert(pArg->z < p->z); + assert(pArg->z <= p->z); pArg->n = (int)(&p->z[p->n] - pArg->z); } } @@ -484,15 +489,27 @@ static int vtabCallConstructor( int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ - VtabCtx sCtx, *pPriorCtx; + VtabCtx sCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; - char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); + char *zModuleName; int iDb; + VtabCtx *pCtx; + /* Check that the virtual-table is not already being initialized */ + for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ + if( pCtx->pTab==pTab ){ + *pzErr = sqlite3MPrintf(db, + "vtable constructor called recursively: %s", pTab->zName + ); + return SQLITE_LOCKED; + } + } + + zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); if( !zModuleName ){ return SQLITE_NOMEM; } @@ -513,11 +530,13 @@ static int vtabCallConstructor( assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; - pPriorCtx = db->pVtabCtx; + sCtx.pPrior = db->pVtabCtx; + sCtx.bDeclared = 0; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - db->pVtabCtx = pPriorCtx; + db->pVtabCtx = sCtx.pPrior; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ if( zErr==0 ){ @@ -533,13 +552,14 @@ static int vtabCallConstructor( memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); pVTable->pVtab->pModule = pMod->pModule; pVTable->nRef = 1; - if( sCtx.pTab ){ + if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; + u8 oooHidden = 0; /* If everything went according to plan, link the new VTable structure ** into the linked list headed by pTab->pVTable. Then loop through the ** columns of the table to see if any of them contain the token "hidden". @@ -552,7 +572,10 @@ static int vtabCallConstructor( char *zType = pTab->aCol[iCol].zType; int nType; int i = 0; - if( !zType ) continue; + if( !zType ){ + pTab->tabFlags |= oooHidden; + continue; + } nType = sqlite3Strlen30(zType); if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ for(i=0; iaCol[iCol].colFlags |= COLFLAG_HIDDEN; + oooHidden = TF_OOOHidden; + }else{ + pTab->tabFlags |= oooHidden; } } } @@ -703,21 +729,25 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ ** virtual table module. */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ + VtabCtx *pCtx; Parse *pParse; - int rc = SQLITE_OK; Table *pTab; char *zErr = 0; #ifdef SQLITE_ENABLE_API_ARMOR - if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; + if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){ + return SQLITE_MISUSE_BKPT; + } #endif sqlite3_mutex_enter(db->mutex); - if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){ + pCtx = db->pVtabCtx; + if( !pCtx || pCtx->bDeclared ){ sqlite3Error(db, SQLITE_MISUSE); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } + pTab = pCtx->pTab; assert( (pTab->tabFlags & TF_Virtual)!=0 ); pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); @@ -740,7 +770,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } - db->pVtabCtx->pTab = 0; + pCtx->bDeclared = 1; }else{ sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); @@ -775,11 +805,15 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ - VTable *p = vtabDisconnectAll(db, pTab); - - assert( rc==SQLITE_OK ); + VTable *p; + for(p=pTab->pVTable; p; p=p->pNext){ + assert( p->pVtab ); + if( p->pVtab->nRef>0 ){ + return SQLITE_LOCKED; + } + } + p = vtabDisconnectAll(db, pTab); rc = p->pMod->pModule->xDestroy(p->pVtab); - /* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */ if( rc==SQLITE_OK ){ assert( pTab->pVTable==p && p->pNext==0 ); @@ -930,7 +964,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){ int rc = SQLITE_OK; assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN ); - assert( iSavepoint>=0 ); + assert( iSavepoint>=-1 ); if( db->aVTrans ){ int i; for(i=0; rc==SQLITE_OK && inVTrans; i++){ @@ -1048,7 +1082,7 @@ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ if( pTab==pToplevel->apVtabLock[i] ) return; } n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]); - apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n); + apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n); if( apVtabLock ){ pToplevel->apVtabLock = apVtabLock; pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; diff --git a/src/vxworks.h b/src/vxworks.h new file mode 100644 index 0000000..45a4445 --- /dev/null +++ b/src/vxworks.h @@ -0,0 +1,29 @@ +/* +** 2015-03-02 +** +** 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 contains code that is specific to Wind River's VxWorks +*/ +#if defined(__RTP__) || defined(_WRS_KERNEL) +/* This is VxWorks. Set up things specially for that OS +*/ +#include +#include /* amalgamator: dontcache */ +#define OS_VXWORKS 1 +#define SQLITE_OS_OTHER 0 +#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1 +#define SQLITE_OMIT_LOAD_EXTENSION 1 +#define SQLITE_ENABLE_LOCKING_STYLE 0 +#define HAVE_UTIME 1 +#else +/* This is not VxWorks. */ +#define OS_VXWORKS 0 +#endif /* defined(_WRS_KERNEL) */ diff --git a/src/wal.c b/src/wal.c index 71f4a3d..ce98149 100644 --- a/src/wal.c +++ b/src/wal.c @@ -522,7 +522,7 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ if( pWal->nWiData<=iPage ){ int nByte = sizeof(u32*)*(iPage+1); volatile u32 **apNew; - apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte); + apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte); if( !apNew ){ *ppPage = 0; return SQLITE_NOMEM; @@ -788,9 +788,10 @@ static void walUnlockShared(Wal *pWal, int lockIdx){ SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); } -static int walLockExclusive(Wal *pWal, int lockIdx, int n){ +static int walLockExclusive(Wal *pWal, int lockIdx, int n, int fBlock){ int rc; if( pWal->exclusiveMode ) return SQLITE_OK; + if( fBlock ) sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_WAL_BLOCK, 0); rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, @@ -1076,7 +1077,7 @@ static int walIndexRecover(Wal *pWal){ assert( pWal->writeLock ); iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock; nLock = SQLITE_SHM_NLOCK - iLock; - rc = walLockExclusive(pWal, iLock, nLock); + rc = walLockExclusive(pWal, iLock, nLock, 0); if( rc ){ return rc; } @@ -1146,7 +1147,7 @@ static int walIndexRecover(Wal *pWal){ /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; - aFrame = (u8 *)sqlite3_malloc(szFrame); + aFrame = (u8 *)sqlite3_malloc64(szFrame); if( !aFrame ){ rc = SQLITE_NOMEM; goto recovery_error; @@ -1539,7 +1540,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc(nByte); + p = (WalIterator *)sqlite3_malloc64(nByte); if( !p ){ return SQLITE_NOMEM; } @@ -1549,7 +1550,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ /* Allocate temporary space used by the merge-sort routine. This block ** of memory will be freed before this function returns. */ - aTmp = (ht_slot *)sqlite3_malloc( + aTmp = (ht_slot *)sqlite3_malloc64( sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) ); if( !aTmp ){ @@ -1610,7 +1611,7 @@ static int walBusyLock( ){ int rc; do { - rc = walLockExclusive(pWal, lockIdx, n); + rc = walLockExclusive(pWal, lockIdx, n, 0); }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) ); return rc; } @@ -1729,6 +1730,14 @@ static int walCheckpoint( mxSafeFrame = pWal->hdr.mxFrame; mxPage = pWal->hdr.nPage; for(i=1; iaReadMark[i]; if( mxSafeFrame>y ){ assert( y<=pWal->hdr.mxFrame ); @@ -2043,7 +2052,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ walUnlockShared(pWal, WAL_WRITE_LOCK); rc = SQLITE_READONLY_RECOVERY; } - }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){ + }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 1)) ){ pWal->writeLock = 1; if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ badHdr = walIndexTryHdr(pWal, pChanged); @@ -2249,7 +2258,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ && (mxReadMarkhdr.mxFrame || mxI==0) ){ for(i=1; iaReadMark[i] = pWal->hdr.mxFrame; mxI = i; @@ -2505,7 +2514,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ /* Only one writer allowed at a time. Get the write lock. Return ** SQLITE_BUSY if unable. */ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); + rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 0); if( rc ){ return rc; } @@ -2650,7 +2659,7 @@ static int walRestartLog(Wal *pWal){ if( pInfo->nBackfill>0 ){ u32 salt1; sqlite3_randomness(4, &salt1); - rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1, 0); if( rc==SQLITE_OK ){ /* If all readers are using WAL_READ_LOCK(0) (in other words if no ** readers are currently using the WAL), then the transactions @@ -2975,7 +2984,7 @@ int sqlite3WalCheckpoint( /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive ** "checkpoint" lock on the database file. */ - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); + rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1, 0); if( rc ){ /* EVIDENCE-OF: R-10421-19736 If any other process is running a ** checkpoint operation at the same time, the lock cannot be obtained and diff --git a/src/where.c b/src/where.c index f45da74..85eb00b 100644 --- a/src/where.c +++ b/src/where.c @@ -202,7 +202,7 @@ static void whereClauseClear(WhereClause *pWC){ ** calling this routine. Such pointers may be reinitialized by referencing ** the pWC->a[] array. */ -static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ +static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ WhereTerm *pTerm; int idx; testcase( wtFlags & TERM_VIRTUAL ); @@ -255,13 +255,14 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ ** all terms of the WHERE clause. */ static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ + Expr *pE2 = sqlite3ExprSkipCollate(pExpr); pWC->op = op; - if( pExpr==0 ) return; - if( pExpr->op!=op ){ + if( pE2==0 ) return; + if( pE2->op!=op ){ whereClauseInsert(pWC, pExpr, 0); }else{ - whereSplit(pWC, pExpr->pLeft, op); - whereSplit(pWC, pExpr->pRight, op); + whereSplit(pWC, pE2->pLeft, op); + whereSplit(pWC, pE2->pRight, op); } } @@ -627,7 +628,11 @@ static void exprAnalyzeAll( ** so and false if not. ** ** In order for the operator to be optimizible, the RHS must be a string -** literal that does not begin with a wildcard. +** literal that does not begin with a wildcard. The LHS must be a column +** that may only be NULL, a string, or a BLOB, never a number. (This means +** that virtual tables cannot participate in the LIKE optimization.) If the +** collating sequence for the column on the LHS must be appropriate for +** the operator. */ static int isLikeOrGlob( Parse *pParse, /* Parsing and code generating context */ @@ -656,7 +661,7 @@ static int isLikeOrGlob( pLeft = pList->a[1].pExpr; if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) + || IsVirtual(pLeft->pTab) /* Value might be numeric */ ){ /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must ** be the name of an indexed column with TEXT affinity. */ @@ -766,6 +771,79 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ pWC->a[iParent].nChild++; } +/* +** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not +** a conjunction, then return just pTerm when N==0. If N is exceeds +** the number of available subterms, return NULL. +*/ +static WhereTerm *whereNthSubterm(WhereTerm *pTerm, int N){ + if( pTerm->eOperator!=WO_AND ){ + return N==0 ? pTerm : 0; + } + if( Nu.pAndInfo->wc.nTerm ){ + return &pTerm->u.pAndInfo->wc.a[N]; + } + return 0; +} + +/* +** Subterms pOne and pTwo are contained within WHERE clause pWC. The +** two subterms are in disjunction - they are OR-ed together. +** +** If these two terms are both of the form: "A op B" with the same +** A and B values but different operators and if the operators are +** compatible (if one is = and the other is <, for example) then +** add a new virtual AND term to pWC that is the combination of the +** two. +** +** Some examples: +** +** x x<=y +** x=y OR x=y --> x=y +** x<=y OR x x<=y +** +** The following is NOT generated: +** +** xy --> x!=y +*/ +static void whereCombineDisjuncts( + SrcList *pSrc, /* the FROM clause */ + WhereClause *pWC, /* The complete WHERE clause */ + WhereTerm *pOne, /* First disjunct */ + WhereTerm *pTwo /* Second disjunct */ +){ + u16 eOp = pOne->eOperator | pTwo->eOperator; + sqlite3 *db; /* Database connection (for malloc) */ + Expr *pNew; /* New virtual expression */ + int op; /* Operator for the combined expression */ + int idxNew; /* Index in pWC of the next virtual term */ + + if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; + if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return; + if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp + && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; + assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); + assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); + if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; + if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return; + /* If we reach this point, it means the two subterms can be combined */ + if( (eOp & (eOp-1))!=0 ){ + if( eOp & (WO_LT|WO_LE) ){ + eOp = WO_LE; + }else{ + assert( eOp & (WO_GT|WO_GE) ); + eOp = WO_GE; + } + } + db = pWC->pWInfo->pParse->db; + pNew = sqlite3ExprDup(db, pOne->pExpr, 0); + if( pNew==0 ) return; + for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( opop = op; + idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC); + exprAnalyze(pSrc, pWC, idxNew); +} + #if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY) /* ** Analyze a term that consists of two or more OR-connected @@ -790,6 +868,7 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) +** (F) x>A OR (x=A AND y>=B) ** ** CASE 1: ** @@ -806,6 +885,16 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ ** ** CASE 2: ** +** If there are exactly two disjuncts one side has x>A and the other side +** has x=A (for the same x and A) then add a new virtual conjunct term to the +** WHERE clause of the form "x>=A". Example: +** +** x>A OR (x=A AND y>B) adds: x>=A +** +** The added conjunct can sometimes be helpful in query planning. +** +** CASE 3: +** ** If all subterms are indexable by a single table T, then set ** ** WhereTerm.eOperator = WO_OR @@ -932,12 +1021,26 @@ static void exprAnalyzeOrTerm( } /* - ** Record the set of tables that satisfy case 2. The set might be + ** Record the set of tables that satisfy case 3. The set might be ** empty. */ pOrInfo->indexable = indexable; pTerm->eOperator = indexable==0 ? 0 : WO_OR; + /* For a two-way OR, attempt to implementation case 2. + */ + if( indexable && pOrWc->nTerm==2 ){ + int iOne = 0; + WhereTerm *pOne; + while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){ + int iTwo = 0; + WhereTerm *pTwo; + while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){ + whereCombineDisjuncts(pSrc, pWC, pOne, pTwo); + } + } + } + /* ** chngToIN holds a set of tables that *might* satisfy case 1. But ** we have to do some additional checking to see if case 1 really @@ -1067,7 +1170,7 @@ static void exprAnalyzeOrTerm( }else{ sqlite3ExprListDelete(db, pList); } - pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ + pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */ } } } @@ -1105,7 +1208,7 @@ static void exprAnalyze( Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ - int noCase = 0; /* LIKE/GLOB distinguishes case */ + int noCase = 0; /* uppercase equivalent to lowercase */ int op; /* Top-level operator. pExpr->op */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite3 *db = pParse->db; /* Database connection */ @@ -1243,12 +1346,15 @@ static void exprAnalyze( /* Add constraints to reduce the search space on a LIKE or GLOB ** operator. ** - ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints + ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints ** - ** x>='abc' AND x<'abd' AND x LIKE 'abc%' + ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%' ** ** The last character of the prefix "abc" is incremented to form the - ** termination condition "abd". + ** termination condition "abd". If case is not significant (the default + ** for LIKE) then the lower-bound is made all uppercase and the upper- + ** bound is made all lowercase so that the bounds also work when comparing + ** BLOBs. */ if( pWC->op==TK_AND && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase) @@ -1259,10 +1365,26 @@ static void exprAnalyze( Expr *pNewExpr2; int idxNew1; int idxNew2; - Token sCollSeqName; /* Name of collating sequence */ + const char *zCollSeqName; /* Name of collating sequence */ + const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC; pLeft = pExpr->x.pList->a[1].pExpr; pStr2 = sqlite3ExprDup(db, pStr1, 0); + + /* Convert the lower bound to upper-case and the upper bound to + ** lower-case (upper-case is less than lower-case in ASCII) so that + ** the range constraints also work for BLOBs + */ + if( noCase && !pParse->db->mallocFailed ){ + int i; + char c; + pTerm->wtFlags |= TERM_LIKE; + for(i=0; (c = pStr1->u.zToken[i])!=0; i++){ + pStr1->u.zToken[i] = sqlite3Toupper(c); + pStr2->u.zToken[i] = sqlite3Tolower(c); + } + } + if( !db->mallocFailed ){ u8 c, *pC; /* Last character before the first wildcard */ pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; @@ -1279,22 +1401,21 @@ static void exprAnalyze( } *pC = c + 1; } - sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; - sCollSeqName.n = 6; + zCollSeqName = noCase ? "NOCASE" : "BINARY"; pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); - pNewExpr1 = sqlite3PExpr(pParse, TK_GE, - sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), + pNewExpr1 = sqlite3PExpr(pParse, TK_GE, + sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), pStr1, 0); transferJoinMarkings(pNewExpr1, pExpr); - idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); + idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); testcase( idxNew1==0 ); exprAnalyze(pSrc, pWC, idxNew1); pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, - sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), + sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), pStr2, 0); transferJoinMarkings(pNewExpr2, pExpr); - idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); + idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); testcase( idxNew2==0 ); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; @@ -1412,7 +1533,7 @@ static int findIndexCol( && p->iTable==iBase ){ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); - if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ + if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){ return i; } } @@ -1612,12 +1733,16 @@ static void constructAutomaticIndex( pLoop = pLevel->pWLoop; idxCols = 0; for(pTerm=pWC->a; pTermpExpr; + assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */ + || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */ + || pLoop->prereq!=0 ); /* table of a LEFT JOIN */ if( pLoop->prereq==0 && (pTerm->wtFlags & TERM_VIRTUAL)==0 - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - && sqlite3ExprIsTableConstant(pTerm->pExpr, pSrc->iCursor) ){ + && !ExprHasProperty(pExpr, EP_FromJoin) + && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ pPartial = sqlite3ExprAnd(pParse->db, pPartial, - sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); + sqlite3ExprDup(pParse->db, pExpr, 0)); } if( termCanDriveIndex(pTerm, pSrc, notReady) ){ int iCol = pTerm->u.leftColumn; @@ -1682,7 +1807,7 @@ static void constructAutomaticIndex( idxCols |= cMask; pIdx->aiColumn[n] = pTerm->u.leftColumn; pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); - pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY"; + pIdx->azColl[n] = pColl ? pColl->zName : "BINARY"; n++; } } @@ -1904,11 +2029,14 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: ** -** aStat[0] Est. number of rows less than pVal -** aStat[1] Est. number of rows equal to pVal +** aStat[0] Est. number of rows less than pRec +** aStat[1] Est. number of rows equal to pRec ** ** Return the index of the sample that is the smallest sample that -** is greater than or equal to pRec. +** is greater than or equal to pRec. Note that this index is not an index +** into the aSample[] array - it is an index into a virtual set of samples +** based on the contents of aSample[] and the number of fields in record +** pRec. */ static int whereKeyStats( Parse *pParse, /* Database connection */ @@ -1919,67 +2047,158 @@ static int whereKeyStats( ){ IndexSample *aSample = pIdx->aSample; int iCol; /* Index of required stats in anEq[] etc. */ + int i; /* Index of first sample >= pRec */ + int iSample; /* Smallest sample larger than or equal to pRec */ int iMin = 0; /* Smallest sample not yet tested */ - int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ int iTest; /* Next sample to test */ int res; /* Result of comparison operation */ + int nField; /* Number of fields in pRec */ + tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */ #ifndef SQLITE_DEBUG UNUSED_PARAMETER( pParse ); #endif assert( pRec!=0 ); - iCol = pRec->nField - 1; assert( pIdx->nSample>0 ); - assert( pRec->nField>0 && iColnSampleCol ); + assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol ); + + /* Do a binary search to find the first sample greater than or equal + ** to pRec. If pRec contains a single field, the set of samples to search + ** is simply the aSample[] array. If the samples in aSample[] contain more + ** than one fields, all fields following the first are ignored. + ** + ** If pRec contains N fields, where N is more than one, then as well as the + ** samples in aSample[] (truncated to N fields), the search also has to + ** consider prefixes of those samples. For example, if the set of samples + ** in aSample is: + ** + ** aSample[0] = (a, 5) + ** aSample[1] = (a, 10) + ** aSample[2] = (b, 5) + ** aSample[3] = (c, 100) + ** aSample[4] = (c, 105) + ** + ** Then the search space should ideally be the samples above and the + ** unique prefixes [a], [b] and [c]. But since that is hard to organize, + ** the code actually searches this set: + ** + ** 0: (a) + ** 1: (a, 5) + ** 2: (a, 10) + ** 3: (a, 10) + ** 4: (b) + ** 5: (b, 5) + ** 6: (c) + ** 7: (c, 100) + ** 8: (c, 105) + ** 9: (c, 105) + ** + ** For each sample in the aSample[] array, N samples are present in the + ** effective sample array. In the above, samples 0 and 1 are based on + ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc. + ** + ** Often, sample i of each block of N effective samples has (i+1) fields. + ** Except, each sample may be extended to ensure that it is greater than or + ** equal to the previous sample in the array. For example, in the above, + ** sample 2 is the first sample of a block of N samples, so at first it + ** appears that it should be 1 field in size. However, that would make it + ** smaller than sample 1, so the binary search would not work. As a result, + ** it is extended to two fields. The duplicates that this creates do not + ** cause any problems. + */ + nField = pRec->nField; + iCol = 0; + iSample = pIdx->nSample * nField; do{ - iTest = (iMin+i)/2; - res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec); - if( res<0 ){ - iMin = iTest+1; + int iSamp; /* Index in aSample[] of test sample */ + int n; /* Number of fields in test sample */ + + iTest = (iMin+iSample)/2; + iSamp = iTest / nField; + if( iSamp>0 ){ + /* The proposed effective sample is a prefix of sample aSample[iSamp]. + ** Specifically, the shortest prefix of at least (1 + iTest%nField) + ** fields that is greater than the previous effective sample. */ + for(n=(iTest % nField) + 1; nnField = n; + res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec); + if( res<0 ){ + iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1]; + iMin = iTest+1; + }else if( res==0 && nnSample ); - assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) - || pParse->db->mallocFailed ); - }else{ - /* Otherwise, pRec must be smaller than sample $i and larger than - ** sample ($i-1). */ - assert( i==pIdx->nSample - || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 - || pParse->db->mallocFailed ); - assert( i==0 - || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 - || pParse->db->mallocFailed ); + if( pParse->db->mallocFailed==0 ){ + if( res==0 ){ + /* If (res==0) is true, then pRec must be equal to sample i. */ + assert( inSample ); + assert( iCol==nField-1 ); + pRec->nField = nField; + assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec) + || pParse->db->mallocFailed + ); + }else{ + /* Unless i==pIdx->nSample, indicating that pRec is larger than + ** all samples in the aSample[] array, pRec must be smaller than the + ** (iCol+1) field prefix of sample i. */ + assert( i<=pIdx->nSample && i>=0 ); + pRec->nField = iCol+1; + assert( i==pIdx->nSample + || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0 + || pParse->db->mallocFailed ); + + /* if i==0 and iCol==0, then record pRec is smaller than all samples + ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must + ** be greater than or equal to the (iCol) field prefix of sample i. + ** If (i>0), then pRec must also be greater than sample (i-1). */ + if( iCol>0 ){ + pRec->nField = iCol; + assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 + || pParse->db->mallocFailed ); + } + if( i>0 ){ + pRec->nField = nField; + assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 + || pParse->db->mallocFailed ); + } + } } #endif /* ifdef SQLITE_DEBUG */ - /* At this point, aSample[i] is the first sample that is greater than - ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less - ** than pVal. If aSample[i]==pVal, then res==0. - */ if( res==0 ){ + /* Record pRec is equal to sample i */ + assert( iCol==nField-1 ); aStat[0] = aSample[i].anLt[iCol]; aStat[1] = aSample[i].anEq[iCol]; }else{ - tRowcnt iLower, iUpper, iGap; - if( i==0 ){ - iLower = 0; - iUpper = aSample[0].anLt[iCol]; + /* At this point, the (iCol+1) field prefix of aSample[i] is the first + ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec + ** is larger than all samples in the array. */ + tRowcnt iUpper, iGap; + if( i>=pIdx->nSample ){ + iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); }else{ - i64 nRow0 = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]); - iUpper = i>=pIdx->nSample ? nRow0 : aSample[i].anLt[iCol]; - iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol]; + iUpper = aSample[i].anLt[iCol]; } - aStat[1] = pIdx->aAvgEq[iCol]; + if( iLower>=iUpper ){ iGap = 0; }else{ @@ -1991,7 +2210,11 @@ static int whereKeyStats( iGap = iGap/3; } aStat[0] = iLower + iGap; + aStat[1] = pIdx->aAvgEq[iCol]; } + + /* Restore the pRec->nField value before returning. */ + pRec->nField = nField; return i; } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ @@ -2465,20 +2688,43 @@ static int whereInScanEst( ** but joins might run a little slower. The trick is to disable as much ** as we can without disabling too much. If we disabled in (1), we'd get ** the wrong answer. See ticket #813. +** +** If all the children of a term are disabled, then that term is also +** automatically disabled. In this way, terms get disabled if derived +** virtual terms are tested first. For example: +** +** x GLOB 'abc*' AND x>='abc' AND x<'acd' +** \___________/ \______/ \_____/ +** parent child1 child2 +** +** Only the parent term was in the original WHERE clause. The child1 +** and child2 terms were added by the LIKE optimization. If both of +** the virtual child terms are valid, then testing of the parent can be +** skipped. +** +** Usually the parent term is marked as TERM_CODED. But if the parent +** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead. +** The TERM_LIKECOND marking indicates that the term should be coded inside +** a conditional such that is only evaluated on the second pass of a +** LIKE-optimization loop, when scanning BLOBs instead of strings. */ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ - if( pTerm + int nLoop = 0; + while( pTerm && (pTerm->wtFlags & TERM_CODED)==0 && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) && (pLevel->notReady & pTerm->prereqAll)==0 ){ - pTerm->wtFlags |= TERM_CODED; - if( pTerm->iParent>=0 ){ - WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent]; - if( (--pOther->nChild)==0 ){ - disableTerm(pLevel, pOther); - } + if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){ + pTerm->wtFlags |= TERM_LIKECOND; + }else{ + pTerm->wtFlags |= TERM_CODED; } + if( pTerm->iParent<0 ) break; + pTerm = &pTerm->pWC->a[pTerm->iParent]; + pTerm->nChild--; + if( pTerm->nChild!=0 ) break; + nLoop++; } } @@ -2857,8 +3103,7 @@ static int explainOneScan( || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); - sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); - str.db = db; + sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); if( pItem->pSelect ){ sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId); @@ -2962,7 +3207,34 @@ static void addScanStatus( # define addScanStatus(a, b, c, d) ((void)d) #endif - +/* +** If the most recently coded instruction is a constant range contraint +** that originated from the LIKE optimization, then change the P3 to be +** pLoop->iLikeRepCntr and set P5. +** +** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range +** expression: "x>='ABC' AND x<'abd'". But this requires that the range +** scan loop run twice, once for strings and a second time for BLOBs. +** The OP_String opcodes on the second pass convert the upper and lower +** bound string contants to blobs. This routine makes the necessary changes +** to the OP_String opcodes for that to happen. +*/ +static void whereLikeOptimizationStringFixup( + Vdbe *v, /* prepared statement under construction */ + WhereLevel *pLevel, /* The loop that contains the LIKE operator */ + WhereTerm *pTerm /* The upper or lower bound just coded */ +){ + if( pTerm->wtFlags & TERM_LIKEOPT ){ + VdbeOp *pOp; + assert( pLevel->iLikeRepCntr>0 ); + pOp = sqlite3VdbeGetOp(v, -1); + assert( pOp!=0 ); + assert( pOp->opcode==OP_String8 + || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); + pOp->p3 = pLevel->iLikeRepCntr; + pOp->p5 = 1; + } +} /* ** Generate code for the start of the iLevel-th loop in the WHERE clause @@ -3292,10 +3564,25 @@ static Bitmask codeOneLoopStart( if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ pRangeStart = pLoop->aLTerm[j++]; nExtraReg = 1; + /* Like optimization range constraints always occur in pairs */ + assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 || + (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 ); } if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; nExtraReg = 1; + if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){ + assert( pRangeStart!=0 ); /* LIKE opt constraints */ + assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */ + pLevel->iLikeRepCntr = ++pParse->nMem; + testcase( bRev ); + testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC ); + sqlite3VdbeAddOp2(v, OP_Integer, + bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC), + pLevel->iLikeRepCntr); + VdbeComment((v, "LIKE loop counter")); + pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v); + } if( pRangeStart==0 && (j = pIdx->aiColumn[nEq])>=0 && pIdx->pTable->aCol[j].notNull==0 @@ -3338,6 +3625,7 @@ static Bitmask codeOneLoopStart( if( pRangeStart ){ Expr *pRight = pRangeStart->pExpr->pRight; sqlite3ExprCode(pParse, pRight, regBase+nEq); + whereLikeOptimizationStringFixup(v, pLevel, pRangeStart); if( (pRangeStart->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ @@ -3383,6 +3671,7 @@ static Bitmask codeOneLoopStart( Expr *pRight = pRangeEnd->pExpr->pRight; sqlite3ExprCacheRemove(pParse, regBase+nEq, 1); sqlite3ExprCode(pParse, pRight, regBase+nEq); + whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ @@ -3610,7 +3899,8 @@ static Bitmask codeOneLoopStart( */ wctrlFlags = WHERE_OMIT_OPEN_CLOSE | WHERE_FORCE_TABLE - | WHERE_ONETABLE_ONLY; + | WHERE_ONETABLE_ONLY + | WHERE_NO_AUTOINDEX; for(ii=0; iinTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ @@ -3772,6 +4062,7 @@ static Bitmask codeOneLoopStart( */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; + int skipLikeAddr = 0; testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; @@ -3786,7 +4077,13 @@ static Bitmask codeOneLoopStart( if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ continue; } + if( pTerm->wtFlags & TERM_LIKECOND ){ + assert( pLevel->iLikeRepCntr>0 ); + skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr); + VdbeCoverage(v); + } sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL); + if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr); pTerm->wtFlags |= TERM_CODED; } @@ -4005,6 +4302,13 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ */ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ if( ALWAYS(pWInfo) ){ + int i; + for(i=0; inLevel; i++){ + WhereLevel *pLevel = &pWInfo->a[i]; + if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){ + sqlite3DbFree(db, pLevel->u.in.aInLoop); + } + } whereClauseClear(&pWInfo->sWC); while( pWInfo->pLoops ){ WhereLoop *p = pWInfo->pLoops; @@ -4451,6 +4755,10 @@ static int whereLoopAddBtreeIndex( } if( pTerm->prereqRight & pNew->maskSelf ) continue; + /* Do not allow the upper bound of a LIKE optimization range constraint + ** to mix with a lower range bound from some other source */ + if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; + pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->nLTerm = saved_nLTerm; @@ -4480,7 +4788,7 @@ static int whereLoopAddBtreeIndex( }else if( eOp & (WO_EQ) ){ pNew->wsFlags |= WHERE_COLUMN_EQ; if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){ - if( iCol>=0 && !IsUniqueIndex(pProbe) ){ + if( iCol>=0 && pProbe->uniqNotNull==0 ){ pNew->wsFlags |= WHERE_UNQ_WANTED; }else{ pNew->wsFlags |= WHERE_ONEROW; @@ -4494,6 +4802,17 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; pBtm = pTerm; pTop = 0; + if( pTerm->wtFlags & TERM_LIKEOPT ){ + /* Range contraints that come from the LIKE optimization are + ** always used in pairs. */ + pTop = &pTerm[1]; + assert( (pTop-(pTerm->pWC->a))pWC->nTerm ); + assert( pTop->wtFlags & TERM_LIKEOPT ); + assert( pTop->eOperator==WO_LT ); + if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ + pNew->aLTerm[pNew->nLTerm++] = pTop; + pNew->wsFlags |= WHERE_TOP_LIMIT; + } }else{ assert( eOp & (WO_LT|WO_LE) ); testcase( eOp & WO_LT ); @@ -4695,8 +5014,9 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ int i; WhereTerm *pTerm; for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - if( sqlite3ExprImpliesExpr(pTerm->pExpr, pWhere, iTab) - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) + Expr *pExpr = pTerm->pExpr; + if( sqlite3ExprImpliesExpr(pExpr, pWhere, iTab) + && (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) ){ return 1; } @@ -4803,6 +5123,7 @@ static int whereLoopAddBtree( #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet + && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && pSrc->pIndex==0 && !pSrc->viaCoroutine @@ -5686,10 +6007,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ /* Seed the search with a single WherePath containing zero WhereLoops. ** - ** TUNING: Do not let the number of iterations go above 25. If the cost - ** of computing an automatic index is not paid back within the first 25 + ** TUNING: Do not let the number of iterations go above 28. If the cost + ** of computing an automatic index is not paid back within the first 28 ** rows, then do not use the automatic index. */ - aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) ); + aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) ); nFrom = 1; assert( aFrom[0].isOrdered==0 ); if( nOrderBy ){ @@ -5927,7 +6248,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ pWInfo->revMask = pFrom->revLoop; } if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP) - && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr + && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0 ){ Bitmask revMask = 0; int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, @@ -6332,7 +6653,6 @@ WhereInfo *sqlite3WhereBegin( } #ifdef WHERETRACE_ENABLED /* !=0 */ if( sqlite3WhereTrace ){ - int ii; sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); if( pWInfo->nOBSat>0 ){ sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask); @@ -6487,6 +6807,12 @@ WhereInfo *sqlite3WhereBegin( if( op ){ sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIx); + if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0 + && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 + && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 + ){ + sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */ + } VdbeComment((v, "%s", pIx->zName)); } } @@ -6579,7 +6905,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen); sqlite3VdbeJumpHere(v, pIn->addrInTop-1); } - sqlite3DbFree(db, pLevel->u.in.aInLoop); } sqlite3VdbeResolveLabel(v, pLevel->addrBrk); if( pLevel->addrSkip ){ @@ -6588,6 +6913,16 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ sqlite3VdbeJumpHere(v, pLevel->addrSkip); sqlite3VdbeJumpHere(v, pLevel->addrSkip-2); } + if( pLevel->addrLikeRep ){ + int op; + if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){ + op = OP_DecrJumpZero; + }else{ + op = OP_JumpZeroIncr; + } + sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep); + VdbeCoverage(v); + } if( pLevel->iLeftJoin ){ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v); assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 diff --git a/src/whereInt.h b/src/whereInt.h index 2ccc6ec..04cc202 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -69,6 +69,8 @@ struct WhereLevel { int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ + int iLikeRepCntr; /* LIKE range processing counter register */ + int addrLikeRep; /* LIKE range processing address */ u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ int p1, p2; /* Operands of the opcode used to ends the loop */ @@ -253,7 +255,7 @@ struct WhereTerm { } u; LogEst truthProb; /* Probability of truth for this expression */ u16 eOperator; /* A WO_xx value describing */ - u8 wtFlags; /* TERM_xxx bit flags. See below */ + u16 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ @@ -275,6 +277,9 @@ struct WhereTerm { #else # define TERM_VNULL 0x00 /* Disabled if not using stat3 */ #endif +#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */ +#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */ +#define TERM_LIKE 0x400 /* The original LIKE operator */ /* ** An instance of the WhereScan object is used as an iterator for locating diff --git a/test/alter.test b/test/alter.test index ddf1698..ebfe97a 100644 --- a/test/alter.test +++ b/test/alter.test @@ -912,5 +912,14 @@ do_execsql_test alter-17.9 { do_execsql_test alter-17.10 { SELECT sqlite_rename_parent(NULL,'abc','xyz'); } {{}} +do_execsql_test alter-17.11 { + SELECT sqlite_rename_parent('create references ''','abc','xyz'); +} {{create references '}} +do_execsql_test alter-17.12 { + SELECT sqlite_rename_parent('create references "abc"123" ','abc','xyz'); +} {{create references "xyz"123" }} +do_execsql_test alter-17.13 { + SELECT sqlite_rename_parent("references '''",'abc','xyz'); +} {{references '''}} finish_test diff --git a/test/analyze.test b/test/analyze.test index c445084..af277cc 100644 --- a/test/analyze.test +++ b/test/analyze.test @@ -359,6 +359,6 @@ do_test analyze-99.1 { catchsql { ANALYZE } -} {1 {malformed database schema (sqlite_stat1) - near "nonsense": syntax error}} +} {1 {malformed database schema (sqlite_stat1)}} finish_test diff --git a/test/analyze3.test b/test/analyze3.test index e7416d5..d61d21a 100644 --- a/test/analyze3.test +++ b/test/analyze3.test @@ -16,6 +16,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix analyze3 ifcapable !stat4&&!stat3 { finish_test @@ -46,6 +47,9 @@ ifcapable !stat4&&!stat3 { # # analyze3-6.*: Test that the problem fixed by commit [127a5b776d] is fixed. # +# analyze3-7.*: Test that some memory leaks discovered by fuzz testing +# have been fixed. +# proc getvar {varname} { uplevel #0 set $varname } db function var getvar @@ -281,35 +285,35 @@ do_eqp_test analyze3-2.3 { do_test analyze3-2.4 { sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE 'a%' } -} {101 0 100} +} {102 0 100} do_test analyze3-2.5 { sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE '%a' } } {999 999 100} -do_test analyze3-2.4 { +do_test analyze3-2.6 { set like "a%" sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like } -} {101 0 100} -do_test analyze3-2.5 { +} {102 0 100} +do_test analyze3-2.7 { set like "%a" sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like } } {999 999 100} -do_test analyze3-2.6 { +do_test analyze3-2.8 { set like "a" sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like } -} {101 0 0} -do_test analyze3-2.7 { +} {102 0 0} +do_test analyze3-2.9 { set like "ab" sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like } -} {11 0 0} -do_test analyze3-2.8 { +} {12 0 0} +do_test analyze3-2.10 { set like "abc" sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like } -} {2 0 1} -do_test analyze3-2.9 { +} {3 0 1} +do_test analyze3-2.11 { set like "a_c" sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like } -} {101 0 10} +} {102 0 10} #------------------------------------------------------------------------- @@ -662,4 +666,30 @@ do_eqp_test analyze3-6-2 { SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13; } {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}} +#----------------------------------------------------------------------------- +# 2015-04-20. +# Memory leak in sqlite3Stat4ProbeFree(). (Discovered while fuzzing.) +# +do_execsql_test analyze-7.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + INSERT INTO t1 VALUES(1,1,'0000'); + CREATE INDEX t0b ON t1(b); + ANALYZE; + SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND hex(1); +} {} + +# At one point duplicate stat1 entries were causing a memory leak. +# +reset_db +do_execsql_test 7.2 { + CREATE TABLE t1(a,b,c); + CREATE INDEX t1a ON t1(a); + ANALYZE; + SELECT * FROM sqlite_stat1; + INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000'); + INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000'); + ANALYZE sqlite_master; +} + finish_test diff --git a/test/analyze9.test b/test/analyze9.test index 8572cbe..1ebd69c 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -1134,4 +1134,116 @@ ifcapable stat4&&cte { } } +#------------------------------------------------------------------------- +# Check that a problem in they way stat4 data is used has been +# resolved (see below). +# +reset_db +do_test 26.1.1 { + db transaction { + execsql { + CREATE TABLE t1(x, y, z); + CREATE INDEX t1xy ON t1(x, y); + CREATE INDEX t1z ON t1(z); + } + for {set i 0} {$i < 10000} {incr i} { + execsql { INSERT INTO t1(x, y) VALUES($i, $i) } + } + for {set i 0} {$i < 10} {incr i} { + execsql { + WITH cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt WHERE x<100) + INSERT INTO t1(x, y) SELECT 10000+$i, x FROM cnt; + INSERT INTO t1(x, y) SELECT 10000+$i, 100; + } + } + execsql { + UPDATE t1 SET z = rowid / 20; + ANALYZE; + } + } +} {} + +do_execsql_test 26.1.2 { + SELECT count(*) FROM t1 WHERE x = 10000 AND y < 50; +} {49} +do_execsql_test 26.1.3 { + SELECT count(*) FROM t1 WHERE z = 444; +} {20} + +# The analyzer knows that any (z=?) expression matches 20 rows. So it +# will use index "t1z" if the estimate of hits for (x=10000 AND y<50) +# is greater than 20 rows. +# +# And it should be. The analyzer has a stat4 sample as follows: +# +# sample=(x=10000, y=100) nLt=(10000 10099) +# +# There should be no other samples that start with (x=10000). So it knows +# that (x=10000 AND y<50) must match somewhere between 0 and 99 rows, but +# know more than that. Guessing less than 20 is therefore unreasonable. +# +# At one point though, due to a problem in whereKeyStats(), the planner was +# estimating that (x=10000 AND y<50) would match only 2 rows. +# +do_eqp_test 26.1.4 { + SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444; +} { + 0 0 0 {SEARCH TABLE t1 USING INDEX t1z (z=?)} +} + + +# This test - 26.2.* - tests that another manifestation of the same problem +# is no longer present in the library. Assuming: +# +# CREATE INDEX t1xy ON t1(x, y) +# +# and that have samples for index t1xy as follows: +# +# +# sample=('A', 70) nEq=(100, 2) nLt=(900, 970) +# sample=('B', 70) nEq=(100, 2) nLt=(1000, 1070) +# +# the planner should estimate that (x = 'B' AND y > 25) matches 76 rows +# (70 * 2/3 + 30). Before, due to the problem, the planner was estimating +# that this matched 100 rows. +# +reset_db +do_execsql_test 26.2.1 { + BEGIN; + CREATE TABLE t1(x, y, z); + CREATE INDEX i1 ON t1(x, y); + CREATE INDEX i2 ON t1(z); + + WITH + cnt(y) AS (SELECT 0 UNION ALL SELECT y+1 FROM cnt WHERE y<99), + letters(x) AS ( + SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D' + ) + INSERT INTO t1(x, y) SELECT x, y FROM letters, cnt; + + WITH + letters(x) AS ( + SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D' + ) + INSERT INTO t1(x, y) SELECT x, 70 FROM letters; + + WITH + cnt(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM cnt WHERE i<9999) + INSERT INTO t1(x, y) SELECT i, i FROM cnt; + + UPDATE t1 SET z = (rowid / 95); + ANALYZE; + COMMIT; +} + +do_eqp_test 26.2.2 { + SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?; +} { + 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)} +} + + finish_test + + + diff --git a/test/analyzeF.test b/test/analyzeF.test new file mode 100644 index 0000000..670d178 --- /dev/null +++ b/test/analyzeF.test @@ -0,0 +1,127 @@ +# 2015-03-12 +# +# 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. +# +#*********************************************************************** +# Test that deterministic scalar functions passed constant arguments +# are used with stat4 data. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix analyzeF + +ifcapable {!stat4} { + finish_test + return +} + +proc isqrt {i} { expr { int(sqrt($i)) } } +db func isqrt isqrt + +do_execsql_test 1.0 { + CREATE TABLE t1(x INTEGER, y INTEGER); + WITH data(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM data + ) + INSERT INTO t1 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400; + CREATE INDEX t1x ON t1(x); + CREATE INDEX t1y ON t1(y); + ANALYZE; +} + +proc str {a} { return $a } +db func str str + +# Note: tests 7 to 12 might be unstable - as they assume SQLite will +# prefer the expression to the right of the AND clause. Which of +# course could change. +# +# Note 2: tests 9 and 10 depend on the tcl interface creating functions +# without the SQLITE_DETERMINISTIC flag set. +# +foreach {tn where idx} { + 1 "x = 4 AND y = 19" {t1x (x=?)} + 2 "x = 19 AND y = 4" {t1y (y=?)} + 3 "x = '4' AND y = '19'" {t1x (x=?)} + 4 "x = '19' AND y = '4'" {t1y (y=?)} + 5 "x = substr('5195', 2, 2) AND y = substr('145', 2, 1)" {t1y (y=?)} + 6 "x = substr('145', 2, 1) AND y = substr('5195', 2, 2)" {t1x (x=?)} + + 7 "x = substr('5195', 2, 2+0) AND y = substr('145', 2, 1+0)" {t1y (y=?)} + 8 "x = substr('145', 2, 1+0) AND y = substr('5195', 2, 2+0)" {t1y (y=?)} + + 9 "x = str('19') AND y = str('4')" {t1y (y=?)} + 10 "x = str('4') AND y = str('19')" {t1y (y=?)} + + 11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)} + 12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)} +} { + set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}" + do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res +} + +# Test that functions that do not exist - "func()" - do not cause an error. +# +do_catchsql_test 2.1 { + SELECT * FROM t1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3) +} {1 {no such function: func}} +do_catchsql_test 2.2 { + UPDATE t1 SET y=y+1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3) +} {1 {no such function: func}} + + +# Check that functions that accept zero arguments do not cause problems. +# +proc ret {x} { return $x } + +db func det4 -deterministic [list ret 4] +db func nondet4 [list ret 4] +db func det19 -deterministic [list ret 19] +db func nondet19 [list ret 19] + +foreach {tn where idx} { + 1 "x = det4() AND y = det19()" {t1x (x=?)} + 2 "x = det19() AND y = det4()" {t1y (y=?)} + + 3 "x = nondet4() AND y = nondet19()" {t1y (y=?)} + 4 "x = nondet19() AND y = nondet4()" {t1y (y=?)} +} { + set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}" + do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res +} + + +execsql { DELETE FROM t1 } + +proc throw_error {err} { error $err } +db func error -deterministic throw_error +do_catchsql_test 4.1 { + SELECT * FROM t1 WHERE x = error('error one') AND y = 4; +} {1 {error one}} + +do_catchsql_test 4.2 { + SELECT * FROM t1 WHERE x = zeroblob(2000000000) AND y = 4; +} {1 {string or blob too big}} + +sqlite3_limit db SQLITE_LIMIT_LENGTH 1000000 +proc dstr {} { return [string repeat x 1100000] } +db func dstr -deterministic dstr +do_catchsql_test 4.3 { + SELECT * FROM t1 WHERE x = dstr() AND y = 11; +} {1 {string or blob too big}} + +do_catchsql_test 4.4 { + SELECT * FROM t1 WHERE x = test_zeroblob(1100000) AND y = 4; +} {1 {string or blob too big}} + + +finish_test + + + diff --git a/test/attach.test b/test/attach.test index be5f988..31c24e6 100644 --- a/test/attach.test +++ b/test/attach.test @@ -859,4 +859,16 @@ do_test attach-10.2 { }] 9 end } {4 noname {} 5 inmem {}} +# Attach with a very long URI filename. +# +db close +sqlite3 db test.db -uri 1 +do_execsql_test attach-11.1 { + ATTACH printf('file:%09000x/x.db?mode=memory&cache=shared',1) AS aux1; + CREATE TABLE aux1.t1(x,y); + INSERT INTO aux1.t1(x,y) VALUES(1,2),(3,4); + SELECT * FROM aux1.t1; +} {1 2 3 4} + + finish_test diff --git a/test/autoindex1.test b/test/autoindex1.test index bcde5bc..e2b8b15 100644 --- a/test/autoindex1.test +++ b/test/autoindex1.test @@ -11,6 +11,9 @@ # This file implements regression tests for SQLite library. The # focus of this script is testing automatic index creation logic. # +# EVIDENCE-OF: R-34271-33106 PRAGMA automatic_index; PRAGMA +# automatic_index = boolean; Query, set, or clear the automatic indexing +# capability. set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -509,5 +512,12 @@ do_execsql_test autoindex1-901 { WHERE t1.x IN (1,2,3); } {/USING AUTOMATIC COVERING INDEX/} +# 2015-04-15: A NULL CollSeq pointer in automatic index creation. +# +do_execsql_test autoindex1-920 { + CREATE TABLE t920(x); + INSERT INTO t920 VALUES(3),(4),(5); + SELECT * FROM t920,(SELECT 0 FROM t920),(VALUES(9)) WHERE 5 IN (x); +} {5 0 9 5 0 9 5 0 9} finish_test diff --git a/test/btree02.test b/test/btree02.test new file mode 100644 index 0000000..de7c06d --- /dev/null +++ b/test/btree02.test @@ -0,0 +1,52 @@ +# 2015-03-25 +# +# 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 making multiple calls to saveCursorPosition() +# and restoreCursorPosition() when cursors have eState==CURSOR_SKIPNEXT +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +load_static_extension db eval +do_execsql_test btree02-100 { + CREATE TABLE t1(a TEXT, ax INTEGER, b INT, PRIMARY KEY(a,ax)) WITHOUT ROWID; + WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10) + INSERT INTO t1(a,ax,b) SELECT printf('%02x',i), random(), i FROM c; + CREATE INDEX t1a ON t1(a); + CREATE TABLE t2(x,y); + CREATE TABLE t3(cnt); + WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<4) + INSERT INTO t3(cnt) SELECT i FROM c; + SELECT count(*) FROM t1; +} {10} +do_test btree02-110 { + db eval BEGIN + set i 0 + db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} { + db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)} + # puts "a,b,cnt = ($a,$b,$cnt)" + incr i + if {$i%2==1} { + set bx [expr {$b+1000}] + # puts "INSERT ($a),$bx" + db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)} + } else { + # puts "DELETE a=$a" + db eval {DELETE FROM t1 WHERE a=$a} + } + db eval {COMMIT; BEGIN} + } + db one {COMMIT; SELECT count(*) FROM t1;} +} {20} + +finish_test diff --git a/test/capi3.test b/test/capi3.test index 9f3d6f6..163bb19 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -452,9 +452,21 @@ proc check_data {STMT test types ints doubles strings} { # types do_test $test.1 { set types [list] - foreach i $idxlist {lappend types [sqlite3_column_type $STMT $i]} + foreach i $idxlist { + set x [sqlite3_column_type $STMT $i] + # EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five + # fundamental datatypes: 64-bit signed integer 64-bit IEEE floating + # point number string BLOB NULL + if {[lsearch {INTEGER FLOAT TEXT BLOB NULL} $x]<0} { + set types ERROR + break + } else { + lappend types $x + } + } set types } $types + # Integers do_test $test.2 { diff --git a/test/collate1.test b/test/collate1.test index 2085415..7cf5698 100644 --- a/test/collate1.test +++ b/test/collate1.test @@ -10,12 +10,12 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The -# focus of this script is page cache subsystem. +# focus of this script is testing collation sequences. # -# $Id: collate1.test,v 1.5 2007/02/01 23:02:46 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix collate1 # # Tests are roughly organised as follows: @@ -333,4 +333,72 @@ do_test collate1-5.3 { } } {1 2} + + +#------------------------------------------------------------------------- +# Fix problems with handling collation sequences named '"""'. +# +do_execsql_test 6.1 { + SELECT """"""""; +} {\"\"\"} + +do_catchsql_test 6.2 { + CREATE TABLE x1(a); + SELECT a FROM x1 ORDER BY a COLLATE """"""""; +} {1 {no such collation sequence: """}} + +do_catchsql_test 6.3 { + SELECT a FROM x1 ORDER BY 1 COLLATE """"""""; +} {1 {no such collation sequence: """}} + +do_catchsql_test 6.4 { + SELECT 0 UNION SELECT 0 ORDER BY 1 COLLATE """"""""; +} {1 {no such collation sequence: """}} + +db collate {"""} [list string compare -nocase] + +do_execsql_test 6.5 { + PRAGMA foreign_keys = ON; + CREATE TABLE p1(a PRIMARY KEY COLLATE '"""'); + CREATE TABLE c1(x, y REFERENCES p1); +} {} + +do_execsql_test 6.6 { + INSERT INTO p1 VALUES('abc'); + INSERT INTO c1 VALUES(1, 'ABC'); +} + +ifcapable foreignkey { + do_catchsql_test 6.7 { + DELETE FROM p1 WHERE rowid = 1 + } {1 {FOREIGN KEY constraint failed}} +} + +do_execsql_test 6.8 { + INSERT INTO p1 VALUES('abb'); + INSERT INTO p1 VALUES('wxz'); + INSERT INTO p1 VALUES('wxy'); + + INSERT INTO c1 VALUES(2, 'abb'); + INSERT INTO c1 VALUES(3, 'wxz'); + INSERT INTO c1 VALUES(4, 'WXY'); + SELECT x, y FROM c1 ORDER BY y COLLATE """"""""; +} {2 abb 1 ABC 4 WXY 3 wxz} + +# 2015-04-15: Nested COLLATE operators +# +do_execsql_test 7.0 { + SELECT 'abc' UNION ALL SELECT 'DEF' + ORDER BY 1 COLLATE nocase COLLATE nocase COLLATE nocase COLLATE nocase; +} {abc DEF} +do_execsql_test 7.1 { + SELECT 'abc' UNION ALL SELECT 'DEF' + ORDER BY 1 COLLATE nocase COLLATE nocase COLLATE nocase COLLATE binary; +} {DEF abc} +do_execsql_test 7.2 { + SELECT 'abc' UNION ALL SELECT 'DEF' + ORDER BY 1 COLLATE binary COLLATE binary COLLATE binary COLLATE nocase; +} {abc DEF} + + finish_test diff --git a/test/collate3.test b/test/collate3.test index 2c051cb..99640d0 100644 --- a/test/collate3.test +++ b/test/collate3.test @@ -32,7 +32,7 @@ source $testdir/tester.tcl # do_test collate3-1.0 { execsql { - CREATE TABLE collate3t1(c1); + CREATE TABLE collate3t1(c1 UNIQUE); } } {} do_test collate3-1.1 { @@ -40,6 +40,11 @@ do_test collate3-1.1 { SELECT * FROM collate3t1 ORDER BY 1 collate garbage; } } {1 {no such collation sequence: garbage}} +do_test collate3-1.1.2 { + catchsql { + SELECT DISTINCT c1 COLLATE garbage FROM collate3t1; + } +} {1 {no such collation sequence: garbage}} do_test collate3-1.2 { catchsql { CREATE TABLE collate3t2(c1 collate garbage); diff --git a/test/collate8.test b/test/collate8.test index 60a8916..b06c87d 100644 --- a/test/collate8.test +++ b/test/collate8.test @@ -13,7 +13,9 @@ # focus of this script is making sure collations pass through the # unary + operator. # -# $Id: collate8.test,v 1.2 2008/08/25 12:14:09 drh Exp $ +# 2015-02-09: Added tests to make sure COLLATE passes through function +# calls. Ticket [ca0d20b6cdddec5e81b8d66f89c46a5583b5f6f6]. +# set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -122,4 +124,34 @@ do_test collate8-2.8 { } } {abc} +# Make sure the COLLATE operator perculates up through function calls +# and other Expr structures that use the Expr.x.pList field. +# +do_execsql_test collate8-3.1 { + SELECT 'abc'==('ABC'||'') COLLATE nocase; + SELECT 'abc'==('ABC'||'' COLLATE nocase); + SELECT 'abc'==('ABC'||('' COLLATE nocase)); + SELECT 'abc'==('ABC'||upper('' COLLATE nocase)); +} {1 1 1 1} +do_execsql_test collate8-3.2 { + SELECT 'abc'==('ABC'||max('' COLLATE nocase,'' COLLATE binary)); +} {1} + +# The COLLATE binary is on the left and so takes precedence +do_execsql_test collate8-3.3 { + SELECT 'abc'==('ABC'||max('' COLLATE binary,'' COLLATE nocase)); +} {0} + +do_execsql_test collate8-3.4 { + SELECT 'abc'==('ABC'||CASE WHEN 1-1=2 THEN '' COLLATE nocase + ELSE '' COLLATE binary END); + SELECT 'abc'==('ABC'||CASE WHEN 1+1=2 THEN '' COLLATE nocase + ELSE '' COLLATE binary END); +} {1 1} +do_execsql_test collate8-3.5 { + SELECT 'abc'==('ABC'||CASE WHEN 1=2 THEN '' COLLATE binary + ELSE '' COLLATE nocase END); +} {0} + + finish_test diff --git a/test/corruptC.test b/test/corruptC.test index adf6f44..a7f93c4 100644 --- a/test/corruptC.test +++ b/test/corruptC.test @@ -292,7 +292,7 @@ do_test corruptC-2.15 { hexio_write test.db 986 b9 sqlite3 db test.db catchsql {SELECT count(*) FROM sqlite_master;} -} {1 {malformed database schema (t1i1) - no such table: main.t1}} +} {1 {database disk image is malformed}} # # Now test for a series of quasi-random seeds. diff --git a/test/corruptJ.test b/test/corruptJ.test new file mode 100644 index 0000000..c08e628 --- /dev/null +++ b/test/corruptJ.test @@ -0,0 +1,80 @@ +# 2015-03-30 +# +# 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. +# +#*********************************************************************** +# +# Corruption consisting of a database page that thinks it is a child +# of itself. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix corruptJ + +if {[permutation]=="mmap"} { + finish_test + return +} + +# Do not use a codec for tests in this file, as the database file is +# manipulated directly using tcl scripts (using the [hexio_write] command). +# +do_not_use_codec +database_may_be_corrupt + +# Initialize the database. +# +do_execsql_test 1.1 { + PRAGMA page_size=1024; + PRAGMA auto_vacuum=0; + CREATE TABLE t1(a,b); + WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10) + INSERT INTO t1(a,b) SELECT i, zeroblob(700) FROM c; +} {} +db close + +# Corrupt the root page of the t1 table such that the left-child pointer +# for the very first cell points back to the root. Then try to DROP the +# table. The clearDatabasePage() routine should not loop. +# +do_test 1.2 { + hexio_write test.db [expr {2*1024-2}] 02 + sqlite3 db test.db + catchsql { DROP TABLE t1 } +} {1 {database disk image is malformed}} + +# Similar test using a WITHOUT ROWID table +# +do_test 2.1 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + PRAGMA page_size=1024; + PRAGMA auto_vacuum=0; + CREATE TABLE t1(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID; + WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<100) + INSERT INTO t1(a,b) SELECT i, zeroblob(200) FROM c; + } +} {} + +# The table is three levels deep. Corrupt the left child of an intermediate +# page so that it points back to the root page. +# +do_test 2.2 { + db close + hexio_read test.db [expr {9*1024+391}] 8 +} {00000008814D0401} +do_test 2.2b { + hexio_write test.db [expr {9*1024+391}] 00000002 + sqlite3 db test.db + catchsql { PRAGMA secure_delete=ON; DROP TABLE t1; } +} {1 {database disk image is malformed}} + +finish_test diff --git a/test/count.test b/test/count.test index 3461e49..862b62a 100644 --- a/test/count.test +++ b/test/count.test @@ -191,4 +191,9 @@ do_execsql_test count-5.1 { SELECT count(*) FROM t5; } {1} +do_catchsql_test count-6.1 { + CREATE TABLE t6(x); + SELECT count(DISTINCT) FROM t6 GROUP BY x; +} {1 {DISTINCT aggregates must have exactly one argument}} + finish_test diff --git a/test/crashM.test b/test/crashM.test new file mode 100644 index 0000000..de10c45 --- /dev/null +++ b/test/crashM.test @@ -0,0 +1,80 @@ +# 2015 Mar 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. +# +#*********************************************************************** +# +# Crash tests for the multiplex module with 8.3 filenames enabled. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix crashM + +ifcapable !crashtest||!8_3_names { + finish_test + return +} + +db close +sqlite3_shutdown +sqlite3_config_uri 1 + +foreach f [glob -nocomplain test1.* test2.*] { forcedelete $f } +sqlite3_multiplex_initialize "" 1 +sqlite3 db file:test1.db?8_3_names=1 +sqlite3_multiplex_control db main chunk_size [expr 64*1024] + +do_execsql_test 1.0 { + ATTACH 'file:test2.db?8_3_names=1' AS aux; + + CREATE TABLE t1(x, y); + CREATE INDEX t1x ON t1(x); + CREATE INDEX t1y ON t1(y); + + CREATE TABLE aux.t2(x, y); + CREATE INDEX aux.t2x ON t2(x); + CREATE INDEX aux.t2y ON t2(y); + + WITH s(a) AS ( + SELECT 1 UNION ALL SELECT a+1 FROM s WHERE a<1000 + ) + INSERT INTO t1 SELECT a, randomblob(500) FROM s; + + WITH s(a) AS ( + SELECT 1 UNION ALL SELECT a+1 FROM s WHERE a<1000 + ) + INSERT INTO t2 SELECT a, randomblob(500) FROM s; +} {} + +for {set i 0} {$i < 20} {incr i} { + do_test 2.$i.1 { + crashsql -delay 1 -file test1.db -opendb { + sqlite3_shutdown + sqlite3_config_uri 1 + sqlite3_multiplex_initialize crash 1 + sqlite3 db file:test1.db?8_3_names=1 + sqlite3_multiplex_control db main chunk_size [expr 64*1024] + } { + ATTACH 'file:test2.db?8_3_names=1' AS aux; + BEGIN; + UPDATE t1 SET y = randomblob(500) WHERE (x%10)==0; + UPDATE t2 SET y = randomblob(500) WHERE (x%10)==0; + COMMIT; + } + } {1 {child process exited abnormally}} + + do_execsql_test 2.$i.2 { + PRAGMA main.integrity_check; + PRAGMA aux.integrity_check; + } {ok ok} +} + +catch { db close } +sqlite3_multiplex_shutdown +finish_test diff --git a/test/e_insert.test b/test/e_insert.test index 0ea4b76..ffafa0e 100644 --- a/test/e_insert.test +++ b/test/e_insert.test @@ -348,9 +348,9 @@ do_insert_tests e_insert-3.2 { 6.2 "SELECT * FROM a1" {{} {} {} {}} } -# EVIDENCE-OF: R-46928-50290 The optional conflict-clause allows the -# specification of an alternative constraint conflict resolution -# algorithm to use during this one INSERT command. +# EVIDENCE-OF: R-03235-45250 The "REPLACE" and "INSERT OR action" forms +# specify an alternative constraint conflict resolution algorithm to use +# during this one INSERT command. # # EVIDENCE-OF: R-23110-47146 the parser allows the use of the single # keyword REPLACE as an alias for "INSERT OR REPLACE". diff --git a/test/e_reindex.test b/test/e_reindex.test index 4b86787..fa66aa7 100644 --- a/test/e_reindex.test +++ b/test/e_reindex.test @@ -48,8 +48,11 @@ do_execsql_test e_reindex-1.1 { INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); + + CREATE TABLE saved(a,b,c,d,e); + INSERT INTO saved SELECT * FROM sqlite_master WHERE type = 'index'; PRAGMA writable_schema = 1; - UPDATE sqlite_master SET sql = '-- ' || sql WHERE type = 'index'; + DELETE FROM sqlite_master WHERE type = 'index'; } {} db close @@ -59,7 +62,8 @@ do_execsql_test e_reindex-1.2 { INSERT INTO t1 VALUES(7, 8); INSERT INTO t1 VALUES(9, 10); PRAGMA writable_schema = 1; - UPDATE sqlite_master SET sql = substr(sql, 4) WHERE type = 'index'; + INSERT INTO sqlite_master SELECT * FROM saved; + DROP TABLE saved; } {} db close diff --git a/test/e_wal.test b/test/e_wal.test index a5e074f..77ac83a 100644 --- a/test/e_wal.test +++ b/test/e_wal.test @@ -200,10 +200,11 @@ do_test 3.4.2 { db close -# EVIDENCE-OF: R-22428-28959 To prevent older versions of SQLite from -# trying to recover a WAL-mode database (and making matters worse) the -# database file format version numbers (bytes 18 and 19 in the database -# header) are increased from 1 to 2 in WAL mode. +# EVIDENCE-OF: R-45540-25505 To prevent older versions of SQLite (prior +# to version 3.7.0, 2010-07-22) from trying to recover a WAL-mode +# database (and making matters worse) the database file format version +# numbers (bytes 18 and 19 in the database header) are increased from 1 +# to 2 in WAL mode. # reset_db do_execsql_test 4.1.1 { CREATE TABLE t1(x, y) } diff --git a/test/e_walauto.test b/test/e_walauto.test index b624b24..a1f4eb7 100644 --- a/test/e_walauto.test +++ b/test/e_walauto.test @@ -15,6 +15,14 @@ source $testdir/tester.tcl source $testdir/wal_common.tcl set testprefix e_walauto +# Do not run this test on OpenBSD, as it depends on read() and mmap both +# accessing the same coherent view of the "test.db-shm" file. This doesn't +# work on OpenBSD. +# +if {$tcl_platform(os) == "OpenBSD"} { + finish_test + return +} proc read_nbackfill {} { seek $::shmfd 96 diff --git a/test/expr.test b/test/expr.test index 8d913d2..7d7b8ce 100644 --- a/test/expr.test +++ b/test/expr.test @@ -943,5 +943,13 @@ do_realnum_test expr-13.7 { } } {9.22337203685478e+18} +do_execsql_test expr-13.8 { + SELECT "" <= ''; +} {1} +do_execsql_test expr-13.9 { + SELECT '' <= ""; +} {1} + + finish_test diff --git a/test/fkey1.test b/test/fkey1.test index 90a4c44..0bd4939 100644 --- a/test/fkey1.test +++ b/test/fkey1.test @@ -121,4 +121,34 @@ do_test fkey1-3.5 { sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 } {0 0 0} +# Stress the dequoting logic. The first test is not so bad. +do_execsql_test fkey1-4.0 { + PRAGMA foreign_keys=ON; + CREATE TABLE "xx1"("xx2" TEXT PRIMARY KEY, "xx3" TEXT); + INSERT INTO "xx1"("xx2","xx3") VALUES('abc','def'); + CREATE TABLE "xx4"("xx5" TEXT REFERENCES "xx1" ON DELETE CASCADE); + INSERT INTO "xx4"("xx5") VALUES('abc'); + INSERT INTO "xx1"("xx2","xx3") VALUES('uvw','xyz'); + SELECT 1, "xx5" FROM "xx4"; + DELETE FROM "xx1"; + SELECT 2, "xx5" FROM "xx4"; +} {1 abc} + +# This case is identical to the previous except the "xx" in each name +# is changed to a single escaped double-quote character. +do_execsql_test fkey1-4.1 { + PRAGMA foreign_keys=ON; + CREATE TABLE """1"("""2" TEXT PRIMARY KEY, """3" TEXT); + INSERT INTO """1"("""2","""3") VALUES('abc','def'); + CREATE TABLE """4"("""5" TEXT REFERENCES """1" ON DELETE CASCADE); + INSERT INTO """4"("""5") VALUES('abc'); + INSERT INTO """1"("""2","""3") VALUES('uvw','xyz'); + SELECT 1, """5" FROM """4"; + DELETE FROM """1"; + SELECT 2, """5" FROM """4"; +} {1 abc} +do_execsql_test fkey1-4.2 { + PRAGMA table_info="""1"; +} {0 {"2} TEXT 0 {} 1 1 {"3} TEXT 0 {} 0} + finish_test diff --git a/test/fkey2.test b/test/fkey2.test index 53b90dc..aec75ed 100644 --- a/test/fkey2.test +++ b/test/fkey2.test @@ -676,6 +676,11 @@ do_test fkey2-9.2.3 { SELECT * FROM cc; } } {{} A {} {} B {} 3 A 2 3 B 2} +do_execsql_test fkey2-9.3.0 { + CREATE TABLE t3(x PRIMARY KEY REFERENCES t3 ON DELETE SET NULL); + INSERT INTO t3(x) VALUES(12345); + DROP TABLE t3; +} {} #------------------------------------------------------------------------- # The following tests, fkey2-10.*, test "foreign key mismatch" and @@ -746,10 +751,10 @@ do_test fkey2-10.2.2 { drop_all_tables do_test fkey2-11.1.1 { execsql { - CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, rowid, _rowid_, oid); CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE); - INSERT INTO t1 VALUES(10, 100); + INSERT INTO t1 VALUES(10, 100, 'abc', 'def', 'ghi'); INSERT INTO t2 VALUES(10, 100); UPDATE t1 SET a = 15; SELECT * FROM t2; @@ -2014,4 +2019,18 @@ do_test fkey2-ce7c13.1.6 { } } {1 {FOREIGN KEY constraint failed}} +# 2015-04-16: Foreign key errors propagate back up to the parser. +# +do_test fkey2-20150416-100 { + db close + sqlite3 db :memory: + catchsql { + PRAGMA foreign_keys=1; + CREATE TABLE t1(x PRIMARY KEY); + CREATE TABLE t(y REFERENCES t0(x)ON DELETE SET DEFAULT); + CREATE TABLE t0(y REFERENCES t1 ON DELETE SET NULL); + REPLACE INTO t1 SELECT(0);CREATE TABLE t2(x);CREATE TABLE t3; + } +} {1 {foreign key mismatch - "t" referencing "t0"}} + finish_test diff --git a/test/fkey5.test b/test/fkey5.test index dc866cb..21feb2b 100644 --- a/test/fkey5.test +++ b/test/fkey5.test @@ -12,8 +12,13 @@ # # This file tests the PRAGMA foreign_key_check command. # -# EVIDENCE-OF: R-05426-18119 PRAGMA foreign_key_check; PRAGMA -# foreign_key_check(table-name); +# EVIDENCE-OF: R-01427-50262 PRAGMA database.foreign_key_check; PRAGMA +# database.foreign_key_check(table-name); +# +# EVIDENCE-OF: R-23918-17301 The foreign_key_check pragma checks the +# database, or the table called "table-name", for foreign key +# constraints that are violated and returns one row of output for each +# violation. set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -74,6 +79,16 @@ do_test fkey5-1.2 { PRAGMA foreign_key_check; } } {c1 87 p1 0 c1 90 p1 0} +do_test fkey5-1.2b { + db eval { + PRAGMA main.foreign_key_check; + } +} {c1 87 p1 0 c1 90 p1 0} +do_test fkey5-1.2c { + db eval { + PRAGMA temp.foreign_key_check; + } +} {} do_test fkey5-1.3 { db eval { PRAGMA foreign_key_check(c1); @@ -84,6 +99,16 @@ do_test fkey5-1.4 { PRAGMA foreign_key_check(c2); } } {} +do_test fkey5-1.5 { + db eval { + PRAGMA main.foreign_key_check(c2); + } +} {} +do_test fkey5-1.6 { + catchsql { + PRAGMA temp.foreign_key_check(c2); + } +} {1 {no such table: temp.c2}} # EVIDENCE-OF: R-45728-08709 There are four columns in each result row. # diff --git a/test/fts3aa.test b/test/fts3aa.test index 6ff384a..08d825d 100644 --- a/test/fts3aa.test +++ b/test/fts3aa.test @@ -16,6 +16,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix fts3aa # If SQLITE_ENABLE_FTS3 is defined, omit this file. ifcapable !fts3 { @@ -221,5 +222,26 @@ do_catchsql_test fts3aa-7.5 { CREATE VIRTUAL TABLE t4 USING fts4(tokenize=simple, tokenize=simple); } {1 {unrecognized parameter: tokenize=simple}} +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE t0 USING fts4(order=desc); + BEGIN; + INSERT INTO t0(rowid, content) VALUES(1, 'abc'); + UPDATE t0 SET docid=5 WHERE docid=1; + INSERT INTO t0(rowid, content) VALUES(6, 'abc'); +} +do_execsql_test 8.1 { + SELECT docid FROM t0 WHERE t0 MATCH 'abc'; +} {6 5} +do_execsql_test 8.2 { + SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"'; +} {} +do_execsql_test 8.3 { COMMIT } +do_execsql_test 8.4 { + SELECT docid FROM t0 WHERE t0 MATCH 'abc'; +} {6 5} +do_execsql_test 8.5 { + SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"'; +} {} + finish_test diff --git a/test/fts3atoken.test b/test/fts3atoken.test index b7722c7..88e3d4f 100644 --- a/test/fts3atoken.test +++ b/test/fts3atoken.test @@ -186,10 +186,32 @@ ifcapable icu { } {} } - do_test fts3token-internal { execsql { SELECT fts3_tokenizer_internal_test() } } {ok} +#------------------------------------------------------------------------- +# Test empty tokenizer names. +# +do_catchsql_test 6.1.1 { + CREATE VIRTUAL TABLE t3 USING fts4(tokenize=""); +} {1 {unknown tokenizer: }} +do_catchsql_test 6.1.2 { + CREATE VIRTUAL TABLE t3 USING fts4(tokenize=); +} {1 {unknown tokenizer: }} +do_catchsql_test 6.1.3 { + CREATE VIRTUAL TABLE t3 USING fts4(tokenize=" "); +} {1 {unknown tokenizer: }} + +do_catchsql_test 6.2.1 { + SELECT fts3_tokenizer(NULL); +} {1 {unknown tokenizer: }} +do_catchsql_test 6.2.2 { + SELECT fts3_tokenizer(NULL, X'1234567812345678'); +} {1 {argument type mismatch}} +do_catchsql_test 6.2.3 { + SELECT fts3_tokenizer(NULL, X'12345678'); +} {1 {argument type mismatch}} + finish_test diff --git a/test/fts3expr5.test b/test/fts3expr5.test new file mode 100644 index 0000000..1e09851 --- /dev/null +++ b/test/fts3expr5.test @@ -0,0 +1,48 @@ +# 2006 September 9 +# +# 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 FTS3 module. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix fts3expr5 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts3 { + finish_test + return +} + +#------------------------------------------------------------------------- +# Various forms of empty phrase expressions. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t0 USING fts3(x); + SELECT rowid FROM t0 WHERE x MATCH ''; +} {} +do_execsql_test 1.1 { + SELECT rowid FROM t0 WHERE x MATCH '""'; +} {} +do_execsql_test 1.2 { + SELECT rowid FROM t0 WHERE x MATCH '"" ""'; +} {} +do_execsql_test 1.3 { + SELECT rowid FROM t0 WHERE x MATCH '"" OR ""'; +} {} +do_execsql_test 1.4 { + SELECT rowid FROM t0 WHERE x MATCH '"" NOT ""'; +} {} +do_execsql_test 1.5 { + SELECT rowid FROM t0 WHERE x MATCH '""""'; +} {} + +finish_test diff --git a/test/fts3fault2.test b/test/fts3fault2.test index f2d10bc..030ff73 100644 --- a/test/fts3fault2.test +++ b/test/fts3fault2.test @@ -155,4 +155,23 @@ ifcapable fts3_unicode { } } +reset_db +do_test 6.0 { + execsql { + CREATE VIRTUAL TABLE t6 USING fts4(x,order=DESC); + INSERT INTO t6(docid, x) VALUES(-1,'a b'); + INSERT INTO t6(docid, x) VALUES(1, 'b'); + } + faultsim_save_and_close +} {} + +do_faultsim_test 6.1 -faults oom* -prep { + faultsim_restore_and_reopen + db eval {SELECT * FROM sqlite_master} +} -body { + execsql { SELECT docid FROM t6 WHERE t6 MATCH '"a* b"' } +} -test { + faultsim_test_result {0 -1} +} + finish_test diff --git a/test/fts3matchinfo.test b/test/fts3matchinfo.test index 36c9121..2681d00 100644 --- a/test/fts3matchinfo.test +++ b/test/fts3matchinfo.test @@ -449,5 +449,68 @@ do_execsql_test 10.1 { ORDER BY 1; } {1 1 one 2 2 two 3 3 three} +#--------------------------------------------------------------------------- +# Test the 'y' matchinfo flag +# +set sqlite_fts3_enable_parentheses 1 +reset_db +do_execsql_test 11.0 { + CREATE VIRTUAL TABLE tt USING fts3(x, y); + INSERT INTO tt VALUES('c d a c d d', 'e a g b d a'); -- 1 + INSERT INTO tt VALUES('c c g a e b', 'c g d g e c'); -- 2 + INSERT INTO tt VALUES('b e f d e g', 'b a c b c g'); -- 3 + INSERT INTO tt VALUES('a c f f g d', 'd b f d e g'); -- 4 + INSERT INTO tt VALUES('g a c f c f', 'd g g b c c'); -- 5 + INSERT INTO tt VALUES('g a c e b b', 'd b f b g g'); -- 6 + INSERT INTO tt VALUES('f d a a f c', 'e e a d c f'); -- 7 + INSERT INTO tt VALUES('a c b b g f', 'a b a e d f'); -- 8 + INSERT INTO tt VALUES('b a f e c c', 'f d b b a b'); -- 9 + INSERT INTO tt VALUES('f d c e a c', 'f a f a a f'); -- 10 +} + +db func mit mit +foreach {tn expr res} { + 1 "a" { + 1 {1 2} 2 {1 0} 3 {0 1} 4 {1 0} 5 {1 0} + 6 {1 0} 7 {2 1} 8 {1 2} 9 {1 1} 10 {1 3} + } + + 2 "b" { + 1 {0 1} 2 {1 0} 3 {1 2} 4 {0 1} 5 {0 1} + 6 {2 2} 8 {2 1} 9 {1 3} + } + + 3 "y:a" { + 1 {0 2} 3 {0 1} + 7 {0 1} 8 {0 2} 9 {0 1} 10 {0 3} + } + + 4 "x:a" { + 1 {1 0} 2 {1 0} 4 {1 0} 5 {1 0} + 6 {1 0} 7 {2 0} 8 {1 0} 9 {1 0} 10 {1 0} + } + + 5 "a OR b" { + 1 {1 2 0 1} 2 {1 0 1 0} 3 {0 1 1 2} 4 {1 0 0 1} 5 {1 0 0 1} + 6 {1 0 2 2} 7 {2 1 0 0} 8 {1 2 2 1} 9 {1 1 1 3} 10 {1 3 0 0} + } + + 6 "a AND b" { + 1 {1 2 0 1} 2 {1 0 1 0} 3 {0 1 1 2} 4 {1 0 0 1} 5 {1 0 0 1} + 6 {1 0 2 2} 8 {1 2 2 1} 9 {1 1 1 3} + } + + 7 "a OR (a AND b)" { + 1 {1 2 1 2 0 1} 2 {1 0 1 0 1 0} 3 {0 1 0 1 1 2} 4 {1 0 1 0 0 1} + 5 {1 0 1 0 0 1} 6 {1 0 1 0 2 2} 7 {2 1 0 0 0 0} 8 {1 2 1 2 2 1} + 9 {1 1 1 1 1 3} 10 {1 3 0 0 0 0} + } + +} { + do_execsql_test 11.1.$tn { + SELECT rowid, mit(matchinfo(tt, 'y')) FROM tt WHERE tt MATCH $expr + } $res +} +set sqlite_fts3_enable_parentheses 0 finish_test diff --git a/test/fts3prefix.test b/test/fts3prefix.test index e7c197d..e8d2b2b 100644 --- a/test/fts3prefix.test +++ b/test/fts3prefix.test @@ -209,5 +209,87 @@ do_catchsql_test 5.1 { do_catchsql_test 5.2 { CREATE VIRTUAL TABLE t4 USING fts4(prefix=""); } {0 {}} +do_catchsql_test 5.3 { + CREATE VIRTUAL TABLE t5 USING fts4(prefix="-1"); +} {1 {error parsing prefix parameter: -1}} + +#------------------------------------------------------------------------- +# Prefix indexes of size 0 are ignored. Demonstrate this by showing that +# adding prefix=0 does not change the contents of the %_segdir table. +# +reset_db +do_execsql_test 6.1.1 { + CREATE VIRTUAL TABLE t1 USING fts4(prefix=0); + CREATE VIRTUAL TABLE t2 USING fts4; + INSERT INTO t1 VALUES('Twas Mulga Bill, from Eaglehawk, '); + INSERT INTO t2 VALUES('Twas Mulga Bill, from Eaglehawk, '); +} {} +do_execsql_test 6.1.2 { + SELECT md5sum(quote(root)) FROM t1_segdir; +} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}] + +reset_db +do_execsql_test 6.2.1 { + CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,0,2"); + CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2"); + INSERT INTO t1 VALUES('that caught the cycling craze;'); + INSERT INTO t2 VALUES('that caught the cycling craze;'); +} {} +do_execsql_test 6.2.2 { + SELECT md5sum(quote(root)) FROM t1_segdir; +} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}] + +reset_db +do_execsql_test 6.3.1 { + CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,3,2"); + CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2"); + INSERT INTO t1 VALUES('He turned away the good old horse'); + INSERT INTO t2 VALUES('He turned away the good old horse'); +} {} +do_test 6.3.2 { + set one [db eval {SELECT md5sum(quote(root)) FROM t1_segdir}] + set two [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}] + expr {$one == $two} +} 0 + +reset_db +do_execsql_test 6.4.1 { + CREATE VIRTUAL TABLE t1 USING fts4(prefix="1,600,2"); + CREATE VIRTUAL TABLE t2 USING fts4(prefix="1,2"); + INSERT INTO t1 VALUES('that served him many days;'); + INSERT INTO t2 VALUES('that served him many days;'); +} {} +do_execsql_test 6.4.2 { + SELECT md5sum(quote(root)) FROM t1_segdir; +} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}] + +reset_db +do_execsql_test 6.5.1 { + CREATE VIRTUAL TABLE t1 USING fts4(prefix="2147483647,2147483648,2147483649"); + CREATE VIRTUAL TABLE t2 USING fts4(prefix=); + INSERT INTO t1 VALUES('He dressed himself in cycling clothes'); + INSERT INTO t2 VALUES('He dressed himself in cycling clothes'); +} {} +do_execsql_test 6.5.2 { + SELECT md5sum(quote(root)) FROM t1_segdir; +} [db eval {SELECT md5sum(quote(root)) FROM t2_segdir}] + + +do_execsql_test 7.0 { + CREATE VIRTUAL TABLE t6 USING fts4(x,order=DESC); + INSERT INTO t6(docid, x) VALUES(-1,'a b'); + INSERT INTO t6(docid, x) VALUES(1, 'b'); +} +do_execsql_test 7.1 { + SELECT docid FROM t6 WHERE t6 MATCH '"a* b"'; +} {-1} +do_execsql_test 7.2 { + SELECT docid FROM t6 WHERE t6 MATCH 'a*'; +} {-1} +do_execsql_test 7.3 { + SELECT docid FROM t6 WHERE t6 MATCH 'a* b'; +} {-1} + + finish_test diff --git a/test/fts3query.test b/test/fts3query.test index 2d12351..06019d1 100644 --- a/test/fts3query.test +++ b/test/fts3query.test @@ -208,5 +208,81 @@ do_select_tests 6.2 { {{ZZZthe hand XXXgesturesYYY (called beatsZZZ}} } +# Test some range queries on the rowid field. +# +do_execsql_test 7.1 { + CREATE VIRTUAL TABLE ft4 USING fts4(x); + CREATE TABLE t4(x); +} + +set SMALLINT -9223372036854775808 +set LARGEINT 9223372036854775807 +do_test 7.2 { + db transaction { + foreach {iFirst nEntry} [subst { + 0 100 + $SMALLINT 100 + [expr $LARGEINT - 99] 100 + }] { + for {set i 0} {$i < $nEntry} {incr i} { + set iRowid [expr $i + $iFirst] + execsql { + INSERT INTO ft4(rowid, x) VALUES($iRowid, 'x y z'); + INSERT INTO t4(rowid, x) VALUES($iRowid, 'x y z'); + } + } + } + } +} {} + +foreach {tn iFirst iLast} [subst { + 1 5 10 + 2 $SMALLINT [expr $SMALLINT+5] + 3 $SMALLINT [expr $SMALLINT+50] + 4 [expr $LARGEINT-5] $LARGEINT + 5 $LARGEINT $LARGEINT + 6 $SMALLINT $LARGEINT + 7 $SMALLINT $SMALLINT + 8 $LARGEINT $SMALLINT +}] { + set res [db eval { + SELECT rowid FROM t4 WHERE rowid BETWEEN $iFirst AND $iLast + } ] + + do_execsql_test 7.2.$tn.1.[llength $res] { + SELECT rowid FROM ft4 WHERE rowid BETWEEN $iFirst AND $iLast + } $res + set res [db eval { + SELECT rowid FROM t4 WHERE rowid BETWEEN $iFirst AND $iLast + ORDER BY +rowid DESC + } ] + do_execsql_test 7.2.$tn.2.[llength $res] { + SELECT rowid FROM ft4 WHERE rowid BETWEEN $iFirst AND $iLast + ORDER BY rowid DESC + } $res +} + +foreach ii [db eval {SELECT rowid FROM t4}] { + set res1 [db eval {SELECT rowid FROM t4 WHERE rowid > $ii}] + set res2 [db eval {SELECT rowid FROM t4 WHERE rowid < $ii}] + set res1s [db eval {SELECT rowid FROM t4 WHERE rowid > $ii ORDER BY +rowid DESC}] + set res2s [db eval {SELECT rowid FROM t4 WHERE rowid < $ii ORDER BY +rowid DESC}] + + do_execsql_test 7.3.$ii.1 { + SELECT rowid FROM ft4 WHERE rowid > $ii + } $res1 + + do_execsql_test 7.3.$ii.2 { + SELECT rowid FROM ft4 WHERE rowid < $ii + } $res2 + + do_execsql_test 7.3.$ii.3 { + SELECT rowid FROM ft4 WHERE rowid > $ii ORDER BY rowid DESC + } $res1s + + do_execsql_test 7.3.$ii.4 { + SELECT rowid FROM ft4 WHERE rowid < $ii ORDER BY rowid DESC + } $res2s +} finish_test diff --git a/test/fts3snippet.test b/test/fts3snippet.test index 415251d..4e1d123 100644 --- a/test/fts3snippet.test +++ b/test/fts3snippet.test @@ -520,5 +520,43 @@ do_execsql_test 2.6 { {[one] two three [four] five} } +#------------------------------------------------------------------------- +do_execsql_test 3 { + CREATE VIRTUAL TABLE t3 USING fts4; + INSERT INTO t3 VALUES('[one two three]'); +} +do_execsql_test 3.1 { + SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one'; +} {{[one two three]}} +do_execsql_test 3.2 { + SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'two'; +} {{[one two three]}} +do_execsql_test 3.3 { + SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'three'; +} {{[one two three]}} +do_execsql_test 3.4 { + SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'one OR two OR three'; +} {{[one two three]}} + +#------------------------------------------------------------------------- +# Request a snippet 0 tokens in size. This is always an empty string. +do_execsql_test 4.1 { + CREATE VIRTUAL TABLE t4 USING fts4; + INSERT INTO t4 VALUES('a b c d'); + SELECT snippet(t4, '[', ']', '...', 0, 0) FROM t4 WHERE t4 MATCH 'b'; +} {{}} + +do_test 4.2 { + set x35 [string trim [string repeat "x " 35]] + execsql "INSERT INTO t4 VALUES('$x35 E $x35 F $x35 G $x35');" + llength [db one { + SELECT snippet(t4, '', '', '', 0, 64) FROM t4 WHERE t4 MATCH 'E' + }] +} {64} + + + + set sqlite_fts3_enable_parentheses 0 finish_test + diff --git a/test/fts3tok1.test b/test/fts3tok1.test index e6fbbe1..09b07e9 100644 --- a/test/fts3tok1.test +++ b/test/fts3tok1.test @@ -110,5 +110,15 @@ do_catchsql_test 2.1 { SELECT * FROM t4; } {1 {SQL logic error or missing database}} +do_catchsql_test 2.2 { + CREATE VIRTUAL TABLE t USING fts4(tokenize=simple""); +} {0 {}} + +ifcapable fts3_unicode { + do_catchsql_test 2.3 { + CREATE VIRTUAL TABLE u USING fts4(tokenize=unicode61""); + } {1 {unknown tokenizer}} +} + finish_test diff --git a/test/fts4check.test b/test/fts4check.test index c98886c..4ded053 100644 --- a/test/fts4check.test +++ b/test/fts4check.test @@ -179,5 +179,35 @@ do_test 4.2 { } {1 {database disk image is malformed}} reset_db +#-------------------------------------------------------------------------- +# Test case 5.* +# +# Test that the integrity-check works if there is uncommitted data. +# +do_execsql_test 5.0 { + BEGIN; + CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3"); + INSERT INTO t5 VALUES('And down by Kosiosko, where the reed-banks sweep'); + INSERT INTO t5 VALUES('and sway, and the rolling plains are wide, the'); + INSERT INTO t5 VALUES('man from snowy river is a household name today,'); + INSERT INTO t5 VALUES('and the stockmen tell the story of his ride'); +} + +do_execsql_test 5.1 { + INSERT INTO t5(t5) VALUES('integrity-check'); +} {} + +do_catchsql_test 5.2 { + INSERT INTO t5_content VALUES(5, 'his hardy mountain pony'); + INSERT INTO t5(t5) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +do_execsql_test 5.3 ROLLBACK + +do_execsql_test 5.4 { + CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3"); + INSERT INTO t5(t5) VALUES('integrity-check'); +} {} + finish_test diff --git a/test/fts4content.test b/test/fts4content.test index 6b2cd3c..481c6ec 100644 --- a/test/fts4content.test +++ b/test/fts4content.test @@ -48,6 +48,9 @@ ifcapable !fts3 { # # 9.* - Test using content=xxx where xxx is a virtual table. # +# 11.* - Test that circular references (e.g. "t1(content=t1)") are +# detected. +# do_execsql_test 1.1.1 { CREATE TABLE t1(a, b, c); @@ -406,7 +409,7 @@ do_execsql_test 5.1.7 { # do_catchsql_test 6.1.1 { CREATE VIRTUAL TABLE ft7 USING fts4(content=t7); -} {1 {vtable constructor failed: ft7}} +} {1 {no such table: main.t7}} do_execsql_test 6.2.1 { CREATE TABLE t7(one, two); @@ -433,7 +436,7 @@ do_execsql_test 6.2.3 { } do_catchsql_test 6.2.4 { SELECT * FROM ft7; -} {1 {vtable constructor failed: ft7}} +} {1 {no such table: main.t7}} do_execsql_test 6.2.5 { CREATE TABLE t7(x, y); INSERT INTO t7 VALUES('A B', 'B A'); @@ -622,4 +625,15 @@ do_execsql_test 10.7 { {...c d [e] f g...} } +#------------------------------------------------------------------------- +# Test cases 11.* +# +reset_db + +do_catchsql_test 11.1 { + CREATE VIRTUAL TABLE x1 USING fts4(content=x1); +} {1 {vtable constructor called recursively: x1}} + + finish_test + diff --git a/test/fuzz2.test b/test/fuzz2.test index 4b3fb72..51dfce1 100644 --- a/test/fuzz2.test +++ b/test/fuzz2.test @@ -125,5 +125,15 @@ do_test fuzz2-6.4b { db eval {SELECT quote(t) FROM t0} } {NULL} +# Another test case discovered by Michal Zalewski, this on on 2015-01-22. +# Ticket 32b63d542433ca6757cd695aca42addf8ed67aa6 +# +do_test fuzz2-7.1 { + catchsql {select e.*,0 from(s,(L))e;} +} {1 {no such table: s}} +do_test fuzz2-7.2 { + catchsql {SELECT c.* FROM (a,b) AS c} +} {1 {no such table: a}} + finish_test diff --git a/test/fuzzdata1.txt b/test/fuzzdata1.txt new file mode 100644 index 0000000000000000000000000000000000000000..6d3b20c131ae1da52a4811289a8f7bb80d1fb197 GIT binary patch literal 2966109 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�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

&Oo%1ocnmlB6~=JI+xr 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

)JT`TZn4V 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 sFCr+&f&Urs0Xjim!LxY{{{;;^Z)<= literal 0 HcmV?d00001 diff --git a/test/fuzzdata2.txt b/test/fuzzdata2.txt new file mode 100644 index 0000000000000000000000000000000000000000..b1d4bb7bb1505fe63b7cdb1de598812f071335f5 GIT binary patch literal 15739506 zcmeFaeQadebthIW$zLVW7;TL8O7=R}r5Uk`EVAnri_NAu>}fW;dWI64>>-Qup;@V2 zBwzQ?Q>^M?6?=LnjhWWUl4WNldu1(zIIsajfs@Ds1RF;{0B?{4a54zsAb%Ln?jnd` zBv9n_8UYON8ir$-`JMaq?!E7$UVZSZyWUK*-n*aYo_p@O=bn4+xu0S;4&QmlKVUoc zw%=wut!C$7Z~L(0@3QT;+0DJ3*Xs@T`Fg{DtNq3vYc*N9m8qU>e~(c_42Kz&#qT*R5v!3uB}$Hd(F0g&|!PcP7AT@e!X$% zxAR_MA=~yFMu}djWE8qtU9B$H7-ReO2YIjP6)sM&iHj4tT#+^W=H1TgC?S`-bI{sn zd6uD~{GAS~R6L}m{|dz*yvD{n8Nf0bUTaPT?fjdSg)|Pwz9saYUZKy zyiS$nH0pGr>caHj%>SBokUD7BF{Ot@5sj8!Vn64lux=LK{uNG_Lq zmL1fayRH50Mr%7i6Mp(4ysi{F6rzj8+lgRW4#SASaJq0MQ$RVO0GY79-OjUVJ;v*e z##rVfsssCv9IubBuH0Oyjc<>$hu(s$EIKrzmJx70VD9KW$;s@_i$=B+8uYaj!F!-z z(ugXn!=gh)?;l?qLiIXKaV8iNnM{U>shXzD=e)gUp5?uHnoc1^v^bCS=J6DYkQ@#$ zE87v}`H~0GVQL16%&7U2Q-&ES3k+%y6$Ib2g%BgJ1TfnI$(ySywLkvj&X>Q;mNpIP z!%Fn+Z@-l?*|)#lrJQf$300<;2YzE>?OACyXbj8vb(wvNL0p4m*52{CNOUDv&t2hv za+O?8z1HcKVnkprx4QDVD#8$;UwP1Wjy=D+el7Rf7rziZQ&EA)EOYR3V{7QK*eO*i zL$Spi;K}7)exbSnXhj1)&wuIbU(thK-cA)wZB(%E=3U8sUxbP5>izB90##7#+;C_A zO97rUOygNen3YPof`>hP$fheqlaTv}51~shdQcWUmLaM#WSU26?>xj<>}^UlKbu-7~UGf7;f z5bK*@e6i8-^!gz=7JPkWv$nFfT+_7| zwLIQoUSWL=pMRkjMAP&0WmW)&e{6E9Qkk5bDp$P9BC25P8yut8u%I#v03q`t1j~Ua zch=-m4VYXrNU!RjZZEK52cb*TOZ9QQ)_#_zJd|d zNi%}jn}@BApC^`zr+TR}fgcY{)_Oc|c6OGh80^n8Iy=gnorSc~hq^%YDCrgEExke} zSn6QF7$ZomeN1J88j7U32na)rDxpKr6#R6hq7)Z7S+ku>=pG~q>TGCeQAlLE{0{Qz z4?%^B40X1c+6*8Qs&m?GBY|p%kcdF1fgI8lSuM4SS4mUM(~mO6Z2JTL{I2*3{_g%C z!F%Le0-7_KtD57FL5F}Ia;1o_Lxd)oR72$F4;y>XJ=EXMV_XQi12~hqGMa^g1VrAE z5u^d5NTYz@U6(mGH-~mGt~Q%ujn-TKff$);e9p}+R4PdI_wjFT9{OE>xpBL~pByha*g@}n` zLqyQSJ@m`ODbPYJ3Sv={zCn*Y64bEih7uZ;YBcImNSNmZ$Wd6KQBMOF1JdO?hLSaU zHO3cWspd$ncH;Aq`csl~9!*B{OqF;@SbN_~2o+?^bF-oj>{EGIK~I($Ch9g{mF46b>_6ARf zmonv`kNcbT`+og?FIk6C&N&3x#u@_xXT8O@{5G^d#4{gtizog{3wb;bBbK;^hWcXm zWd2K4O{zpLys0v!N@UM~hPFI2*=%p-)nH(U&Apx0uAk5Sd!-W3W-2R4@DD01S6Ilr z7m+fX<-I}i5wU%h6I0KRXD70syjiJyhFw{#d^vL=yO8-vCj0fHc*uB;?kV~%bA-JC zdL-LkUcU+34UmstSzq`{77vOO-IZ;3iN3|Dj^`B`Bb&wz9lKJaII=SrqO3o(Ea_LP z4I?-$6Vse~_Jod9nq#5zUl&Je_>y~wD;d>;Jdy5b6;IsudQtrR;w#(*Q>AW z?p>qcwRIlp7yk*;t*vjhwpL&Mo$6Wx7Nk1a-!)JOllz__6=vDc3}>FgR4j#~&fdPC ze=t5?V9E-CufLOw3e;xvQmwYM{K6Ib7imAB(tUP)Wi8m%HnySrD?k(_i;+J))E|`{ zyX>S`7;c$Ck+eU5A-9VFRfROI!1lYv(#i%+Wh@IKzRC{_dAtHQ?ER_irMQQ5zS8zL zNHQI~I&c1ty>OEBA@=1so6s9zQn@_@YvCS@S1)MRiv@_{!o7kV+elM)uLj2P*hJF= z*xQ3;a7sK0$d3a*>0#)@09q4Pl%a9Ciw1Nsvk&aGl3I?oTtfyR9&F+#T*HsW+%;jX zBuqjavk;1feaOqXz*0m6O~Hm_stnr^R>At06@pD>*q)#oOEZC>+&s7I;wJgnTw*Xp znXX(Bzyi|1CM6O8QJZD3(gp53lbtXDKRvV!6#NlwVWHr=L)FU}1DV#x0F!$-hmSK5oW23rOyIotkS>3EH z-Mm#`-&NLhY++$@>80u|h*mXLGe2%2O3h(`*+UOyNmkHTUIVDX;J8WIFKp26{KA5( z-!B_F%giJHPgHZcEX&5r<M?44e_q2c9#*B@*0{flNhFM?*OoDjqhM6Jw z>WwnUt2#%-K3Zzqc81JrK5`uQqCm}{LK ztoj2og)tna5K6wZwzMiT;v@1gQfyRjtu8HB_3_j`iXN=ANC0_YLb>t~tx_v;Gg|D8 zKg;(eD&CK(O`J$1QPFk zwOCcS6hkEc&>^3tHIYL#vbsU$hhN0Wxdbt1A0VM;_)iOU`D#Ml+0(q zUJ(o<>Tg1CJ45+QGWDMEm`LA4Y;hE>DQpmC9h>osAhrjru;ZrC-zF>vixTY``05{vFKB1JJh2t+f+Mv&Uu&R^xnh3fb3 z=9R_8bJ$ZX;@}EPh(j!+e_fKmF7^)BpLj*8;i@-xvbACT%BW&mc{#tliD-fu9FGgp zUhdCE9QXpHH{7A>vlBPI=(~`6gSzX^GG;Z z#7`#iS<5iwmIs!gZHNpc>sWc*$#|7Xbq*YN0&rrCJ0Q@Jsn{ne69GC5;3SYE{n8%v6Saq8j21X>jd;Ddl4$m3Ma+a>>mO$%p?U7<|9qx?tU!~#F`K3SrT zIDEN(C#M*8^(a&xZHRD1e>^IF8B*Q+mf*`aJ60D`_jInEy zc`9%t5t!W1V1uo{v;j9UnOGiEyO6 zzYVLljDe)#p-nrfiwE<>uy!0Ib39l}B5gV}VV~Pzvzj107vu-D>%Cw1atpnFiT>AZK0Sa3$Y2c0iH^@0MS<;v6z}B?@#7z z6}(SQ&QH=aK92tj#WwZ>aAxlE$KVJEUEE$-6K9#LI*QwpSWzfUIDX^{30XooS&9<; z1{)CYzN%%t0gmZgVa0B`5jy!U)DbT%y|l9SyaLH43S+NOEy-|DueqB?SCzc!Qt1** zdH7>F=D?tok;G&OmefOV6hnt~YPl1_1bk9ctKP@@H0ml*j+m^5Ap8g$rjru%2`Zx9_75zteS8g6kwe@q| z9VRis2@MvVMA162I1o!`SapZHj8rjT$=W%Y^k_YNthT;q6)ug?C>!J%V@uU?D|z7G zYt*?@$vI3rSCs$5=L(UE$??Nh?*lg5!GWQtk~>-{x7a>MM~WC7DPphHzwocgyH@a6Dl4^* zl4^^sVr;S5mZ?=7iDHITD8b3FVZT~k+N?71WkvUzo*Rl9rm&*Ipn_r7cM|Zy?3bhF zQ-q=g>kHL?oBbm!6&C{QUk*|jiOD$F_!R6WHe?^jB5fk87<*8#vQ^qp#*a+!>jSLi zE{^f@1*`nw>(yY>X5M3~?H?4_EuVycy?UX=FRQ+?T)kDZR?j@O+)GdeSJXC1vG>A^ zwX_4%zw8O7USW_t1*^0(iI(;cB#uRIod}F4Qc17GcHHzaq64AKGKTPI5M$5{gSU+a zF`e_mj4>L-!q?~tGV@;ftfo~>_ynvmCG$Py`5_lO6L{9)Kos$#{40F1O9uVxj) z^g}2jq+_Ez)c^b<0KU-VZ(M_o;8!43X<^H=qEr$)=bI`Rzs4&s8FtXKF~N2r+bZWt zRliylH4UMG!!1f(ZNQxxhRoh8#yZZtM?rf0=653$A#w_5v)4X-4Q5Jouh+FtZDF41K-d6#9J zWL;{MyPtFtTlsWVS!Ll9TtyNaDY!*ax!6U9n+L$LD7{l~*3narb+!<&+*I&r4wsxd zvE661X{vt&cyM(SwAFz)v2}@&PC?EmWgYdZFgoG%6+(t2*kG7xUdMN_v~5AgFn)-> zSfXN@?*xiVIwkTkcvGQ4N<*CF+q>ci0}c0ALZYBRc9q|qI`gxEYk!Kmxl~(z0a4oD zzZv)-Z#uxYV?4TvHLf(Bkyk&wI?#~j0sc%Fjd~>>jALq4a4!Nt;bN-pRGPprgW>!F z^#lGF9fQ{~337B-iDaR*kzt$z%iTT6Dz)9Luy~cGyD)iu4!(Hgm$clKfzZ@e$dZ?g zhAYp~2b}hl*|loz|{YxF7eR{-$E!}r8DFO9O1#K6ZvyD|GV@Yv@U!!Jh!~Qy1G=Wl5Tt0uQa@byPfq_>o7ybFloes z+PJD*T_=Qv8SAt<^~P;nsN1}YLt8j&PLH~@IqKr+z_Lxe*$$P3&El1uaQjSO(gC#X zy_sFbMpa-0X?u_EUT!bGsH02E4WS4$fZAYHK&>Jt(5h|XjsD7@Am$h$ASk5!X;rU) z(ufFM3vH-WGpyN}np((CO|7l-Kk!yAzVNatLJk~ z@M91D>TqlLe}3)Pes{Pf_Eg$8e(l$G-3&P0ScNg`bvHcm`=2Mq_8a-o%J@&LFZ1J< zqMw|;7GCHIiKFusA9?pCB>KjTEe!)Jr(=K6>=Q;gnk5u*z;9?!&@d2#>s5^n#9-(PX+s7rK=^`9llmN@WH!ZlVf?GjHUoZKhpLLcjJLVFi)!yjuiryj{1lizwQ7WQ8P@<5otZQf`plDrC2G? zU>^tq7&d}X0Br`br6x9Eir}Y(9 z9hsXNJ{{!6Z60DmRs;aZlyv~@M$+uuwx?%f?W4>|w6nA+=&5ML;%4I_JE%8zTl?HW zxA_he6~${Kt~8EZ0_%k!!FnZ^W(lm;a!KX=_p;oy~1TY9BZC#SOPXg5 z#du#dAiALIs5y}lBfPAqgy>9+W3g@m#NBAPC;S=S<~cH?zejpcUE!HPj~p3&lD4r` zVk}Ija1S~e2*Lq%@E2O1!)8ZBnBiv938oj;iu1$W5&T{6HNC=K6Wc7R&~7QQ$Ha4Z z#Zocz2w6oyQT{gRT#(RFAkHhIE9iF`c{&<|A678%eV^x^5d}_AQhGhgOmK6{dGj5* znUK-7DVVXqW12ppWU8Q8eH#C7qm%{y2OwBd-X&u@KuX+RF>rHD)teXXIN#yRa3U_k zbZ);K+9y^J>efwK%qraqTKF~EcE!LE>pfa7=!J(BN(*8x5Wwn{yJDehhNXlsHfF}s z&4E(L$UvOXxe#iYiyy~zkWSP1j&f`x6gbe}X;CLO@tJdRV<6mk6<`WqXF+%Md{O7I zy4uk+6Xnw8lA&`BX@U6Wo!)kfR|Tn?o`fUSk|IDcKrjf46>eJmw{#994kC#?I+rA%5vm%G+of0o zjNjmCs=Ra_4|jHkU`7D6UeIjyuKdvjtE^m;6riRns;=?tLM2QB5XEf>ExfpxwkZ~* zVMu6PZiHE(*px&xEX;0Ve|;5w|LouPq%)*0GiL-kE02juC~83k>WtC)Dt(kRn?pJ) zn{yJ|K?4qx8dV{AEQqMoX}r!EG})(Is>yN z^wQx2#UOpNZ_<(S@%Nw!Q+#b|$!02>PkivC7}o*Yh-5QnV-x$up=)y=HhiW-YzAPu zdugTmGIk1m{Eu}6L&%=`<#vtccOJf{c#@np*k%WvgS~zC#7JW44L_6lP$st*U;Hp3 zv2AZcaAR%BdB4JPtS;Kt8wz#243oS)tdG|Uc~N>l0?DyXq*{mD65vkLsFXUzQuM8-A|5%RH9W~`NmC0YGdpElMSdO#W?ci= zDt0qKRL9^#r`-$zF|;{`Ic$T@u~gTVtD6#69WtC2r(2e;tyWbi6mxr)U#fJ8k#0NU7Yi5y`(MPei!a|y~Jp{B!H@(N3Pa2s3dnU%Gg9NCj)Smoql z`5_(!o%%I=R#Sp!cq$QDEX_=n3UrpnxZ44jXBb~K^TUp^zv!Y3e$hv8Q-+hE=aS?F zAuQ?=kD*o8BUC}_5-^hx<>2JWKw3PG(_<>WjDb*Ukh)V&&lR3Ua*c1qsbk(^GlSwj z7?y*U^qBVIU}y=@n?N=RQBLh6t{2O898ATJUnk-4PM`0ZLz5onQFDTFFi_QI=X z=5TQo;w>z=mKt-0rH0ZvL|iS|KHSEELs)RrW%pG&aM!cy=X@I9o~TiCYDH2%#@30- zr#Zv!!__yyz^C0J-NF*w9OS1a$1DESI9cCkCNuA~)q9rSu{6;Ng77JA6x5j|d!hR< zL8qTDH4fFUe>i*pE5>JAr7;7KyZknt(y(na<_y~m7cs$E^|!VIHHy=2j5=y#XBMqB zUJw2D*L3(HzmZPqVN?Oy&;ScZ?gk5LKe4?e%K0)CdHAKqU;P!Yfj(b9^vSA%lz%~v zs62;--~#N9_5&6is0YMfR+|qWKC^(;a|$%FchQt5KkTKku|u!;oIXPB73XNt`|u&m zobccXHoqg9{ycoBEn;+7#LIj{SX>aUo=%9Go#pHAq(4zG8DU9TBjN_Q1Y2RhQke(R z=s!@NJSqaUxFR5ttfs6@wY@hyEd<7>H84M9a4v7xx3CNDW#=HpdpHZ4SoB8sy=RKq zHZHM#6mgNYagX(%MMQt_K?0h)U)Da?MRiSfy1T8uI3}MhI43>h9Mfb>1}7Gt5Q*)B zS%=*`%o)4qibwH#0E%?$l9bBust)Hxgs2mLu5>0G-7_Yy2){-?6L6d)w~rxc2Ko&; z9%co_q$`VQg$A%;L16fwkTu|nBz{yc2{I0C>XK~V7<1-M?PRgiR!qrb+z}AWjmdnn zu)dL3F)TPWw5Lvy%A<*0k|7n2?%;8Yq%aZ1qxqLN0Y-#BDlIl_&JHkfxbVtFI*=qL zQ+o!D*q=0J&`PB$P(X(t!IsJX3O{qk#1uI0+1$?|_ z1&F*>NvgQ;uSzBzGX(BJlq&~ax!eQGb8l&s&H%`*Qk5#gbrCAq0#|>iGTp)u9)?>1 zD$1S!I1Bi91#VF3@@z+5oo>I`xH5s~VwAYr-iQ769?vEmQ8IkAAfqzrBm#Z-Y=wKO zu6!ErKK@P8ttIao*QL`uKdB!c`>y)bSHf9oRIKy+Zb;m|Y-~?vEW3++vVlgSdtR~n z%F1SKGq1KSqrxb)umH5Ev0zYRl}ZC12cX5Et5k0*N|Id`Bv5^*epLq0A|?9CfWl6U zf(R4>X@I#PUrA0EWA=e4?j&{1>ZvX~mXmxO|%N~%!dW~H$e3HR$9R$0=Sg-^&1E-noW zbWLC&Tfg!}2G%3`YOOC6?S3}&lcRo)qiCZSG-g53ebHf;ZZwC9LA}wrMkB2sP7sYt zqmR2LFo;0E8YAts`k*C1g2V#E9jk`QyxUmi{I_3T_Z8H=m%xd1o5N$^2k}hbpyqSV zi-$EvS2k&dC}+b713$fxPdY9%ERf~QJ;Vw8DO!&9K7l95A9^I$stKvm^3Er-wg@Z=%oWTla!~mtL zwEKE6Ezj;=lAa^%naAnm5d(Ckz_dMZytC#hvVjo;R6}P#2B;W(SWzSf;eQk8l*}>O zXEsayWK5l1B<*7nn~!;H43(SG`ouuj2}&9cD^AcR8t`@L&d|c#ku=zA*2?!3+02Qz zJ~RyVBL4&w8-@*;;fC4V)D&B4P#_Cy*~ez&D>Fqg7SE8$_%%^ZedbEs(#ON z`<tG~lyLRI%{u~A$vEIr;I>y`gUpzrgn7~$T)DaYP&m=7cNl`2A0YqhV8>YS$0q?j6j!C-1)cr0@ zmjHcaB3eSo2CA)Ns$p_+if1IM<&*yulXq^S#r*EgPzs)mDvhs9i~*5Q6tCYWm*`d1 z76j{{StHDP72sMys+cZ$hTEo?hD-c$_@df)B0z9@NZZu{l?sQkfK!A@6pLt47NrdH z62sUsj+d;hytq{b6Owjt>extdh{HHQ0@g4@_EC)TD$m(@FYE&-A1>PnOdl232<%hK zuxb{*RMjsnp)4DNdBgV55bq;zSs@QR(hNKCE|s>v2!(D)k^UcGUb|OhcMn>J_ipdB znmct|*Fu(!DQ`$oY1IuW{89@tb}YLy(!62Dm%)Xm+~i!$6^bEN%H-*xQkay!erO!v z!S$%P9o34{X~_071U5#n0h-65Xt2P#ompq3WMIn#9tyzIp8!UH9uriW{H(P6i3DJ zrPx$&6g~uU7bIOrq0S(RBz>d37buU@IzE&>lxb(fajC|n8o**qQb7Sy_#3Y@RI535 z;CdhKHlladYXt>+Bp8S1@jL+`z#_gq@0oSji) z2}VQgJyS*^0m@|7Kh(z@cib~&(24ww%ZULxRO~51&b<6ENJ&heF+DDuh`ExyJG&yZ zLcp05Va`@ZVUaPsj;ezGDv+MoWpt0i$7oGC!hpm;FdGGL=VFmIlE0-MZnVUP-qo1Yg{Ee-#OCAqLjBsc z(egTqKmuVcOg!gYgEm@TV}GK{p2U##pUPVi?Sh4PQ9x>Hjy>{s|P;dI?X8cY9H8cm;R@7UfTm9)$s=V+!`SM+@`OO1nP{ zC{aP0U~t2V(ZZZ;P6Bc2v6I~U*v+w(#Ua@<)l$YV(23m`>&0pzX=7}(FgLI>TAY(X zNq87P#zTCxI3F#}LG+RHdEdPJY_0ju_u^a$^9jFka=ub3#ZS6ttD_#r#W|)EVXUkd z=#H^y&wK2K<1p=Y_R)`hSeY5Icsrw+YZ@c6@II!wWNoH1_0M4NS5?#I(I>I|UdwJc@TZaQ$oRehp^~qshWyzC)TUOsDQChnh7|f;`Erz{+&oqbsse#{ofdo1@3i z@lVrMOLYfXp~u|=5z>tYBpNMhZXlFCikJLOVn*3WBZ4}B1g#T7NF)h%Z+U{u>r|-l zWp%3oMH&Ix5g=8OU8vdt#Hcf(*9|u1LYmC`Q#h(PuG7)d7}h;_Dh*=0pN!s)cdQ_e zwBmxHvVC(}harr+M*rJfu@pYuDqUg3Kt`@2Qs?oaPIlvz_R3m*x>A&fY;n+5I$KI# zu*!;NkcR|S4M*E>OEXG`s|oH8L^yqb=Z0%jWjJzB-a&+i8yw3O4b=D20o@!-ahqL6 zEkAJrn7bTdE}~teb%DSr&ors#EU3vJdR|0SbDKjD-!H#qMOd|^$RdT zcYg_V0CkJ{LxF3jZmHm)F*sh0yLYk;ANm^(ycH$O7S-8h(YfrFxOq(6GZ^#{B~)}y zq5lPw735p@=*qRN(CK)?UrVOmY2Q<>6h8H5Y;C>9?lxN6pZc?B#jCpH#))&7}%cjqF|_Eeuu(XB|GPg-W_li>vr<8K_tbfubZp=B_skr!-L>IpS~D%3P4+ zbEPN!Q6nINKUQCqkC-D@zR?p9hT?b7P16XtyOhN^IJ z$RFKyw_^=gE1Aqw2VfH{)AkQ!r@bru7rmVa_g4&p-8+EyN{@XMUB^C3%w>Fh+;5{k zo&p~-jE5RghfY+G0TJWl&(NQb{|Nq=`OQRTxKVB+Aq%3qm#Y$u7qh%g?B(c&5mKDG z`T-+UT?`(FRGo=6U^B4|kzJGqg{XwjSPpu4@7bD*BtJE{l}`AnVJvW7qXP?gT(>nr zX)aq@-r9h>w%YCMOEvNnWZ%W1F8q_!`+{?nV9<+!_Nev%+sWpz| zt5@sh0`Ia2BDE5El9jQfu?vU76D#z2{EtxT^`0aVRKr;@$6Ob1%jv<5ZclXR`E6yt zodS=FLC;E!sNJ>Q$RQe&(V<3N{Q}&bir`}w>gPa#DpkoYg&BirexB6q3%SVlqc|EN z?BWEQxM=!Qw)V)qlIgVMjB7Z#Ce_hiT8cR*?#yXk1Mc647C5T)XRd{hbq^%#mXl+} zt@qL0e%HBWJEU3mO2#S1kz(b%D^}DpDRHsjN`=R!tg$LGw%a2YfKSxo@*MY5u#Ac% zGS#v{m5Fe$AUEiO3e8m!d0+@97@*cjqBQHasQC=8850b2B6~_TVW&vLi+v@J2l-tiAw z+t`iA2AeVmxZVgw6}{X-Ou^w2MDe|qQViEA!1)!uF*tT5fORSXAk|V_Dy{N5g*RIN z6`Gq=gp)xd2Ti-ER{RQgFA?q{3yW=(SwyC_tsrJl6C6+9{EX_|q4v$8!Y|Pg$M&ex z$NKGbwp;J`q{Ij7AI^YOoqj=#gdz2f)#;jf3^pM3_{z2&D9_M9ReZ9SrhY;^;HL>3 z1*1r`T95v4;z<5tarUbQzr%Pm*nPJBUWPL$TQHBWLn1R|zg{>;0y|W! zPzhHBD2*fOTvMC5DpC_+FAJ+74A)bqG<*6xX-26|6F8cI^lYg&b{Wle0mS*3 zVidg&j5U5ZDT2KiOX@;Vi9{os(6Rw$`RUt;)_E9vxCYbMP6RYrOW;&+(%;YOsuY4K}K0fW`IJ zYm_>Lk%@8GwVP?_=F&^mTk9)p$8TCHFKtdTEsZ(7{ur5}UKMtu-Hiy1E3cnSQ&fG` zHa8EAHs_2EJrN_%W9grMZBidwBigPu-+}G0SDBF31Zv5nd^n^uyuB_BZU25?Xd7d> zdu|70X1AhjDg^z;p=fw59Fg=odG`1VtmuVZ_$iY#u}nG!Y@Sl~N=g0>e3#G-H^+F5jVUWD)eV)(Jh$qAT?gr!_<5pGG6XPmlqiak;tv$eE5cTN zP;CvVP(H|GeNFkw85?`LQjvvca*?^H@NhOXx~S_6@@aJ@hbf#brZxk}gzA!U#oHPO zX^O1M)s29>;^K)n*eT}eN10-_{lNzxJi@;Z{*3;F9=i*y)@3qR10yJy+MyrZ!5%mf zfX8g^$U^*8^ugXdY{Bw}NU&O(DH%=!dWu=!$YyY81<$j4&3lI(pwaLu5HtE3X-6Mx zwB7<|k}7l# zw@8y}hFG4ij|O^g5T?(OsZ<160dSiS)l!VlXG6s68K)*Qd(HZ-!h-zK)GH>Lz%&zH zG*TrQw1C2(1?&x407kml243*yz`2DHZBcJu^JsfO8fV6=0XbeDAHNs(_(wmD=?c2z&Tp`YLZbrr-!UqFy3z5A)s?mDZ8KOTsIFZHP>rS&tAmUN*hM0P z)4F}Lxog+|J2Sd%RgKaCi%~RHCwSuq!C8G}VL`sIgU-R;KKHgjB9JZFdB%AomhtP7 z#HQGRf3H#BA^XlbOc7UD`_0B)$G^SP+P}Bg@LTsfd#&c}!?q92d*Mp%I()=j$>mm8 zK39cvKN9=MT#w~)FTYUTs8SsFuP2=B$qyc=qAH?*aFjUfiDZ(G=TVy|M*h&JPNa%c z6^2U%l&S#w4Zec69!m@|25%@L+*VbufOZ14FBok|sFk9qY*hgL7CScLzoHz*XuDJfeE?13zT22>TTABVM18Uo$$+ zh&IylP_Ov+s1zztCs&0bfy`O*sA5WlH}PD=55l|)B9%<&l)*#k4-(SP2F3G0{K$gH z|Eq44ddKPU3UBCT5lv|Y5JqXdputL$<>E(*xoWl2;fph4m4|>r@nd;8*yN%xoB6%0 z8c9@?`)Hb_h)Ef%13}162h%dksx$C#5h={O^;Ig#g*(+*sE;Lr5k09P*PS}4L&Oky zGU&;qx0|nnp79V7%V9!pMCKX!@Utgy!z9I$xp8d}`F)A^EqcG+I1C(5l4Ye5;^lKg_2;65a-FZKUC z)qhrz^9ykW{7okFH*s-~Rk+zB35%z{mxgACMo<8108W@{Sa6#CRn8+g*r<}0^QrRo z3LYus^r(d+?t`7z>(~RoA*z#A>beCMkDZC}y_de37y;O$nSxdi0V_17f~gU61!+~pne32;1F~9_R)zCSDkng#z&HiD{Mwr;iIi54 z7$0_Lx!IAory0e;)Qg;e2>^NmvUt&WM>q))pOv&Ohn+$4GNM1)=k*G;Ag`XjRUMl32K78lev(A&X{*2X=VUngwXaWlGDh0URTivQ|`d{g=o!8e7IxO$Adh5bRzZu#)GpwQ@_cLg6 zq%^~~Oai5gG&}gI?4`H|00_&3iCmCmI(T*7{2ji}AM9s{iW4^f3B#uL)Yxukf!iVM zEhx#-N!;6x{skHW92c>>_&Pp)$*RP@Y&X)jQYx8cM~00t!uA`1ZNzdX!r;TT-UzpM z$mSKZG>r&@D@Yc{*%9HU=xr*8K8J4RVc6+y!nSa^W?qp}oHOj_lt~?ai{}GOzY3&%%O2-1T@RFf$VX$O%BsPcheR>X9S1 zLdk?%w$gR0?*b&g<)xBE;p3ab((QW6sGAw19OfHWSmxT=gTLpI(Fj|2!3p8Vy%n>c zYOSj(MU7n`RWvemybPf^y~8FB7>Sb&?0J2oDDMu4VOwjA#4&mb#Vpy;7RAOLg~^#) z?d6Fz52fxoA~u6jFAC<8p|b~BHkeP;9;A8q#Q&6bs4F~DyW!BDlm08>I*FKbef);i z%#Z7#h_Pi~;VK3*QMRzDx0(!5<+&UWy5k(2`Kw;aC!}Lbwk_ZxhDE!f&2|5adO~GN9`As-`XJr&Wz83V7g4w zD{%WM-^oXpz!t3qsJ{-Q$@W*tO7L6z?=<8`{Qp=;cA%=AMu`BEU@W$uAOxLe5B7-fa{?+K6{GPWS;%Na zog_~jjVOCg8_h6kwv3*Fmrnpe=Y(w&zdG}vzCjY%u;i~%=bLii33h%L2{R;oZ&aVJ zzH&>5<&DtAd}0y(!7~mh^8({f%b3 zh*L=ocmeZY5mNO&77diE{f&2A!`8BK)F^7Z1j{Jp=KDE*FE?4R=GgN3>MHK6W)vwt z)WIhGt6$usPw^3jGsLbvuR2KCc$`J}sDcxV4P`|{c=o*o} zh)~KjGsLbvuR2KCc$`J}sDcxV4P`|{c=o-`($LK!4~Ll~4WBnMwI>9ifcRpmM5TE2aL>FDjY(H7aCR7U|%oIJ>Fhd;iNs?1x`!sD@d;J-4zZTDeWG zT>5UMLX#MR3c$mHSL}iwC!^IA^TQ-3>tI0HIEfqLAkH1uskaQ>d#R0ka$z;(c>}ol zqARASD`KZCv@_;zHl)6jn(sIUn-ppC$xVqNU3_giL5qf?G8tK;-aJtoEGFz`sf3%< ziH`?_o=R1~QhOq{jv{w-lFsGbqd83az}n^hEdKl*`5l^+rX|-B!|^_!A~Dyg-x?KV zeuD*2(0%p$C1MIZgu$m09mL~@w-#`u->?nv)P}U2Mo+5NOvl~u@1y3A#k7~sFHt*f zCS#mF3NabB{6cm4b9oO^3Od5UkdibEn~4cRr+A9FfB!4N^Yw-7RlkAd?zd=xySBCZ zm;Cu2{$|HNH7=f?+_;b}jc4(|DafPu?j2=+a$)@F-#yA?vq$e`VCl_Nm9KD@9Au_( z_a`!+pd1s~PyRAFTe^^4_|#Ji|3UW0KAHXc5w5w)_6zmbe?9!1Gz^5lC^&xo*A47R zRKKqoND!x&MxAB`~0ZPPIL0Y_L2bAL=mnV_j3 zjcMd@&0u}ec4%T4%^trpAZ?%A>@k?sL_)%D9WFA2ud;UQ@L z@>4%HUKuAb6z78#O7&WRwJUWJ>iM7hn@2}}{XSAACe@O5sFb_+{q_bg4liXYlRkoC zlK_a$+IL-YDhz>G@3o$K1PE^lq;+X-k07K)ep26bfhZ|!EMgKfoj7vRl2AOQn*^Y7 zZac#%8|OSSlg+j&?77QuMi;ECpS!G^kC=r_CLzj5X}s>4@9{<3F^Mq5f)Lw=_~O1~ zKxe$3aiAr#Y;HLX=6r>m{$6yMCAN*zIX4Qe=fbyR|Z0y1PcKvPG<%cGN0{gDe z8;87M&LkaiAXS1o+o046SJtnr$14`5y2+j2fP_Pe1$%z}K1uFesbFXUEG*6>*=NVW zITT3!hS=VxwdeyVK~lhKSVD)oT+fX!;=K0;KZ7}S)tju~w2C)%6=C#CuPTgQ>G&!C z38IzGhR(Dgfyh&-yu`z0Al@e`W}y^0x#?F*I#5>=RdpDQO4))fD$}XKOVEz+H|+ja zxC|Fs8(S%+wDTAW(8>5zvq9uR&;Y`MDBid%Kpl1vtt|Y75msYATlhrN$Z}^O? zZQX&j38-X;VUjGFx{xg`gO5ZS^}~8k0fYx zz)`As()jFfTyDT^hjwY*e<|ULHS`mK5EIzp8doAo}^B6kG2LU zTOH3bbO<^)gAW`Hqbr6}$~o*%PQASlnqVohZhG`+s8qt2?aUbFU2q|>ytQ=`y0^@S z6`T4lqYFV8dvpZWKu03oZwj8k6%<7>+TtJdig}AZ@G1h4k>czxnF*v5oPrK02mXh2 zFx~aEkefD+7l;sHC)OodJtyEg79b^_1_jVLyg!piADka6CL_3g+#0)yKppO%b|}>=B%>@7(HV4}gVtD};L}cv2D9Bk+YC zR%t_fhVMBI;)jxGLiY)hyE-Xsa`8ZI!rN}Tgb*>hu++Vev16l&JDTh5!qNm!X&-zL zQMz(@)cwlR8DpDRY6)u9o40UeqP~q)EL^AIVlRGeZ{~s$PT5ZDu-VCv39mV(p5T~b zaAlffe;n*vKB-`haH8b`O?A;YS-7@;4AdH17atGyd=u>4!yn0nqj@u=a{*n2}< z30(2u-M3UM!K+|m9HOoAEB)-fC+%q`&S%)M!$aH4Lz~P{&}csEW%jhRKC$9~9WFV(Mf{`=eHHsjm-tH1FZzwzkk=!h3C%9CX_c==T5zj$BOgq%siR@yfuX#4MEe)B>G zN0s335FQU#itWPswJKm%h2qs{=KD@FUpLcHGXv;tfs*+38fWIUQil1#L-dp z$PPYAY}D^7{D*typDBP9h_?(ZysYwBZPbB5Yfip{1|>Oi7sk0Lu!Iaa@F!7Uf?`0_-VKVf7 z(GoXXVIt0C-aArr2p#Tx=cEXbwGX%39k^TIo}YuM^C%E%>^bs8r_Kp(ULV;`csnNEfL3_oZNvIAqk!GkW)=d(-YmeNAxg( z*m&g1t0rY?+3x6(do@ob!EERb_CN#Y49b1d!oud#OVwN0@~g4h%~wBPU07IPuEI_! zmpj4TKJ!=%ArB>AT3cEb8SxSM7%4WYw^o;ytMVoX4+?3upn1nXXl*xI+xc!q_f^_i zg)0_;k7p|*yJ2DB6BZR&G;)aZd*XucKw~9t?|7EqAyDytR9q%NH~ePvJjyG4j8|mf zP*xl+%%!&8A*2(A#|a_s?Z8!b1=(EO9AXVaU?tpKqv0Bv3Vj?+_>lM_0*rg2is3h~ z^w(lyY+bp99uRRr*`%_t&>i;|U{#iiI^wGQhYo{VS`#Uk)@C{9t8S12<%@7u6*^i~ zG3*dcg^S+oRN5oxYnXnogFTa5&~5%tg(LckFr2861%$GpQ05mrkcxSJb^Tgy;x)-w zrx;Z1|E%HX$S4W<#IHzJ%uUo~GW5+?TJ@fCqY{;yD(Tc4etQS4$i4gmobly;{|r69 z8}K!n4j6zL)NKZ@Aop5X)ZoA3z%jqFfRh}nARd^)h}qmRp=J>D8eUWBIS%#ts{5WyDsu+UHgYu=PDdr+Rcwx){)hh>b@DdtNo!cGh4*=w9JS zkr>he&fd57^93{Bz+o^gm~Ya2R+mDkmKYcF9moBZ+@>x`rI4j$p5p22YIY3&stiIx z)a6h;D#~bv3exE)K!4botnhHf{pS;938YK_&IQp%175s}M7dnWf{xF&I%I$%BBt%Y z7z7q~><_f5hq(E;^Y%TzbqD;cuuBI5C|+qd!U-f{ha+tJkXge%MD2Y;jd`cDx9{h1 z?CF_(e{p-fz~Jpkn_TpF%4F6sddNKT-&B+&J0AS%|N9thJ)U`$dcXPVLMRPVjOnMy#>MyU zSa0daGT#X5raD!TJ=Z;Kc$c>}HgGSX>NX$Lt404RC=TH93Q0(4tx|Q6-o7 zJpUzL_7wiba>-aeD08Rl{;=wVsHmKJxTr^Prw2JIf5&s#F_l#G#IKd_^W??behd74~HOX>g6Xv*na-{=j zth84YF-hSO(qHZ%^! zDmi|}EuO1OD{IOApG~j0hUaE@1?CQ+h1=an=j7SF?LYVhzuDev2?rpBg@5}7`^rHp z;440z+JW?D^+z|5FEiE6j`gR+>jf6=CZm1Dwn4}#CZuTiw z*u#hHX}a}hZVvKtRD5LkbL`=qHUgpWZIIqQev;wzfj~m1i9jC zb?gaGm6)+J%wGEiGy0&TY?#GO-8-p@uxfCNsOAB}p4f+`nrDFt+LLwwGqMR|OnFr} z&)w``-0jhhw%wYPnF#s3N~_@()M30>(MCn$26G3jm>LLf$7j9TAmv?h?mIEDA6-oC zR{ZXrUK8}9dc1oEexZDHcMO;GV*1z|KK)Zs6n%!Mhc3TSq-+fY4Fk3TpO0%k|~ge7ju> z{Cy~FRf**C$ULhbZ-08pB|aQk*ElL_PYi5zWNps5_*?o~~2?^1%!9$CI#(4Qp$FenaK1}j_gu6 z%2egJyyTK$$Pr%Q`;7R{F7A?6n?hLbzPMEl#AkU_paYk`^_(fasP;gvp)Dq(*I1+8 z?%Wnum$wgEZxK7haPkW4Ybax76Gv88%{%9*1SX8ow&`dvdfcK zV9hbyz__E{823ax`1}hwb#~bFe6h?5Q!sK};@7b+5(`=1z+Zl)xqPcFU0d3`77=lc za!yutjHlm>)KitE%^-;pp%V|c{Bzla04>8s#&LJ%xkR=@kC-Q6gPQl-7Z`t4Q@(d3w}_*z0O zsw-$o-LnPyIW<|r#B533XOFa{*5Xu0h_N0{93f=HJ>Up2xl97Bjz$C!rF9ruc;r-~ zbsRA~pp%4GqbTEbKodO0Sq9VSoQ08K?DMO0Ji-+-ozEwi%#2li2>g3ZR-fL+T3x}@|~pT(RaS{--hE6 z`kn9mYB*el(Cy*J0gWo3plUy>uPNtOiu>)teZSJUd#Ca&3wMRBJyuQ<*jaS?@V)Q- zOL6%4fBoL~{uOO$iLYJ$^FPqv_l_b@cGDRSIE}FKi@e`s+v>QiYI@J7OZVucU*ZXG zb37>*M%klB-wYfYWq;B9SYH3;!WTc;@qXJ;_0O4V)4tDHY0E@9U&T)&eTF|Tt!&h` zmR1{S4WH z)A>EI`l%vpCXi3A#3_2tQ0Rm=Wu)5)nA>=T>(v`eTdP>zWin4?#B0avT!6XF7r7Me zm!<4MW<7d=?!0t2gB37u{;g&2N(w3Inw!jPD?$d*rm|fuYfI-J~vN_cwWudspA`+i)hBM<+bOx?FmKb3Q8%XG6l;oT0?Y>^19#ooc5ApH?6N zHYwgpg(iOwq(iG7kAL zQT0EMo-Ps`}1EA_(0_g8}mUgJn;fdqm=CF_n<+Ng?qkrJYt+kA`ypD_;wd z=i*~T;(c|~@y}Mj(idF)WJ<54=%@74&69$>PZvO=_K|23Aj8#-Jqav%H1R$Oy{u?F z1!p>g%fw@V`u|iIIkUfM2j-*9nQcN3fE_~@_fY$glAgh#GhoZo65)W=43z!kWY&Se zJju+D#b_E1!oE73Vn(HmFfb$xC{qY`wShs~nU`U)aQJ8V-X9}h=0$JbgYA6DBMW-wO*}_Vc;xw5X+`RB zk8|YTW8OMV8dnWDXp~vU#z2lRM6Fk0 z#mM7_$q)n=9T2j)MV?Jy=jIevg`d07ho)YWNSn&SvOLwzy%C47K9u?1_jXl5Ea9*g zj(0_#;_9V<(7nN|e*Z2Er*S@v>1L@B&d-8fRd)ry#qSE%$4;Vd8ti@+%rL!+v#W$z zBe_O|Rim=&6Q?d=ko{d{`McoWQ<;?3b{KcrI7RljpNAQpdf}&Ax}JLZ`pKPo5yx#t z9h0tOhI1T>O?m2+)Bmkr-1^fVN4jjBfb7D-Yofet zoaKWgwxnkbb^cagUR1*L%srCO=?Qx1qE!79NX+3U8s!b}23JpWVo@ACR0j~PyF=4l z%q=pesVGfp>geV`2U{;2r_7Gq{e^wv%ofLz+&08sTPeuE@e48Xo^edxGb)d_KN<2I z66G)TvT^$E<(1kCI0lyI{x6HUGLD&$Lm?*pTQhdh!NHVVSv?W)2YV`Wp-bjad{yO) zDE2t3?b6U)v^D~w0UCO6@-=o2_Vx=4{;PNnXi=ja`RlKD6*?il`P~K?(?3mToLYS;q7vgd#EJemJIWi<>rrj{9E6sOqHj} zX>!q<#ti_ocma>$uM{L=D3t#f{6ShBh^q-?w0Zxbi5DOUJ9@2d!i39QEN3L z#RNmcV~#HEkDq9n9B4Q1!f8Wc%J2sR2j5+;|F%7?fP-GC(A692Nx!b3f_~0e^tcO} z{z@Kxi2+>Trqteue7v-fK4`jf-XK| z-^7Vvn_(LI|1L{jXJIQZC{jnT!Sv}uu}p@XJ%|V3OqC>9blI1JR>T5e3j7BV;k+R{ z2YK^Qf@ZmFyas{gGUgL}PMJaK9Z|C;6-mhSk61OU)a8c{FR693PLl2g)y&Rf^Pmrw zC&qP$;dUZ9!SUIEcOaNCdeh!pz^w`@C|X0WHbX4EzOhT84$!CG4$$=pqC!3~TdeZ= zhXG~s<|WNNVrmOy3VW8(`GD-uUP{y^MnsiqvntmW0)mPK`IOu+axnh%qf9Z|{@{ZT z9^s$+>;?gU7Q6;;30Tf#u4=a>(Yq&?jop*ph9|tRNUUnT(LAoQ@(OU?Qr+0BF4t6i z#L4=;bD~zrEUM&T)C@6^O2oe;fNh>O-F~xiWdhGdwF%Jf9Ng*b?fZGSOnBzzHosUi zyO124b?@DrH+C1ooguvy@k=8%s<>-&xvK7_GTaTg+(fW#utxcUk)6$7tyILdjKu!J zAwe08c)mz#<>5>>BD_+0sEXs0!~$+OSi4?*Wg+~cV)XCdWOO1GrUUc~kNNy7`aAp* z%Bup@Z+sS&LjCHLu>mrIU0HP78Ji_kXlxnJsWQ~B&bshjdLphFoi`NBium+qbcShW z5bQ^roCxbM@IrAHg%;Nls5Z0B0w7CZ$9qCe6mmcZ`4JZ|W0W!UdXg$X^T10ayGTmL zX9$NuDZqPTSA?==vO#96pF-s%;n{_M)X92kiXRCf3|mPFFe(MP1QFG_0L3wI~Vvvc^&ytWwRAfx5gOLA|Lq*YqY|QDL z;8+BEiW(M_EJ80aZ|sI=nEzg9>pxX=`~zq$;gE280vF=_B3|epJ`i^3Z|G1F5~RX6 z|4=Ed7^^&$k{6B-qpInN%dP@t-q>6YFAC1g&GEGE!%_-=^Vp>k@9`JR$H%NJ1o>C^ zHT0@r{$Z`d=8av&Zha`aCFm60sXssbPURh%k{A?iC4zBQfbEfTjjg?F)#pJID>rXe zudm>i97jnwZ|tfpZ&Z(CW4YqUx zIt{jUi*EQ~u+2qQ-lD7u+F-cJ5BK>|%x1NQe2c6J;OWW&w#Z7Qg=}^0x(mOd8@;u$ z^!&{wSc2}~+iUo@TlYG9t!CTJU}$R;pw*kVm})f|P1+X%{MN?G&83Z3+2^XSvZbxs z`pOzI+^nwEfQm34_&wa4`Q~AxQ5-Lo##5!ZUR|vM9XB@CZ=%^D+&X3QLgkutBFJQS zXrNdLvpS#Mg5ykS;MrAItc;pS!y$YGl2&7quFOW`O3ZC zhz6!La&=5OHir7G*F5p{P-!;Y<@^J;hH_TYx6*iKmvKiOt22tm?VVQRaKCxGS>N~Di>;=HgkL&K#~m~iu<68*UBnDf+gMuLTw1QJ ztgkr;t>?k$!MzAK4rFx&nA@j1!X*P8VX|~iZ`<+JY^!SM-dqO+9p{pWj-Z>GO?uN2 zvxrz;zj8=;28Bhz{eCNY?jIDr6?_dE8bl!U%|Moua9QF@FfEhEmB%DTT=Z(GQ-P`-ET_00mvvmOW z?Y1Xk2A4B0=S`iGC+A*?S~OHf$O$-dW-XVDnN`xgyrM86UV*Ys{Q#CTtz}dv}|+v7VsO9-6@*uhoh7l3#T$WZTqU z&hHf2E~xzmKv`R^LP|o0f-`NHl<&@Jow6Dgpn94M`JAdb%N++k68GOh36(E7kF%KskXJTw8~K33pKXBMawC&&*ze&4Wuz8 zNyP8^cj||Y&h3DuE)qkvvl$bR?0pIUflp$~Z5X89z3U(3X>zAE4j=P&5fPISmlO}M&NMKYoO zH6~x#zcQ(uyn#O{Mq$6XdRnm$=fGw@vTz&QP)rIQDk6NA-sKOhqUgaYj8>Wak?Ye1{k*iaytQ?6L5x(lAS$Jfe_w3f12b^IDH}7i8m&^h zk$=Ey)mLho*}QFkzT@%~L$U{X3hKvS;^;Omp}i2CGXG$aj}i1Vdt1B~_&om(TiN7z zrg7v#oHWyyiVwWvgL3h~Oz}ab_+Ym9;8O9yT=Bu>;)8h?UOjt5FXR3fPAi(A2nT31 zM+k`ZY{ctDQmCK9GYu`jZ?`+(=eKwF4zLB+IuM-@60XV-EM2XuX?uXRk%Ase^6J=w1v5`ZwHy>5%Aj-9sHE7V#fTdNM zuB4I;&|bezhgG(2uCZ;kV%4Wt*4AmwABRXtvr`GO*z9!0pDJC3G$me)0V+k8I=0v` z|H!Xxd~GWk$3>AbAxab-;^5%z`~E>2sznGeWjBX0|HUeAVk5%Hj8a8nN?cxFyRo{m zj0G>(m`00A)aNeAX|CWEdTGay9Au&Q>UVu8S8$=CTTCz);kL58Qdk=1x%`Ap9tNESx==eJ zL5W1m-Auy*Zzg_H@t_havgH@5%b&}$eN3m*5DKBezJdXclB~uc#>+zplBpjc_1l!( zo8E??SbMn&MOTRrYp=v8w+%$>JOL1BM0L?%Zxn+^f2RQAi13EUv9T6vK2Bg{Wn|C{}gPF#Ry%~cm%Un_zmHK_5-oK3jxtkx? zQPst;P&yOlbcWJlkrpA6mICQm2ZaS^9i<8xxB#d=@W0yy2A7oxAmi<+`Eq$?X0BYC zxpaB9GB-DSxpX;190uQtWj3)9ZhuFUlgWjoDdmvZ(2u`F?8m0|6K1Q!ZBVeL=##J7 zBPu9vSS;K@w!yfC#yQw?bibXP2IH0^3jCqIU2prh8+&b+K^r4nZdKK=6SuxWdv3_p z@L6Xm-)j2!zu4ZVi`0Z>fJvbphdpJ$)(&Y59HObj@@a1dY?>6qlGMfGlWXKa)*XsQ zq>c3%g?1=|5$R5TGfL?97R#Jz*B58FAXZ%*;lD+dX86gAF-o@Hbah( z(|cUJ?BVT)53yPf`ZNT`X{A%UJ}!WoGU=*rS~CbQNN8~MMqTBECtWd)=`i^6hCLLG z$dWjt#O6)aty-r6CM2|4*yF`iGQK?y zZFXI5EZGP&rZEeFpm$PSh5%6vfMyMuL4v3Td&G3JH=`HdQ+|$C=B@w%U3uV-lA;1vW)sIpho{3#od&ZFB+6 zZEn}4PZ#cDW3KcTAQPzv?uROD;-cO-cK}N+h^?+*x1Cj}KooSD3L2yUuRL%Gmj*4N zTpG9pj?h8yP#zeQGaQpPWg8NuOTM&mPSh*I4HX};KEF;_ew+Y~r3^s!H6TQ5q@WQ3UV0G5tQjA3~QN~ANihdGqV z{gg~fXt#8ua6Vh{Z9_d>J%Ftybd&TW`1Aw0$Hzlj^D{ev8WdIDNYj#s}!zYkuX+9R>S;m@9P6)QH;T6853hdx2^}`4G4sr0( zuR3a<*|=p{2fGGbMdGUL$*>EWlOlTun*>W6dC%HKaFtdizA-6x-5Jzj(4t`neoZoF z_$Se(+T@}MQ=Cnm#_CH>@qTlswF~pZ#jV;6?^46pvyEJql}KZD3EK^7x3AgSfvPV_ z9u`^D>SnyY%~^`cb2?6vrE9MkTX<^M4*onZ3Y&QjgWHz)1zd@?D7$WtxZ*ji6BNu( zlVz=qxnRu_WpUq5V{wm_b!}<+1$Gk_6Kvr+PB}p8#`El6^WI^{D_;t)U3%!9-~3Hl zDgCB=#EFJb6FDMPD|_!5Wv`7TwbYM9^~@zhQeBvus<)aMI+Aj`ghLRDs<=_OB*C|^ zI3tl2_V_z*+-pIwBdakoo{|X?R&YU{+hkRGhqh}LUu*Lbi$7n`Wwhrng-HA4fw0VA zU*oo*0!o_@3`yJ;QHOb6=W^)0&JA!h^Sn+UXLZV#;)He-jZrz2vqrt0GZJTuqAc+) z#YwBAZxYI2SR#USWhY2|kI)2(B-ml)7L&VV?(-R`@+Osy-Jyn5;IfbAqZagA?EVH{ zmB}qvmiMaKSc>eXruhHDc8dQkM5Uw{m{?8HpGrk%@gftaE7qHutQ3me6!ZV8ZqD%+ zZn@dWto|zN280Ep!4#Qd4frHu#Hnn{C%oa_!#~HPb~A({E*Wy{UBXa4><*h z_GA?0OG%y7?E#dhxkDuGeIU`jQRY2yk_(CS`QVspw8y9}7fO^bh2=rpIZ?$~yRkEw*x)GvR&0(ED`*an&C(>= z8>@vr-aXQJHQEUJk|Bv&Q{26Km?b1nVcW(lCnsZ5gUo7n3Ly&@tFWD&{BDu?MRrFQ zc>{+}VNgZqJ$YQg-p6nxrhE64u;kbZ+no_7irS3{wE%NWnih~G%N>OYi}~&?uz^dG zTuonDA&2=Fq_LEH2t90qJ7-9)RtG@uHMq6ZYC3DFIYaCuAUc7xnFxf~+B9U-z+~%M zo?VA(HEfwRXGmyLNVS!&h83I^LAend?KZ$FKSsJ;Y~8t|#SM#_I)n*sC%0sS+B`}0dM(3Yl?pfo@ znPybrQszP?^8)nElziMh>NIBvUb2*zP^2iD4!qxTL*jGVC8lji;n#|Hz|uc5yqJyY}FRWC8W}RMX%)v zG;Gn<3**wdm(E=*j(5Blfu~d@{_Nn7AT9z!Td4z&E<^xGEz*M4H+k#n)Qn^Bi{m;= zH!A$SAFAf?-vQb(Sa3^9V9u5HnH-?jTtGe%R|`c`hvUB@M8}9K4Ez zOuFXcgst8UH%7J@IIQLHz(86Qdwo--SM-uRcm?a+vv{X@;ae{P(d}cDhiLsWOo7O} zl}c`eMjxG&6aU(HQLa;MR2i~kiegF(W?05d0?>IL zD7^SD`c@_g8(MX6&OxbubutAX>4H7z-8XC1rR!|{hO#8%rjSyvC>spjE_d^D-QGPj zufLI0q%`1A36EooV#>P&nMA|4QQKNtRZ3+K9v!r=0#}QmO?$@yCM*4xe7>w+f+B^vh74ciYB?`H7NZTL~1)&Gt!yi!=2~R;8rP4LN zS5ji4v_Ji@O-r$IG4(2~mS3cufXlC17Hx82QO+NfN@G|c<9~BeiO|xnwJs*s8akbF zIYOM{d;Rx#^FlUL7S)}k3F2k>IIQlnA?``Cgm${wxsxA%W*izxvg7A1!Jp7!h0DfN zCMnfDR_;1(;m6($1x9q2Say|IcVc?t4#V!~Gu-|7LN@a#xNliHC&!$pOzh0xUt~PrtHN=) zI|-Uzr5*OQc-Xn)UE0R>suSUYZA=c)bfwL?G~0{bSPs~@9PZdVCc;_TTCI^z!?67Y zWx`1k*tA@Hk`_;<43#p2Qmm{_K0f0;m5HIr(AgM$;@S&EX(q^{?9Ppy%*a$TV&@mT z?9hya8dG*meffk3q0=<~fRc_bjD$%zG#UGH@+-6FH`cdqkt?Y>=tu3pgLO~81JXqa z)BDODm9XvNrE*i|>9-eU0_kkSnw9Ujh zj}2HspcRrw@^JXJmgk0KJTpJjXQMbgvn0vtJ1v;wH9Lz?x>>8_qK*)(6z4eib{BEm znKN3$b4jY&ijUdz$@J|3lVo(2%tzg;WXki##3p%&>n<@SIP3I^!L%h0CAwjGtz#r> z6&e>CRXJ1M^ACR6E8w!y6qgK%yF}@}9dYBgb@2{ewPQr_;`qJb;(ngoQ{2+U%A)S= zaqsF;MTPDzl>xkL9Ixk(S%+&)qpv=?w*129z8`&2kOG2!j|~ua^cZuunlui4pHAbc zL(?(A_K*+Oe(okUPUlIkzlnAQGRZ;QW2F+?$MEE1hvIHr>>BHB2kt@Ax<$^I3&Q|? zjrH$B^67Dicz8bkGtzJ5`1l09f`4~&B?&hU0h%m^%#8-Ni(zjPI5bw=Ez&W4nO6CWej4^)8B8p0+f+PLGWKsG$rVdLfKC$Be?l%`P4YJBcm|U% z+9U3rQ3cs9pAuxKvSZn1ckv0zPMgE@B~K;Ow{U(57eWH9Xz@i)Fl@+0+P1hftm|GU6A^%*Zl)% zs_})y>TH9?6yPRyg<@Ttb(K|b270JUUU}|Xyw`vs0_n);SrjIUK!rUh4be@KdD5WN zWw-a@3N%DGysiK3Kp)mB%(YG+M!B5QNK;N1?sT9 zu$(euItlHq+x9^fVL`~-7q}hSTxoZ31cy7UQ8Z>I`(lNi}u}+e8iy1)&q*a8 z>qf4^?sS5M`Aoh=S6OvREr{W!#sZ0y=5!p+^zXDi zEJ#Hie751_}Zz4<&%Gup`)cIZgsNFoY}|2T`CP{>Oj<2okIqiLFR*5Luny zIp5=+@4NTbgOBc>nZ7g4x{vSuIN$lsch2wpFuKIiFPu)n?{-BXm{+m#*N}7jTK~Ci zCiX870XW^no=Op4vrZ3na)z~f86adney{Es$D*J~duBClIIR*LCxN25-76Sp;hKd#>Q&^wAh$Y&cYTBmQN}_~KQB4}e z8&F~Z3fI>D5%vFRqGZ@5NxxLJ`s>T9m|tJGZ8MTa`L(T$+iT10uTn0h;?N47HeeuZ zBy4At;}w;oJAMQcpy#X+>632i8UX5nhyAMYsoV5CYlhfHqnU0%r)*y5Z@j91eSTMM)(Yylm1FNsmuFFY=)flsYUrUPk%= zn#ncXj!SYDE^+Hsx^f*0if_^6hBmIhq$8N(q8Q7J>6PeJb~K70%pCoBptV@;2tGci zn0q3&DR|THfgu^&8*a+Hobq2#WGHEZfuiHx)HsPmR2<80QA-DSXAXr~#0y8(MZBQF zH(3qQ@-Wh$n1XTsmHbW~jxO>`tmi{6FYu~CuOLc+^~tEoB7={OPXHicd?HTs(LdoSies>OC^H|o@Ofq0zgJ-fre!o7{@?)R?!zP%mn?DYA*vjg>U z`mQ^Fx4qLeChuliV}A3F<7zJHT6bC^@TV?#SkgqL+=9|KvsVg!3=VvEgUBze409L0 z4z_3XBCJc?Z8Z-Lq8@fi*o^@^*!;l_8T*6RXQUZQ#%!Q;eX!ztcBRwO34l1;5&l-Q zmUV#MS<``HqQk->H!PWJ+i8cw6}Ij-y8-^M1ih%+^Q(^KFC`v4P9Yv0KUcCNroMS0{tALUU^=mfT7XZ_X|;6T4vFTy*yK~2yIp^yf+bWCuQ z&MG<3d57jb#Tl=kwBY|noofv}*W9uuxh;3r($KP7xWE43)&Qx5- zI8G$}Yb=#$Q?01`em>eOUn=ikF9+}=dW2E6RKl}fI(Y4f_vHQ#JDMjZ!xbG&3%-hv z>0{%3D0J*pmZeWyXGlRP0JLc=f~1Q=i(yRd=xy0>cND^S&(j|BlpZ&Q@&{SWjHT%e zV2RNP6cGsy^nHFVPim0yi)d}V)59AjKiMXoB`tF>I9V^NrIyZ?y)T#Ey!-aQ%CSyF zH>nws;?=+%vu8I1G6#$_rm};KLX#(0`$CO6jA$m@XlWYI&Ty^{;&~p!{M#Kc|6*VF zX2v=($f+jH?>B-QYHPT%_ELR=JQ2gxJvGKGQ-wDWXFb@+q6#p(5@cZxQC5&eCHQ=> zo@_&`38-$$r$i z7bTqqO{chpaOc8h|yLo2yo5s&oj!3PSvr?r4{ph?)7JZ)lYjC$F=$KUH`Sn^QSC^_G4T zbf>U2*b(HZd~-YowrAZMwy{MVlyfIkDB*O{Y!OZx&+F}(B)bsLqs(!Q=E*@X)h^1h z9+o`Dtjhy?hzI9h7XtX|&Zk z+@~suIEJvEF*9O*`GZj~Y?=g+`U7yD_M#%XltonZiz~tH%?Qawy6_1L;K{hCd^b91 zbQ*AP+^sb-lUSl1s6)tN&Ivo$M(;s;saNUTZCYMjRSy#l>vQ(juub-qSsVE0oLY_)!UOZx_ajS7*XMh#Yj*i{jA@Ewa! z&j?mYx0NZ%hmkJq=C7O)T{tC|2-fVS>LfF0FW_&4f8*rSo-YMXJU$+f=U2ROo?m9X z;zqn z6h+T_4hPH@)ShvL5W#H)!4^5K09x_#S5!mXR}Hc3MilHxBH}*4d22Yhh1dBPSev5O zMIveMOkDFrbH@~D(a9cvGjmeh4Zoh_c`RV{;NIPr3* zmJy67P*S%glEMqOnV-B^XDwbFQ{|H>63zZGtnTpCROQTtn-UBt; z=FYK|7)f0xe2I>B_BOlCclINq?b)IFecRbP#Q&YoRWs0 zL{{p0Fu4^GGp7yf!OYogG|D4Z)j(7ts(eiqv}6V_@oS>|yfcpzQEo{gmD9YOJBo!W zt)ACX9TG}cgWf`G((e$#+vq7~Oj0WsCqkHaW1O@J4kfwmpA&@gwUw<`U?7fDJzydg z&8UYu1a=Kfm{`b`t{wY;qHWt?TumE^=}^ID3~3u_T{eV#>M%%yW31fP0G( zR1^D<&_yOSbi$|`(KdyFo}p;PGyQXD8XlK!p#>MB$DctiRnUL%tft@Z8;@%Y2}mB- zya@1uoOt7A7H>x%|I&=M*T)v=%eq*)iCmmy>6T!^iGD7}D2CNZXy3eRPneDhDS{z` zc&Ijtb_KQF?9DQX@#|)-bhAkXENh)2{Jx;i631x3{X^&kV56-!Cf?!--662 zn{JSGxIGWxPL_7ofJ1;%yeg?PZZ2ms01#gh_)46v78^nJ#(i%ffg4>z%IUj4-Kd1> z(1-|K+Go&a-KL&+owASfwjUL`1C;?EW95TKLis@VBfP;YmiMRz5*-V8{gwCffR%R< zBeuA*xp}*ewXzo-_25OL)N1$G<3%}GU#dW&EItMCw_A%FTPw>ew-(pZ1Ju>xNq@&4vO8AaN8Oq5VQFmtGP?9?qD#fv?X^Ps zQHTc$C5&wTO=7%#f*_W6KlxOsQ7?I(RARlx%6dl0jC}z|Ps_J&-}Fl?7zMqK>_&GR zhkF16YykK~L9WB19}AiO9>2G*`bKH(-0!qo?YDeBDg_mp(>ZaTwm1wEKYE$t_{XhN z)*npfDN~47dSY0=OD&k-L@y`#2y(Z2ryI4p%^o(BclMfZMaoT(?YxZdF71zbhBTE& zqv)`=!#tV=Wo-4xJ7HL~IEm)wh2N#SA2N@vUf-B185RwE4L)nTB8&$M3N-%=?KFhj*`f$qYpPV2*wOvND55{zv7hImVk5EpYEf;3a z2ARJ~XE0?L!iY%=QuDmRv4sXxdF?T!BLW534v6fcMoBPB00(U;6~AzL@f+3ZbnN+J>QX z&fs3BeRu%K;?_>1M_P0;)zkp`AaqLq!lf%5<$^L)>-1;5dXcf))#<4zE)t@T6^f(Z zp%i=t8fX0!^=o76z?Qt}G9nCj2D^@LrvOpCc)_N;@& z7=2%MaN59nHr0IMBc>YNo)>L7zm)q>EvP|%LXqn^rKFYIkXzX>Tv{o&Frs8vP06y-OA5$cAw5uPl|dt{_J^wg_41?B&rVV1tWG0wAfK-z!^Cq&Ovm|EQ6t9)vuBBl;#5D zc8@md8im;}NdG-6&KCOYI?HBjs($sZ(-|^x@-L3*|1RNr3D6{my|5~g{v=fvc_~U6}Iuo&@k|)?Uj-2*UZtU#_@;Y;!=5kk~$V6eRb1 z;y@JI3~TEfHy2l}D9nPd;8R$cs@e~pdcR1A)^Mdos%wb zI7?AC7r#)ywGJ{6;1o5{Qo~h!`s7ugJ#p2;sbQ-Q`I@m>QB|Ls;i_+}udXgFF272i zqd#<&UtYg?b7jk)(?TlYF2SsT%TPXY#uXP~0TH8xZLGhxaxHPzw#&;jsiX%4DB}_l zvCVfg+};b!u{#?AyQo48HY9Rp-6fAa?6oUM0y)Y#NiVhXZbAbGS(;B}@GbPe7rSSJ zklQp4p#qt*`#LKuHR3-w&nIV>R(s`ou!DN(cyxTay{E{Jam8*llN*&9*pzX=UnbB0 zs};e0nleBQXMJN4MoUR%NRTjShmf{~+Z%%WG^r`LxDQ5eY})Qf>y3Y+2CC_YM-OjZ z1G5Q3p1vI*m~2ffV-=pc$;&%eFIHfQ>0NlQw0crBd#V+|XY2K>d%xWwpIUo|`>i{z z#(vaw3{R6b$!wOYyD&KnNTq5LC-wY`gY-+^<4J@uR+pSqKh>OPL#_4{eRM6^w)PFU2#%e(LI#h~EUQTI%r`lrEJeW!P$sskv z{rE*E8)Z+LzENLWya_NAa{C(}$bwml?nzG-E_sMIE*_lgezR2!$P9q6Tw|w?;G1jC z(@Wxs_^r}+zJuL4ew}<$+?v=U12PcJ?0%ov$J(Kx=<@e<_rt5&x%ad5`=V(Y%?_TqhKWV{s*3g)`M1htIknbQu}*Vl{NjSi{t&_Wi^17q)WmtON_);G=i zpq~IJjh8o8tZ6+;RVVEwD1Z}HA=Ow)+^QY2*5UJ&(%2S-fu2w|Dt6j?d)tj2cz;!A zJ5WmvSSc~h`l%|tJlM5Jx=xpHCvcr3`7{qvC5AgmXu?**B-i4KBYIJ1zbh=62sl+B zrb6MWvkzXZy>qw^U$WhD(B1*WLkGgLsH=AloPxG)Xz#rQr|@*#=u$1g31~um2+vJ- z-ibOSh{OhV%BW%{-g_wt1|VUVQd7nOFR;y*v3w#X4H`sfWVc9S9nDNAwjhgkV{vxb`)z5ptTDuPAmArQUJVT*kS+f=lH+O&aU;}7>pUKV`iaQ~p0l3VK@ ziPAJR5cU%m@=j-Lu-B0%r{#|w3H_~8(@X|NA=rgG5Y67Z7j=rvrO@0%zC#D}=*v_l zoh6WAfX!()TMownCFE<@aEg9T*KY2d5`KRr3uB_OpL1u1*pWl&y3uas2oj5x>E>zy zSmoKo!pM3Rh8Kh+jEEt|Fx8>)ibqd?bP06?}%{YSoxBzjw{oAv!&Ko3gGsWShQo2 z8qx!KuoAXz1**tW>NM1MHy^R#HzZw)X|>AQN^u^RX=ns;vS>UcD&L6X_<5*q@qzY* z^srICwYs=mC$@sLxS>F11nX7_E;B`yn9N3`_6d{FpUX^0$6vU~H>>6m75F&cFRs13 z`UcyLqupPo(P-Acc-eZO&3~z9ZYtlB!B{R?k>}dmiKa0bCVxfCi7Js+qOmljO|80k ze_MKKj88YhA1?FF92UQ^B7cf&v$$%UU#c8a6NBysC-z+^`^m&+QWE4MY_%~^~Zc&H)FE&14b7pQ(~CvD*WYV*9W8pXyB^l$0JB)u+l{OMK%8W z{7nunnypImI3i_MQ$Xjn>*x8C-rQJRQz1+NV4#}ec(^(>aHCokyVNwijeG}|;ZVlk zZ8mlwrfcqWbFg&(vRP*d;U32D7AZfxq)x!?cRJby=zWm;=k^t$D3|l|IDmgS|7W#_b_(#Pc}TXi+RHBrxgtPuAj%GhjuTEAynoR~szr=v zgQ3&X`TMQ!KR=n?pw7tXX>zn+htd$^G^5@9diu|%-pgjR(cs9FblBykg~Z0)Oz*U@ z-`{g!$_tyHUtQU%-`RQvisaWe7q8b7Tkv6H`TKDp?$I_fp73KN7@o;Tk8-(Gaa#{C zJjUCAh2aTu5{8H5DGJUyVdS&ma4|2{PsWr<4` zDKxpf_vq0hw?ck_Q6T_`r8ejgjk%b}JCel?2Id_G>m25!1yK1rl}7<+DCp6on#M>I zC62TNxI*(G#z-akxaj$Br**@eJ2D0}1r4k6RWRH*Ugg72oU$(B5TpIvk9^xRF{w@o z>2E*VJCH?9XSJ8Z->~ijvfhv3^0!;$<%nT-5~+ApHC4(H1WR2h4u z%)qLQ%~6IS3LVGj`e-DLSO{E0TlG4{LIc4fq`6%JIc&Hl_ivXn4 zw?EfOBfiol)Ib(0_G>~4Gs9jjsAk8cb`kjvV>>Ap%d3yh*I^_^VlDh_bLQk4LP|Dx~f6`fGtn z^Btgu`IZsp8&FiN+mtZ&bcmJGE^NAGO^kOEi*a%%!#Y$Dnirv98yIVU)Y#)5lHh%@ zTZ84>8_-tTx&t?1_06rto3~29u6nhezn(W9kb-=k&*q_QhAuPz%v0jU3TD_9^Hqg6 zPgVM461bAb3Cq&*E3f`uoM`;beTRXBtVOy`uJ(bVb0Dq(1PFZbD_aoQj&2jXK=O{T zq%vIGf8qu4$&27F^->Rko75g7=*H|X9_oXMSsR|C)Qdp_eBweJDSHFGOXLY-^cXJOPJvt1Y57jfwoi35l z)0fmw@~``WQ9ufRmiy$F%q9yxhBP2c!=4L2ySO(z46$S2Zw!m0IUxQS2mUFoXnLnc zM?%gkzr~W=W31e);R$!v!J2<6mW3q)V4dRt?u?hdu%7;zN4;lAe;%#LXpK7z zE8IXBa~OmIx9Dah7$}Fi#B$U}x!JFwS3LugGWGE%e%aR09W|B4E5p83?^P`;Z&*G zL0GVv7t0`jR?B4KHOV`0>GxkF{FxmbajNANve#9HDnMd?_?GM9ttwrexpSFq=}>Ox zEzG^n)S1QW7Mb!C&MacbX4Yy>DSop!4%7?lzAKNj;bvfQVP`FyUy?zarSiVCQ~FHTTkn=z-vk~zOfw~}xHlJc73Eh*04OlYm?_&7zS_8)A&RYB( zb$J4?0qNz!%Fvg}&j_aR3mRi{yMcSH9wp}NPF&YmtBiqhL%b9h~YN_S8;C~c1ovC8{21Vir zr}k>Sw6EgOnZ<~Mq}4I)oo(;4ZXKnwV3WVfMH9`D)nc?4s*c(mS3#NwCCCu0Cm0xZ zR=G@_*ciJ+2`HD3*>~gyL2n61sqR7kS$L=Pb8wp?K4XCNE(iLf$5KAZznBMRRkQWm zf1fYkk<_OtKt12{&%30PL$`5xi^p&&QP}}ZQHm$XTZgw!2NX~M?+bR>cc%`ZWm6)Y z^0q)ZL}lgX)A%TeLG6tIMcO2iuY&t$cGX_?mX}!}Ue8oDpq+CufWr)RgtyH{cvnHU z{3ESqrvUa+%xctf$=RD3$i)i4<(=vIP-=79Bk~*-XH$xQ0L^Qu{0%-?? zwk~grz;Z8;#}MCeJuthB!e*<83H z*$f;(FrKmi&f+ZG4nB-mMv=sja0gq~KK9@MuxM(NgmFUY$f3h7>BJo1+7=r>Iab^) z2iTh3rKojycMo2z*Ec_YP+2D={c3SD4~`MI!YV+3l&|rc7<~1s zu+mWx@m8cz{c12w>Z$3QEM@M)Bxd5tVyJld`}m5=#W0HRCjXSOnO7XdJczQJSNLvj z#aEN?)*)zec{E|J#>eTM+?dnby7cr!|Apx+oXkRO@dg^7eI+jZ#5oDiL8 zBG6AV5B2g_>u-S2!3$)wwHqBpyEXrrP!d<%OvL_EFW10(>K)&Kexh>Hr?B0+wRX!w zLbxo*oZ!-ZV#V;31F4l-%1vAcEteePGD5Ciu1T*SE1EGka29cTU;L(p^HMqqY1#-B z4xSb@L6qSbu`abBfV#R)ex`>l$HvOd#f?NJNzI7VvQRJso+q>|Qo>S5w?oDDCXN4s zw9>x*d7m9KHD@gdXqORylhed@6>-=cU>g)?!l{WW*3@%~0W5LkQK<}{$KVnPPHmc# zH;HGnM702jgu49%BO7zKV41RGlaYzvU1IN$Xnk^KtJU<1&_9lP&HboYN;0qLCq0&l z6m7cWL2MA*&4~vhSD2jqjJPJ#uD>`rdC7fWiXUg~ZHI-?U&AaVBuV;LV0Xibu`2co zZsjr3A<7=i=bRf|Q#S{UuKCxf$08`CF=NO3JH*0PB5kh%hJiGJYRjn!MD4 z0V`a3Pfv1J;m>qwT$^90^O9@{f;po2m1NTyAt(j8v9W&pmI}g+$+z6X>uZj-IjcRo zL?+$>CABhR3$JXitkyq{y)h1RQe5R!vt6<)&*4d;S!lH%z-rZ>Xtcr^%300W&Gg|L z6-SJ}KtdpJi5d06@WTmy9T0BTJl0DVAJiL8LbH@OLf<4!(&y+{a_^I5QyL@;`cs_5 zdu*amLzlKEm8jEZHzy4GpH$j}lc2nn^5I-t&3+JdfK+VK&wcm;YT>u3hos`nDy}af zqT%ZSl(!AHrTqzYgS&fC)C;-|iXJQmU9wpXDx?p3c)<9oVDu9FQk;&8{-99_I+Oq~ z*vQZl$smzlpLm5W&&CRsZOD?lz1fy z)+iS}AZJ{jJ|5B(#{8362kZz8UohG*ze+ULRNC~8dXy)%imeA#pE^)w&4rN^kHi1l zy(k=4goY(yWT13?2POqjN%LPGns~<}1`qIG)^~7{%{&iJ{M98yhD=`Q4bcP|r0VKZ zKLpVE)11WgD14&JspPmUDkU|$DHUfWy)5?Qnk62Rnje&d!zkX(%6r&t23x@96Wci2N$5}B_JTGV!kCq}7ubkC`t|d^{^MW& zb%KnDH#&JINAFuoDP7VnL^=Kj4h%-6Lh1!GmGT61EOA-Pn6G|ymY(Ud@A}_(fkgtK zr|D6{a3=ZTMSg`(GkWL3n~(HAA`_dCc$Xe2^X=nQn&{EtzEF>^JAZhbbN(q(l!8yl4-LuaBW8ZK0=l!~yk`T1knx(wOW=oS9QF~V zzy6F9a|Yshk3%^OpCYPk1>0PvB!SLQmW`)WMm)5w(c~w-k1hP``qS7i{}i#A-A{h_Q^q=5T?h(fxJ^GhppB{S;Ar{7d8O4BSz;Av1tz!6-*hoKm z^wFiorS*-iCBC-RkMs9a6!FDgJ1qUc*h1mn!t|r}2!04J3u8L%Pki*VpZ#nd|LEd! z;Fn$IxW;R?$U&rbeK)e7JF-ZH&phAH-TXjBr}L`Jy7H^!i#*q-qO_4j@Yp+;I8CP~8 z5KE)@rad0nC{??XP^6CRqJV*WW&sAO-RzJ!j6+3581fG&MWl5F!w3c zYM2_O(kUce?(rYr5NTeVLD*FVAk*(aw`0@zKp+TgZD~>&W7{zEWt*_182q}CdsvAv zr{yMAK`Zc^6CfcNBnrKXO)8WbV?TGMX`g9gr!1(15>bn=sItE^E<`e(pc#<~CtA+62{~qRW86io%HS5pjlKi9$9mGLZ)Y+Uf1wCy=@tS;D8hLUTbY*KIK&hu25VgB-q8 z$c|tZ?WyS_)Q5He`fMLzOp%t65OF3mx*N_WJbZ^*e8!y16_s{b8`#$9$Uzw-uqOzfX!f?Gc&Fn7gm=RopMpQg#}C! zTrV|S2Zz0|Dq5L@5$J2Z?6A+WfU!ksPZV$8!cxt7dI{UTzTZV?A|R#GcgzKff@h~Z zv9utepG(TJ^^FZO`9QR$j0Ss)IAZ$oR-lixX^$6@A`T4M^;O3&qj;r&uf*)DVPoT8 zA59_tLb3d>#Jv+A{6qMGQ-)9Em??JSxVfDU`TBD?fPu#lt3Liu{r558Y_zume}3Sh9K%nX8N(!CPwB3;f8542bZjT~j>D%^k8y*^FMx zlzI`bmAe?}n)+!aBc&dsHITFs^lkvwWo>^cJhP6E2Tvj*qjQ=~vZ+oxY+&wB&IAbDE=!HNyM)vp{V$x{PcCQ?~Y@2lo zp|>eC9Xk2Co--A}=9zx%rFBRAF7BAcRZ_}L?a}~!I#N0SQcMnwrr-5~m(y!OP`t`J zh{ikjiiZ7o8B#zssNsMx^>s$9tl;T+xS?sO%*ZX{^*I#c@l;$juFmTTWEqxoIj0Qt zqO?4Qspt|Z!I3+R<`GeZc;Ygc^s$f;a7V%<1^UcKQ^kcBzHVDd7x6F{DNboq;5<~2=;ajq24wS<>a)x)7}r>^(!ZK z0eUVl@akQ-2QH4&WTy+Wo+m!k*DsT8-A|JfDPv%#P3kiJRVk^Y;bZcQ9ws>#7PI9E zhClyb|UEEkJ@Tjq^^J7uc9nSC+THp#+y>pEdABGei(~Bqe1OzVf-yhA$qK)l|7w-&{^ig(8n@ z@Wd9qLh+myCjg9SnZ|c=s*DuXt$>g~B&R|k*n2Hr5e|9HW?p-dAx>Pg(2L}GP#Min z0-%2^ehgVZOi?-xkgKWy#>8HmWN3%6Kqa#fXC?&GN{3u##W67keb*@(bC5W1Lz7iW zQH?<D!TL#F#NYSSJrL>on9x3ip`+O%064IsE&W-F1$#y*Js!?VhdTuk9O|V1;B*) zm_KG^PvzP{iK|}S(i?n|1$HC)=N3#z=+2JL3BqOxl_3$N2m3*wb6^e2`0V7ZY1J@n~on)8k3ML)d4qv+f06` zM(u?msloZLHt!3%B}C$yJh*fVLM27FNRt6>pWzC<)hh$-6Q?_DiHg^fALgb|8-jF3SbRe?N(zSgjv_( zbNkVLyK{WCKx|{Pg{PFSpNqd*m%9%2R*6n32o4;nEQ~!=2*m0vi_@KCq?h9H)tq5i z)yMrtvo#6WoLuqU(yg&&?Z#1auvAvnAs4yawE1rKqC4&`D2Ripth`WeR|-*c`WSQk zY>^6$ivg;%gA^zzAASmaQ2C7kLy2>DvrkG>4;uF(K03znaAm4$kB(iKZvY`WZ4MP7 zYH0UeHRavI5AC&g@|yqZ$)kSIW1f4f{z~6VHE-V_&py5{Ti|cLFH3zcg{A|$b4mEA zO!Pm*^;8z@{Zy!vEju&JFgQ|ndsragoJj;qrxb$QcrED7DQ?5t;wKMC>g>9bH8r8> zP{KJ$c&W-iO7Y=i=cuVUGbPSaMDYQVLdOX#TD2T$QiQ6Ny0GtH!E5~*oGY>}fIew| ziNqs(aPDwCso#GtXL!3)$w^fLx z^Xk-x3hFVoQ%M=T(PRUsN|-aghYive!D}ex2FtH3Za`&CjxiwcN1GmR(`>g<4k)CkHS~E_7uW2V(-UV}AAfEutF>UK2B5o*Yw&IWSFF2G z2;YRSn@Inv5;XY9pF^4A(LU9r%0Gds*4Q-9t?DpU6e1oag9r+w<@LFXmC9%L+q+Rs zNhDrijp|zWexnoZviw2aQjgsx=SHgk)yv5vQi5Yz?vi04w$Z9fVpCm9Y^kv##6v<4 zFa?Sz0J})EtrP2uA~-WOP}1Nm0!D}>alPQ!tNjkN$D56vP7@{`%IOkSc3fiAJau{{LH0|6v)a$#{K%RmzJ-|qIprjZ|o}TyK??LeRI41d_MpGu5I-n z1nt(Hdr=RTKJd|8zWr`q4Hw+jpWg$CKfWX0TI={dnq6C{za8ucyZ-s#ln^p1MR;)P#1F-$3ng;N zhBGBCXgwMa)mqk!7cMxVH($-S)s>qoTZH{+tPe~wi>s@{Clx|B$feWqor;~e|?Csoi(YV@p zGQZ$pu%9nk0DCYnV2#KK+05DkXe=y~aq=JBZ69_D-y?MsVB!j`5yU1r0k zvNCfzm7<%`9xU{#P;2W^aqv6KTj?O=-=IoQIE|sdWSA7-H9g`3erWsLS1m7S>Wx9w zYz&Ck)RWo&hRuTi?O`s!G0>W_L#FVwRgL~>&jlL3c`5evfnyt3Md?1xZhpe226 z(mHLd8J!3|1dw-q-R=`G8XTJ8^Lbq=ly9SQ=$t$2Zxk z>LJTP!6@K~a=MyR$}~>(LRByI?nKGP6|hwppU}yoE?DsiUWS?;>TzBJW;KOKi5&$v z6-J6kS2Vi{z2Nkg%Gqhl+*n2_7S|v`+zNi^LebVm45OdY!w8-IiCp)Q8EcBc=|*3} z&|jS)VW>4E;ii8wgo;PcAKqxwcA_Q!`W>dmFszXKRPNx(*Pc5@4(!=br0$? z3B~PcvAfmL$gzi&1%wt20d7C&n!pxN@?i+vHi82uaJ6g{ndVs`Xa2PDl_EOyP7+F5 z)5%?P_qerlzte8D54*5$UR&R|xwvX~!S?)`-0{f+Y|jhzYa)(gFHQWQFPc4)kQ^wZ z?wtpXZ=m&~owp9!V7^^#W(a9DTPh^imz7XaYtcJ`?$B_5UT{sj0aXwXQb!QLSK^C8 znVmGzhm4w8MAxS@6*7_QQggZbqiwwPgx^Y{xcBo=zd4#PulNKvhqfS#wBz~S(K7*4R-9Ez`pS& z>&}kx@(md$nI~F5;R4}?gGk%ObH9g&bAzU{3Fle~$}hIajvP|a)k@{%ckW)Ty`V0V zS-rp?SQ6Q&9Qo@=yn#*Q!MgikGFezKrgb>6j*k^9ud@R?RuN>gnF;v@ul;Ad8m~q$ zp#;r#y0KSW5U4b4uh&DG?lON(S7rmereg+_48G^MbdlE+Nj zz@B*>mNJg{Qhc(vwzzeBV{ug<6@gKAn^tUgG|@chpfB$h3zds=lke`Bzm>U*mAT2w zJJ>@J?i&92V-Bdi)_9DD38dKGHu41u6`_!Ld+Rhlhh2Fxoo*5mrSU8jWX&gyKBp@CJ5hSW{pxDo&`cMCnu`igWsXqQgM z;tXT!L@Bs^FW9-{`2pA+;j-AWDB^@6BZOs`YP7?&5t&{3-Mu?}3evuNcj2AJ&f(#{ zL5vwOmN$x%Jl$RF|M!}JjooP7HS?+%W#k$XZjNnn>p;eY&&n$07TA zxDny@ry%;eKP8V^qel0L3TTZwSaND(IZcZySIcsT~t$Y%cOldJBhT0^Hku8C0`&Yjm7w z17qgp!l5TP-kId;J6hAQ7$v4~U}58i7}zwrSyXHO7XMKD+MARX6N~Q&TP)F3??%PM zyX+T(8dR*QqZTj+4bSY1v%Vw-Rptu(J|MRt$f}X*_$2!}Kxi^aE+!?;aRMc^DFO#b zo!lf2jDFlXOHzUO6o`S>MQ|saeK4m(OZ8DFmV^+u6b$6jfKq#Dxw^z4{<6BS%DCx&u z+T&$fWyiV{jBlJgW-~b&T8UEt`o!89mWek(nhs}U1Hf-3&b4$9-M4`g5gMHUp}_!S0@2( z{H}c*wmgPQ9#o1XXCWpdAF#Uo8}YlPfOHVnZ|iNdHxleFf=@V^%f&e-T7Oe%OdAM5 zYg1hYWA}~U8S2Uk`rizSjiW-8z~k#@1^1$9_E2!pzv*57({KLfqxjX|@-BjlF6RH( zRC_E}UD+&-{dhG1H1o7L*)f-AM^H*#T#kPr=`=UC7wu2owSw4x=M&v04QNI7`OjG_(hM~#6NCkpI(PS`@(R6>bVwf>Vi>=3rR83Cqq~j6J;>1-5IC?Q zul+>lrl(IqpS&jXIc?GIpI^%Au-IoL#C}CDw?>wJ@zUg_yTCp#Pt7K-m(-i`bQngY z2GJJZg_S4W?`P=lMN;I2b9z)E?T%sfRcAw}R_TbZi z)>pELnh5sV526m?GO0@)?a$B65xxt_*!Xpfz)^j%%CG4YU-G*RHiruz=$XFTICO_A ze$UzPyJ}VV9)F+tBUi*pYsQQjtrLiCED_n+QY6o4gs?r@g$o%zDGli{q(YM*OZd=W z<&Yu#Y)JA4YacX)@uOwrCJOmMbEN(~xK2NNN9r?T)y*|}4Lz4Whxr67U~It0C&pp! zMZd;-R4_3yFZ)qYUmt+}&} zMsR~84|Fht`XjNPG+DJ|5j2%g&Lc(f_y``iHmW9sRX&tgq;ja__S_2g*(Z`n|FjjP zQtEnuj6tP8QW#)+pZvKF5&oE_pH~INUeMi+pP~mJWYK2jlE%9Mtp#-GgABCRb6oe4CcpBgdj}>qP zn9A-r7i3ru1MfKDe3TiWni)W8EqLSjjRV{p-2l>%-ciuAS?ULKg1y(oosYhYm$dSo zb3ACIQl|`}%#phawAF3EBr|-zUnawX95*;gGuw6mAbkOX+ zca`yh4y3Dslg<6cQE{6leZ#0oR)ZrT0aB!8N-Yiw^8116eTaFgUhN`1pZveU!qXrokCYlPOyoll6)E(?~zZNMrY z(!iI?!Wf{W%`&Pb2-PX5%)y8PADuR>TJiC8c~*OTVgD`(xoR~e9hswGwSIj|>oy@W zULDin@W+oQcg=oA{+eBma$sP$JQPHIQYRc@cVxqecWU#6IH@jOxe3qKm#)qbWjV1c z&LKU;uC6KeS&T=A-pdP=P)n^7?YB3}wEbBK8)hlT57Gjob1e$L-Wug1kV%@L7 zC(RCXa5;1H_H3~p#{y#3NGV!T3!$?d4(agx@lg<`bRY)9Q4LdDC-#tad$w3Z0Ed>i^Mn6)Si5tBYZIe}JvhgFEqO2L~&BaX1`T zyL319lu|YJHkyJnNazQPZ`1w;)!GLd<|Vd#H*XT`j1VOyySo-2zV1c$8au~#h}F6S zm1=mst|2YgLy|dxN2LfbE}Pr2-+()&8pqfq8RO2QOHeyErY=JSe-Vi(_@tXF`@!mMct{tFlcI97mn~r)XkG+Lk)L4Az=$sOA6&!SQ$U0${#OGBA3zaq}Szf4( zSg@dtAs5`Z8^yhVW71Ex68>1lN+3BYGWvXh?keGg{gfNq3x2NCe(ulyx=&B%g~(Bl zFlm5N!@6L1h>Bbuzy*x3=0vkPOTJOvQ0>oIoydIx8J1YXl+YvShLF|_ zsd+n-dOj&nap})dOnj=vW0;+}bmu6@?Ix+qQSjh?)QKQ(*FF&$2Bf~Y@!~82r1+F& zUdSF?mc}g$>{=})tQLoJ`WS3)f7UBAl7XM;%Vzc%$BnL6$3@oX&RCHfhq77lRP0g1 zU^?C)+0{*~f_UjSwP5WX8q=#x7vVsJz*Z%dz-vp<)3oXBXUyjcyRX#bK%J$*%s#l+ zX&)Zo{Is>x05l*5#bTwRQGzSeWA?~Msbc9OxWhxR>Ry?PJLWuJQKOP?L90v=o2|QT z)jDp%NyhiognA&2cFX`rr_lq5rQ(#}!_lqiDEu9qm?#I0r^Um@43k6Y%}UZiBjI5e zM!>@!1_^s!FnAeLN6z3Ad7}jT!@Mj}9a%>(o(cbzqhfyhbzDe6`<@pZn*%uELpAdA zP6Iy&7fTm^psc>n=wPHWd%Q44PY?Ag{z(n@`R*HU|4KyPvpzR|CE9htg56Qrhj#-~ znn3CB{dljKg+)=7z$omOg5NN(Y2Jv>&WauD!J_n3*pWwxUssv6ciej!k9r> zSFxrLq}ZE6keUvOEjGv>Uc7V#hVgXH2}@@B&I$SJ@oYt~Om>T;RIAB)8iU_sP|<9B zSo3bmX-%T?hVKl^0{CeP<)U&plgY|Crex5Ww19fmVPkZWEW&E2j6~8;NeowhrFTOO zlB;BYafhT}o(9RQ`f)O8P|e-wpwVgc+AtJvEak%>@4irCGW42TAi+qvbA-;3=ol_O zjx+n5q~`|=*M`~lUwC@1c;IiW+_(Wu0x}Y$O~B?>eeqhbejWVCY8?jin5FMj;AQ#7 ziiNAktYI(QvSSfOZGaoK&wBgF*^1!R>@@7PH7G@f2tmqQ5k%z`mwIt&Rk_}f`%SeA zN}qaSGSS3`2-ba*GHLb9a>FHKTHqMe+sk{X6t18&2@#lvH8LW^vn|7PO8sRSWXFO~ ztBz&Bo{Ju=(QHNVw7PG#{mMaeZ;vz(tpG~Ax9`|%pZs8SsdQSsX#ZeRe)p!RV0?93 zOGA*&Pm&=>d77sk81|1(e*CPi3nL`-mqrMC>Jt7GXZ9oiqEDU|E)+_^>dLG2{5EF7 zX|D;;jY^qQ2}@Vzp*z3ZIPT_gGIQlhe*Cx8)0N=x-~bjXVac#1K|Y@XFKv`#gg%Zs z>{?;9G5eZcny{>5W{$+JB$zvU(v+&DP_9su-#O7TDhnPk66A;b@^%PNZ3Gdx0+_So=@*c({F-{O9>%f{T0D<&=P_GnM<=p9+&)*{9<9nQHW7u&X! zfdn9Irn_n&fixh2A%l7O#JiN-!^oKE1dI>8Px8J%`x6H;uQFuAspn4p)|T_d32toW z;_%BHUhmA3Y3hK9%|$4-PS z>l6JN3Le}`gWw4PO32uRpNGgVXIh>qUOBi3OWGD$Bf@O$REEKZNA9(0lW1`+ZNJgU zNbv#?ESVCMtAgBEx()K@vM$%MZX|nOVMpBHx(1{=CIKQ0Jw5a3CS(puuv|!UThCtWjbD1trM>gb_h|qB`CrrZ zhms!c9Z8bo(H`seaO#cXrlmn;kU{wrL!AfVNO`#Ga5dfP!0QUzeIa$z7P>L;hLwF#XY)mu z;W=)zCsJI$D0zb7B4pN{>BwYbCR?9-TA~mU+yL$dw!%#6TH8qa@2SZde^B&6d+Q5{=c9qmdUR9ngEnk+R_ zfv=>IvkWpe^i26=JZw|vs^~qF)%$!Zm};D4br`x?O&d{!EOMHhu{+$`=KcGO0G-w9 zK<$OJObZ4lAXV|07Q^>!IgD9M+gBF900$rac&s#L=jmJ(nE!hUr-aK|oX?an6Rz*- zq!`A*gUGBChPeU%?KdkW;vXM`;`qSqzTO9(4W5ggicSSdj|Q_sFrOQ5b&Y_$hw}H0@WJua1fg<#G-9!Mg2py9CcVeR4pg1*NZ)1@Eth-F zYFBvbHPf-0VeIOl+uT3ci%9Je|I`CXDK=Pup%UQJhUtk)DK<91%p=EBim%bHg)IWT z$2FT3Di)f++p0#H&7^g7LbU=Z8hWw$9fNS!J#E^on&HqH*@^(XQH_jGFDr54c0 zP~JY1iCyOSCTV)I8Q7$eH;1w>_-TZ^RQQylp`v}trn6B$C(c~A+AtN(u2*RR4cI6Y z4x{cTUcgk7Pu}6%lsF(8o^qw(KS=#*s2#$uI*wwsQZ#v#(QxSToYEt28ez{gz2dQ3 z6t5g<%JNp9F{Bejngwd!^52PSdAwR;g2($89MGxrEHfIwCYqzKASQH174{N54cqT# zXp7|S?KII6lh1%Gd%+}8S5jHX19dZ>zi!Un(huTnCiVuo;W}BKyb}|7>iK$U$h@bk zXh*KuaRsC79@Sar8+qfBDFzU z8%d*=h`v@AbjTyUFK)-a!|54UQt=!wGs3abp{ayZ5U2uQC&x;|mID}Inpi8Om2k*n zP%tjVz^YM5w%y|Dl|6TUir#neG52~Ucf2BKz9;5 zRUYZ}Afh@{9?`*GV<*yjUIfX*_Td=~?G6BO5TOro2xcZ?z#pi;6CcG>LjNh0#TJ&F!k|F1bptKF>yN`8P>r^?&bs{r7#p z{*U-Nfy)o{_xu+lJS&e8IP`4nMcp0n7LFo*e?CD7?oyfz3goPmSpri+&Mv*AnO#xJ zI4AO}(F3=`43A-Y{Diwh{`dD!^Z!PGlAJ@De6;zj?&2GEz@9k|jcHXl5 zc7e`dPnkl%+roHnXr3L4Gc5+z)88nj3fEjgC;C7d1D;V2P-ZkP%*H$@R=)3TQl^C{ z!zVsK{jO9l2CzG*lqZ-5g@pBuNvbc>6Yocs2Jexk#RfiolkNa&?6mg}I#IV z4h~!P87lfH6=}`upGo_OJM|ymq`arE;v0uf2}X`(%zq}hO;~1OU+QF4NvhRJQ$T(n z&X~kFu1{-dc+Y?uinAH=V@@8=*)Q2E{ug7PIgRiLGW zAnn8QQiL0VHXOmHe(dwf#!ihWQ?(&S&WAlEp}Z$7z0EkQh^qQ$Qc1U6Z*hrL z^8GW{-ZibwLND$gmE;nJ^HK?HQJFd}e#-CXqrEATPt!O2ix^qR8|^~Q;Ss<5MWT3< zuxf6?KLRr;rSeRC!NpXXMBU6Rj3irTXzCkjy*#V*j7@mkDuSwgENl52cUBzR9CN|i z#mR!*2A;}?mN-YfZ~=1p)B4fs_WE43a(JcXELFoHqOHGaJH4^zdiRgrH>x=tQT7wn zK83K!JpV9P*15xJmb(5^bCdGhr`pdxJ!^rdr3F$(?&)6jAxT)ttz3nO3wBTbqAdgm z>5I0<3Bvn$t5@Uw4&g2BHCp!$8~38-Zf%cVC*SZENWAu+5iwCHu{9sMP-&$}$*WJ< zQ$i<7HVNC5D}-wLVlHUG@vc%=h}X*?Zg9Abg7F-YSNyA1FXCpR0zHq3%Io~X`7@Px zn|O1A7s$eoXzNlRBTeysj|Pnqoo20 zDnngXBuT=Rl( z_SfF102A~a=cd0F!)5a>H2^-oMN(1zs4GP2O~YLp3PHEm7gttgUKpDUScPx;*0h9* z_~RxpixSw-V5p{j7U)?Ee0W;mvnQ%5#4RxJglqfY0Io-)4%i>eL4_Cgk>M|BI@UKf z=x`t{&d1YUp5eP|i&&R&itv#OLnSJx(v&7iAWd3M=^PUg{Ylc~Qh7qjG>I-DgrRHv z`#RSvz3enkZD8w{yw$Jd$}-# z2AOIjOhkVZRvlT;%#29-6p!s7LY$^OXzs$bMVmLd=J*D@W>A0w-Ij5)`;|lRNv(VF zlnENyqn-Qtw5-NeY~(v!;k#^v$}>N zE(k=#kg7l0Y(8221kL?{KamA|_@}v?d{+059z9IH&F%8XAQ3$GiL^9SFiUe2u~J`H zntSTbNKHQF~B8nc1yL?xDR^yaCaozEoSB`lN3k9Z93%$7;$D3W$yH zEzSS&fh*mTJk$JVPGM~jKQMief$00`4u?%@Zcc#)uX!ixbRhvKmiRNmy1`UouBW`0 z1=VrP4+y+_l2#ogy_Mc5Qk`@N(}7@ndpp=sF30JXM0Vy?ytHWDW#h=>b>qkb5!RF+ z4}hprH2s8BJg*+JRUzJWo&J!X^X|vq)j%-hBe7S-hQc(e8ge`+NmDteZP+)o{sNT3>Mq40C!Bh2U>t%QAdE< z*ju+zidQ!H?uxy#v32*tAHK!D?2;DVGs$x}>wP7-R1Pn_OgdEBE>)jUq7n9*Z$*2@ z#l=$oejbvCN=7)+cg8nvEu*yovwv#5AQzU5B8&nqCXJBwH6&O=cJ!cvnRC%N5%m>8 z;b^*%zpfItx;g|apc7C*^uwi)%nElzg6_ zU_GPwyZlIjDe>&DZd#!Utq>LweH;N4gs+o~6Ai)SN7CNv_dIe9oYdUvq~+xW2cdAz zzGlQREr7J&Ha*Sz$Dn{IW>A+ud*KbZu?kvmEF{8-P!}#hyyHC6EPZ2B#T;vT8tgOT z_|!cNtrQ6Zs|?H3@@^T!R-hun^XYbZxlDiQBmb64!D}m9udLsO3(57@R<14N9^ua*YU;f|UR< z?JkV{Y~;41IJ`6z)fleF{YEK zumDZ}=pHOxk0%(;JYg9d)yO-+$|g2m zxYToro?*K{ujVxG0~$IY@|h%(EWzLcB;$-w>SW}B8H(l^81{5cdV<28NiUp9A}1*P zV{fgex+|;P4bLX-u(WF6WPGZ7`%LECnI!UT;*zj2yD0~bGe2&>#OzWv#}_Tagsg*w zm~QZne(1{0t(yh7nz9%pgkH@3+{LIrtIURH8wS=Y_XCHmCIKyDOW!0>KCbbE)L=#& zI-G+8=>)eJGjJqJXWz>X&l-Q<*@1vv9ND@~rWHdM^KJi=^zRXJVyf^FQZ&Tx%$02Q`c})R|QBq?ubmj@^k_Q@LSGv6L8yL?}Wt zodLvL11)^N^*1A?T3v4tuo^;j&E&VeL)7qb};3nEBMFXpSxbKuPrav zH*vFpyZUCZ{7QZK)#A$~s$tLHNY4t{UoICllpK{!5;gRD38>Tw|L%B4*WCCNNg}JI zaV_D*yR5Jr0e@o5OGd_HiKjIx5qT2*)sG*5LXD5qQo}XqvzBBXCirf6Hj+U24(>qF zY^Tu!`3uct12p0=Q}e?;lE%R~J)>btde@KIKcit0Wa($IM5VOkGa7d984WuG6xnFZ zju}aP*sjbaz$_A@H@u0de$!VEhgX;Q@6IXLP7-(I4T260I?>&z1EBG!8yrxRxUpdA z=b@D(V@)Mu5n5`Rd7;dUP@CPnszb!WX}cF|M#UOXkJ*$^$#Mh3mdfpfNcPbi<4%uoq;#3!CzB?Ckq<(3!W@-NZrWLvMH%2i(Z*F!I$CTjhq20v|FbR z$y_Sbfe8THLILU`-0{?P?qC&1vI>$dC=e3u=U#mA{>4h=<^4{yTL>06gD!m8M!O4R z8@mNJ0dW+XdOArbYq8v=->DrGsCR?JDI&!;Cwq5sv;%cj1Q&pah&~m ziSgs8$%shf29R0yTj8#9X{sR zuwrMO1i*2Bg_L!)W_#&Wfx*)9E3f{ZRaIaGi8D(u&dA&0A{$Up{AHC170k)iKG3&V zuR_T|!myuyg-Xq>**O%%mJp>gf&j84OYRwkf>}Cfo)t8Eo=9D=H0(tkMX|8R3Sj^v zF~$e5U4u!(*8OHT!2gw?7j=6H{j)Ggi3hKkhzD!#2bJuIDe{q_$ zUj6JvWXL$&k!wb>L^E5Nk;w4(L*NGd9ny&AiB&?8ZcaTI9o#bNw3703vgs>G;4&VZT| zdQ(sPJpKG*o2Ob0FMDEU%x@jfpS5$sG%tN1SGqlMkP;N%;?)yA2V9at!PI#PTn|_B zH-fvp?leNfYrDBkiO8>nO09;f=uv7)p;l*Stfb_;Z5HnDSWa$mi#*ryBh5Rf2MNvHxI(K%5T69`<`a>5LdyMT;JzmBeR5SOXHm9|SI)ZY`L6^yu61^?%{^J-k5cm$+A_ zIq`bXn?<6#5yeK_H@`&Pv%KLF79lh?n5zvK2j1xdOt2PK?DB6RbIF^jH{N3>#N|$- zwcFlTroucb$&Zq|o|>b?DH#~Z#PC3r8FpHR1%uizY*mJZD+U!-&-o)5l1Ht3z57M@ zWHn5Hg?#3dL4P2Mbs}}n41c;h#6YAj%H<5p;aE+o;b+F+MEJspHk5OM*GsKPZ?rL} zMw4(dZ|zfQ*lAh^`%{ffSxX(rFG(Ltlr=(RB`jvhXG^oR=O4sgMW z=>dKKz;`vigPCw@!GIYz4two8?=*G}5BC9;-E3i=?gIh1v6nIjG6yOgTg4LqcF0BK zFj0lE^f|?t;yfyqx#9Bw=sA^Zc0jpAMW#7|sYWUX%`>MKOxxBJ?H4!d4LI;gv#vzgY1X^#^KL`%V)+v=2qMm#2zSR@AX*sZ1c2d8^{YLHffgyyO*?X zi2W7Q>1YSNp_GP@mDW-*Xam~B1^8|-Q~8&j$b2U=m2!TbO+9Gu4Y^dvI3fFRfH^4a z2tg^?1dNC>9u0E;+}ho6aUdlxLAdd;aq?r2GudibCGmrjchvGrc@oyq*Oa&Xj!oeD zMO4X}v{j{_*3uTD?*W$m zhaI)~$POoyOyx8hhjR0Sr(%y>VuG&RSl+?{sF=kHK6o6)WwBGyRH%1+5Vh|X9ZlDx za-mQvjd3zX9j?H7eaLrh1z6FGtE++ifUKRR@UqxJq;qekxjQ|${U|mo<#>3F77vbJ;0z46?QFIjb*4tO;J>qACjw>V8wxnV>Db8`VyP}S>ikw+%*nc z9NR$vnf=5Va=LbVwfw#BZR39q zRsMzFFJUm2i^ad!iu5=B@I72h_+SFY$#rMe%iTYwWK_KGeeYVG;?wWzyG=wg>7>Rk znb@iXiPCmUoxi(w`*w5nwe>BX5dW0Fbw*`wkAmO*}aD3~%tninutHR5(2To(`#S_=NvBdSGNQJB+{morUu za3#*KL#S0WDKq4BFfBVxhkW-;o6gdEPW6kbn@>o^KbR}evzg6I#n6nynGVlqGn?A| zcrZm#4J8=En8ZJu*{9=w-(NiC`H`#C!S!sLaJE~SCrR)U+p^wY33MBdJt$5h+n zm?s~aZOYgfkJvGCvYaPt--qtUQ}Y=Gb9b2;Qix~6-HMgEBM$fa>!a>*6`Hmy%sP#D z=rr_aXxcE46F$2Qa=#9^eY^a<|IX|>?Or@VK?hEIPzaJCW;Of!c|M@0&U8^x-SKRg zD+=*!m>cVK{W%PCRTY>rXXO`%RT0>405Y0ze$~e7*9^ zgA^}E)MD$4&oi7BTQSo&hpS}@P3IA{OfL(4%l>)_P>Qb>_W(R`2z|`vZfy^Wx|y0D zE5UbDuJ!9FFQ34xUpuEfQ!7n*JvgTf2PXR;q=i_&etomPmGs_;i&oV_yE38ShX3`mvCoE2l5#8KxisL@WxHdigvf#Kgcp z8hb&#kbgxQacF%fzQq_Q2Gmd{l8BjjVd9G6iEGr~>YI^rO!nqi z6vMol2*gWq8-EvBqBN!~RI=go(5X$y3{1UH!5G`gBv0?0yv&EihLbBnBxZuSChM4QL>#JIUPiMkk8PQECJD#@~2cNJ9>UB0*qz2M+YW40jN=4n5olNQW>r{nyyUyK~P^bhhw;oiM7peU&=B^k z>AiATWCJXqHK-TBY=Fu;y?gYYv5|xYaxV8=P6c3N-nF36Icx=AIov<+jd#T!aG)vE zG^u%aVQN=YE`FQeY`5W4C4y-RE@S0X4PlYjlW)QlyC-;%>Zo`WvU&+P`{s%hBB!E+ zaWau}+HPK$NTqLF4deyfq@wN6ZotNYT`de{gM)Ub7j;Nee$7o(*chcIdX`)NfzZ4R zWkdcN07j7T!nu(2x;ZawKR_cMu31aSewH5X&TiDH?MB_5?Cm_zJhtK7Hgmgw#_p$J zq7qw%V6Y}#PR$D=4&71KFab8h4Ip%&wED}+8dUUQLD2|cwb6s)+%Gr29JnCSD!e-u zgawB-^El{WP~R;UE?%0vv{NY0l&8wmlVq`6nXOdHmkEaF8bRVbzg*UH42>=7s%7N(B!_s9;qBw!+(3zZvwVH7d$>jhWeCr#21i z)N3$gTY3Y4AJ^)e%jF=_zvLpj3=|N0O#2ix_zVAC_UW47s?u!NHlj*p3p6__(qAlX zvD1g@&BYCN6#=umsM6c)RVpnwL#)5P71wmDe)E?0kGK`>ALx`2dgYo*i5yfQzO~Rx zCWueQYy5=^c({G*S|ufqjg=c@=jR6{*9KU~Z03Mozp=6=R?PK4RMA$WWNfZm(Su1* zJLVYU#4JJGe zxmF9wyqWKJYXF8&C+OC;JT9dghPF}SVdo$Hh>_FJ#2f{Gr?Gbk1a2^9W5vqr6~ng1 zzo}o?U;2a&Z+_!A;D^CSBlWIBB4eO|0fkZy6NvL}<5(-OWwd6N-NXH2DRJU8R}sAQ zj&fnIC;U7du#^@st~cu&TQt1agWi0MA0uW3tW1~N10Oc`jI zkQgbXr71_K$p$habLrrxVc$wg)2MHNdZ5#{Yk;oM!KVfU2MKh-PxlF5jMFcXTqHnk z;AH;x>Z;AInjO7(tZ5sHmxylI)R=r6%?omAES86?^o%M6l2BMv$#TwSmou#u=lTV| zsz|nM^~?Rj*QP4Em&}Y!mT!Jg0=nOl6_k@>u9DociN%Wi;@sL_!A{t02G}zUyt|MS z%in-!(E^ORW8c1JSKtOfm;&Y$dTyO=)%D}*2eZkauyYl$5!2o7?!eq_WRZ3(0V4%z zM=f%`Nm!GpP%iWd(%Y&w8bO00_>f*aJKfxSShgl%7;h}lak5(`1N!|&vsDJ-nYN>^ zFK_8VNnzbZcCI2eU>c_fa98c!X6s(<_SW@qc002BFVi1bO)Im-hPU<7cI>=LqQtW5 zy$VM$WTMd6=1TPoLY3BZ!2o`sZ8aDGr{-5gZ1c<%RkW-MtM=_O*pPBmzFWRmzF%&} zEvomF)yCc)?<#FzzY0}TdM0w^Dt3*t<+<|Z@;pK=t}U*<@x{6evjbR}W)Fx*y#}c! z$jZtuu<2jDUEeGgdQ}XH9u)+?*oP8F6Y_6RRS*1k>N&i}>ma;U!G|E^rql%pbjtg1 zyAyS63pRDbRb$pI^BdT?%x}B3DiPCs zdl&Gyuj@W==tr}L#eAw`uN^z-UXMs)1{^{&zz`2ZAPIs)3K0p=c<2#DrUt;DmGdJ8|1@yZyeVslM1s+-$yVo2-^y?f_?lang7-p zrWqXn=tn>O(T{!ye28>-LVG2cU9t0@%w}ntEn8DB*)x2C(_x8$bn>CRUc&N8zhD`e zoPoH)fAjU?vJ%#sbGxs+;^^fo*bWh9?SlyWs>q^bKs>Ug z*A;*R!QV=IdYe_Rvp!(&0|8ICQcw7pJd#1)6p&qp;w zkGdT1?orP?gWKq~`TVr_;zBFFdSv>w!+v9Osz`tH0RQX2o><7tFEjCK}$8O zHGHcn)hssfTZH(y+S*Vszl$qbcdQr1>TK6xX%NN&;eeu{idFnJDRU~Ymvj9KsOLCJ zzj3^|RXnaT>+1p6g8CIoL+%Dj!>>K`t~Ay+;J>%A(W*7-m#+qNGf3y^hC=F_l%c2= zf(>v@mV-^?eCzJ+TNxyVP$LFx(GVd;)YJ^{f3-$1Q~nAeLl;%V^#eVek@%@1V-<|5 z40S5;Tf=bO_G?Cw!0+%*tR@sMtUHSiZ`-Hpdadp{MRR_s`{*Iu(GPmA4N>f=_Z^El zY)}XBz@-^N#B98x6XP!hUMngBqX3sJMP zxiMR)Uu_^6lH!%d)0N^TN?fMzMucWOR2GqKP!)kR)w+h^aSa}}`5mvw+=iGQ$0Wf+ zm%uJI)_7VWjOfw`{yHRjii2&+Kw?LObtwulLk-8Xt+olN%;LjG1w_?wOC>uF4NQn;aA8_3J ze(-RqdDeh+#qS}(i+OF^<{HB-P5ZNtmWtDIB3(&)+qoNssP^Z!n|6Urh>LdbZ0JVl zY)GCX<`jxtR$r z;q!py9^OAm$>}O-dlD$MapkV4svcw}&sBly|1^@+Bhhc^x>BqAy3 zJgk$q0`~2o=hlhuJ^bvc2q;71L~W?pTtD|r6MOB!)P8^6(!|L<(8Q47L>Q8_;?u>W z$4elo;Urxpa72cNK*TFxdqKAyxb&vuA@8^=SbF*{P8D$Fu-e$d+;gouUs+h3pP61< zte_Ng*J`<7z7vo~_U;6P7WnK#S#}t5Ku$p1wJ`jVK$3jV4nUmKkoFEHI5s`WK3!~h z{xF8x`780krF&-<8NelXTQ?_uwlx1JzMGSH*?Vne4v4d0_RzY$f{Dh4-GzN?982-0 z`3Q>VNN_NM7Ikn>BEZm4{0nx$>-wrQK6M4wKZBHuuwymqkO#w|RDf7{V!Kfsnm(!S z9Z&=J8uus<#KjYa#9=6LlN0y!dS4IDPvJmxr&x!SmfkTJi`xg{vvqVx96aEScxw87 z)qe#%%MW6!b!xq_8cePS>y6PHAD9eQ*+)t9TJ_mrl@AF1{24!R=;d*ngq`xo!xKg2 zAyz!1i499{tv=V69m{6NZmLJ|HmslG@bH9r4S#mN?fl%KxA%nsUA)~rJe(~c-`t@> zA9B+luIQAhvU3rfoiqCPjQY#v*U8?F^6_tYZg_YHQIV>0F13C^gOlMHatYO=_BDhf zvT%trQfxWAXJa$>uHwf$$x5{e(J}I3 z+p0YkTwbd^5ll9oy5g=^Y&;2qz}Ncp($Ympg5ZjNSKLXHR6}@;PFKZsEjq%v((_?e z{rpuc!}Q_C`g>!t4nyLQ!6)d@>5bW@_2$$Njx}F0&(1Et{NPJ_ajZEyB+e4Tea_4| zIGCAPSX=;y#T~cZhO(L{>I~=5@S~l!`KR&3$LZ*aG(2&Xik;I8aT?+)rI$0@xtKEe zU*zb!eL*L>N;P6q0j4%UjrytHmVD?M>#D|akt(T5GtjEXNcNJD-cQ^p!}eM!;CN%y zWn-P?azZejM&2{eB;+zukt^!_g}F1p;qDGjsFC)#f`%db*=<4JOh?_cf=Gh2+k*6= zIjtm;L}jdW(>m%^0?VwLn!VL3F0=G&DM!-%b_TIW)D??fCq6pNXUi%yRu&(sRA$vM zE(9TDKN6KL7Q6iRd^U(|HG|Doy2`_Gc=o;?Z00m$4~)p;MdoeB{#ZUGMHt2>=Q)NA z*GEli8D1{y9BKI|9{IrYj1*`ya_PkWj4&C8#R)dL)>9`GPd#;|Ir#zo@Gpn*vR^Gm zyq%2>i(^>kO_>aoZG0BoX3IY&7qu@hw_se~tg-yh2BO?J5)b>J_l>G7&%>e%(W($P$HI~L)?iqtwpw7SHP%0J)?$bLb%o%Ccxv`g)~+NL@pcWsi{$x!?Y;E%r!uIg z_q)F4C;x>1d7FGSwr&$Z4i=2^$%8HL^;{aOBZLE$DwcRQ_M#h@0MiKj)IomcQ_WPb#$Uy{r?cI@5{!Qfjz(4=w087Mnr^$yN zJ(r5UznI?lX5K}Dkh~OR@<39U(G`=DTNfTqdH!y~L*-3IA^9t)X7^?$<^(!yL)S8qI^l-b+4*V?-ZHbNf=C(-EaGH!nR&;K9^*T`Y zS2uf?*e;0d5gpS6sY%Gg?#W9;WbZPHYhF}W4V^#C$eZ4C0WrGO_{QH}NxfH0#ddj- z1##~kpE^32@Xw;)1j5HiKGGTg(V0sOrIQ7V%dUFPCYD12_3s1moe$8Gw_e4qkL7`uqbv)-sgJNMj@~o4+VHG{p>h(1@kfNcxss%Z5wnG`nMV^oAmTmW*@bgj{mg{Z9100B*wNWcM$ zh!cny4+mwz%S-BPwkwp<*=@R$nYO)k_K~)oT^3wIVz|b*gkZo4ErJ9=J;>U^wjv4o zG$+;ISHf$VmtOjuzMy$F^QH;&hM&*9^jZ2acQx~VIM~`{-jt%|0>( zo6ke$6GgJ1aigHl%|Vvv{45z@;*dPJhUY5a98SZE)Tc@huvtJ9duiS;Sa9e3f;YM; zxLMLHQ!bb}npYZ|LG5b&@)N<0%V21(JmL7Bv6#0#LGoHYID*$_!0}nOP9KmaF#8$1HJUR%EW4pWeKfOyVITYIH(SkM71|pgx-hd?xx9G)xk^7Rgax*^7hewp zGiTpmYjZqj`?ZSM+Uwa?2{e;@d&l;R3hHS!eLragdiEUjt;fd_pDT%>2xQF+vOI}8 zNd&R-@TCh=m`8BS3S(nlC*8JE>r4 z#o$k1&S6)<6k2+2pgU@Spe$DE#0iJxqr(MYIQQt?ShOGepUhKu^sxf8HSpLF{Mx{T zpu}{@4Qo53M1$Tt;|pPn2{E%1SPceMg83$W6`(S1N!I$@xV4|ITv}8a5d&*tGZ$wT zVS5FEk@R_+-cEkwaq<-3{1LH=6FvBOHwJJ&q2Ol)o-*0MUwEc zb@$F%oc zShA&Rp#`7*BD|zvn^#&jGTYz( z4M&eQRsE62euS26fO;|urxa|k9Fy)z4vhXOoy;DkG}H5Q3k&HsuqnTp`svMZkl184 zb68w-+oSslvEJK#PIV3Y8zF-yMlbA+E_EWStk5Id&5#;RxTRz(dQl}X5{U5Yfc^L_ zsRA`wmHKGfXyP|~gFk_ZLyu{QHIhgIF|d<(yfgx#n2?--_f{EyRC9&8K(!!KrjEy_ z>iD@P0<1W%hmIo>93X^f08J%0me9r=NJJ3MBOZozN7ip9ClYukqBQiyJJZN+)wrjy z+Fj&*!a806HQ)iO);wXsHiUk|co|AvXTEiU3cgH#?(WjyNOE#9dLr!vgl5~lTLc?A z*jifDR%#15ZM=~-YY?Errj5llv1@bNHw0l9hkvw_Gb^c)mn&%>1gJ3{#YZ~;6*71^UX{i4wwBuo9UC*R8*V(|d8xV1;G@nosW4cBKO` ziVf8dERvuYU@gI5PCsy{`I<(y(6%%*ROxvI89gCRp2>Td*U7;6<}6u`l4O6-!y$g? zGshK30J6z*Y~lDfq|~-X-i3U$FTVOl;@ zrUV;qu{)a1@X^#J*1-wK&5_jO=If)2(EmT)ri+e~)q30SUe}CtI*Iu9ll{3++DnGf z2j27O8-j4^>galhR1fuPM#X6|q&GI;uKK|Tqg_}&e6Wi9O^BaeobV|QN2I*(*aY!m zWzPNIMc9KGfy!C6nritPGY$!uSH+rpMvK`Pq)V&~Td`nL<(rWZNE0A+aFkYaANu~J(tsBLFUj#ouO z1-4~j25|xSL9;XSNg}>!lq5;p4m-zc1K0;63Vx~^QE(D0?@8u+MC|4;ea9!{QhuhM ziw6_$@7T>;(#JGRx3{NNc8ihaVp;i5VWu>%fJnQ+~UB<8hDB-Ldi zK$TEenA>W0;?_txZ;6}?mEgVsn*g&c9zJ}ej6tOHW(|yOvI*D@9|k9@;3^LD_EKZB z6)6$0OaN#S!iWIMwI$%CgLNFt<5@^PNZCoxQ9fZl`8J^!%Wdt6Lv=AwJ9JpMP9Fdx0VLjXh85J zvdX(lO>rSOrthAOVNh>VP=dM@l!S2$3v+Xgb-n_nvk_)A0GHeE&g zYUl(veSYr3g)>vr50Iu?kBxsnB$G_Pqw#y~_gACwF+w$sw;sIw-A{N>k12zGJW$Pb zxIXDpk_#4RH=qn!(pGt~n$t5rt~EYs_r(ELr4t{pVW&4`=CA%VsVp<g>ueol)OzO|{KtHMF_UM@KjTx?_9`m9m|f;GP4a@-tWkrJ8<3)N3_^9<8Ir7}E)?c?L) zZhu80X6sd4@?U1Lgvq&cq;#UUNdqQBBhsMyr4sXJuS>4Hbsy!YfjY z-f;~WIW{A*NQP5XPDh=#?%7JZ#I#1XzOVT=Xfl3p-^Om=yC?d0|7_ouzP_M! ze4+x=5;yyvg>}W7|AC|5`OY`*W=`++EmmeP&CO%Z?Hl+{@9hIG3F-dJzv&zQhbWoM z!F`i09|iUG{dwPe`zHRIJ~)n8U?F@ewrVU^^xd3CecwdM29OLzz4fhceeYY}x{4oq z0P8M(4)X{8yj!g{u6@@U*R)G0c#o5VG40B~iE#4s?<{|FUmuhZGxRp4`x*OK`wz_^T*bLOec8JC@hQ&mA^P_^Dw(q9>X_mkSh~ULi3&Ons9nT`rZimn= zs}Fye(tkL7C~I^&5$9RE6VlAtgBM^%}Xt{02GevOc+9!D&)^ z=4U76F)8J{!}b~mqFv>xi`!Jl{oKcA1Z?Gusj1N+o+`E9(V z-G-jhq+decgI=YR+d}6`E!CsmJdD-h+Su*Fl0E8;iQ|@;EbM*B(SgB%4{6;sb=uye z#dO!k#L;QrD}*|*6{7QcF(wXSiGX)6!)wHMos93bE@XXO;^pX7acD#{Jw}TXV>b0C zQ*m;`< z91ZAgTG1{-L)VOz?l>B@K))m6Cp>>gD3t`=37ij)bn+C3YX69kW7$EFTZ2!lu3<*# zuwJWAPd!puC853>kQ4O3s6A$gcPWCHbUGgsr?ynSvj zPP$Q~&*b6JG#p>4!YrT;&c(7TnO}3y<9m66&F*vQyKa58{ga803U6#%3YXEj(oC&R zMsIUa4(8ud0kRfrjSmy^IG?W-L*~GF@j4rC)6VS&t<@Uys5ejc&(jhCvR!`V;xz%H~#9#%R-~f)2J4On& za=}%oOE~3KA3|{?F$JH-oIaom0|jGN-QB*!c-~r2zuLOSJ94snK#e|$|0~B~`jB#2 z6)uY}y4EWLUtnhADU>RBqX7MlfKvVu;zu-nphE7Nfk~bYZsVqAI@L~)IQ-GKp8 z8L$zQ`+7r6okm^9+#XuGSh1(o*7X7ZL3s@w5-B;~h@N1_#a_&tQ+&l!-ff5#JjX_K zBig2J`q4vTWd(Y5tbytjSaCZMs<1*AJp9n=NPDY+Y9U>6I6jMx*Kx5^R2iq67`jO+ zO_mC$@~~C#=Km=gejT`*3%14>exmv!*Wri8^3ep}JK4{pfS1_4`r{DXJTWg`$e7 z{!FXbs~;>M-D1r*&GQucaR)%O;&u=uJ;S>Gkd!y+g{Ha|w}BRlOWzDuwl<+AhYRmk zz|#IE7i4YV+@Ns<2JF4XgRevQSmzV0T_L3uF*I|O`^L@ZT||3Q(SQuP#Gy3$^tuIS z&rbE57EHn;VG87~7*9kfA-QfNT2#h8p!o^6d9jh!c5_1;7}$p<}r500d%|MM6#r`b1P|z-#rH7tapj+2YrsSQ&On7_xd-S~c z;)~C}_=PWg0l)bBg%>}M7yGf}6b8}Z9-6A`Yo-OJ{ z&$LtPA1jJYWE9MU=yb9R)E@OF_Knf$;T~z?`0*wV=2~Es99BHJ)o8)cgWL2D(~kFW z_;j68E{T6;SEt>my@@e6Z3KJcB<f? zCOUfy@3Rhs;-DDi;4&M0VSukW8JEZ+K$EYOJZ8P-!D@cCVz=;478X1<==RT7VApM$ z1ZCM)2THXk6U@YgVMyxxeBZH>*rym!#RrczX@HJLBBE=0>>sH*r6MDFM zHFN0d_NTFJf=EJ`Mx~ZmGQDo6glm1g)DHh_0Ufc_#}pLuB#q+;SgFH-R^OEtw7 z5fU$@$E5S{PFG1jwxM_2-uPx#vIx3i2juS0Klj|fd=5fs&(SYf$;IN2JqMl*#w?ih zrF{5C@%k~p51%I1jCbt5WQm*9rg2jDi7CFNf@Nwj>+ID)HWc4)sQ-F5cG92V3F>^~ zVo+$Vf2wr8QJ-CEkt-g3m!gjAU5$1yPcrdvH;D&B%Sym&NAn09tsF1DAC@Y$;J%iM z*E}cZ8H#1*OP)1LBSvqf=}GV&?TX~nKp={rw$lA%o{RXEoW+&uUO3pO8lbRvRWhY{ zmqDF%1EQ5D)RBc2f-xh8HxE*3U>qp4$V=sv4-gu54Nf@WBY@USv>*eac5(E_TH$8w z#F+X<|dw~KAvub5(k(_dpjhloE=CP94 z^uE@EUzK?9+d-W?_9=cDgf*OR-Q<*JkDyX_2{q z>de0&p*H<|<>I9|E8dnl{qoBQwV#Sq;-tKrUS%Gx6lTsgtCz)^bG8{^!bgA$tH|gh zYjtQBRgNId8rG{&x~V6rtTkFyP!n12YKCQSpuYlMG*We+l)>4znT3_0s7IDf7bL*; z7gY~#U8e+M_UwxiBpJ07!^QUi7mO0HOz_;?#mZOdMk;HpB=-LayD`$hjB|Mtjr7tQ z1G5m|ojRuJ4SU-FHBM>u8I0nW;KhDc8ToY*UN`p=u~LR}H~g%TeA-Z&GmMA`{e7McF38GK|l9$hv?lr!p^M5N63LL}`1QXH(o-*LJO-pH9 zS?<+Nn=iloi{Yzz^O{WnovmDgInQua$2~w_uKd2eJqG3}XjoGlLLO+eeC*{)dDOv` z@ds+9I{&*!#TlC>5^g`g;eGG>Wqx<9pMZLeWxaB>Xb#mdF>ybw?I3=QHT(sLch8g9 z$}%hu$A_Ufa3-&9w_yA79XIemx{m)eHd`Ot#5kUrQq_rOPTkxk#=xcd&!1mJh+{9i zo2u$E5*;s*?$EAw$5}<+p5{Dk%U&d~2S}Yom#fpXEtjlon5?H$vc8Sk7hd^01QLgY z6&=;Uz-Oq!TQ!Gsgh_P?Vbx{zoy$$|&viS(Y<{~>A560r=fY+g9Eln&HHjd?tHHF_ zP+Z+P{Iu^No2@OjZK4!RYetcuh;S%6Dc%|nEJA%wk>ggA&~=n1FilLZJVR6(9GNr% zpe^q(b!kSRB$7^0@i$E{LU$+L{+UTjVT|K0F*=S`FPMzKR9(iKRZ3<l|A^cBOKeiQQ;=|bv)Go{ZeEUX4(Z7>M)~0>tQY{42 zp*i!JXkgDx)@A8zL+8(m4zfft(7rY8YqSHykq)EKl8&vy^*2V()J5v*i+R=ZjAM=s z2_BNEOBV>CP6%WUQQ+Jx0{_Gb@eG2?P{@w6w+<3LE0wZ& zeBc(cSQ;Q<0a1j_u6Zgdo)z_iK@3h}0lqyt6cU9YwYF$N57<4{xW{bK7I)Fi1H#pg z6}n;&UR7Mh8l6m9hE#IaLRd5#*nPKvIvjcfqHdzTNl>30ATe?6u_3`JzqNdwlFIsA zUK>D4?#*he0mn<#Gueg31)Re$D|jc-A#o+|iBxU|8*9~-0QWSb5EVVC=cyy;6@DO4 zqfSoRFZ}iHPoVJ&PLxM}(8A7soM-SZQDGjZ4nV04%C{4CyNH84joM^7D zj^pZTu!y^wBC#z=z76jczMB3vx|+t}{bp6zmpq5ldXmINh=fddkvo+jn>#inxP%6n zM6qG(BnivlLZwD}#?2=i^~*Mxd?(Qg8KHqV-_3GQf+A$b>8>iOM}gp>cOk)H*A35Km$o1S1_iMtyz2(k^p{)aP*hQ%m zV9zX0P2Ydlw@=MX!=wcc;dHL`9>FhgXXaQUlf$G9qay+Tn|UZXxL6b3JT)vXl9TXF z`+(KPr=V~TM|0R@YOZLAz^!_11qRy?!)hh1QUO~I2wXhw_9(P<8Fq_DskhbdRQ79l zXr(45*kI`WxCAFH&UYv|NA+B&o|GFOy?09948_*FQc@kj!OU!Ku+00TuhKliZ}GOE zD&9MNb&ngcROGmo((Ly-gGoSkf%Ry?v;*XfKE^xtz?n!70AEUw0C!-@hIFreFllzH z@ovC6#XDuuxJdVt5|mDbzMV857GMWAxw|rZZk{kqA(Yu_QJE@$>1tNAINH>N`Z7Om z>hY=rR1P$=edk(B`4(=GbO`;;_N_sssAT6c8)d-}_07BX@!>%>M5az^P|_))8$`~{ z5>`n)B&Ysu7a)dRU~-DH3)N?bg>I#3dakiSdJ9XKi~Jc)a0HWPw4SWjtu?Mg0r40; z;HQHXs|{7a(Br_peRNXl-O{hcN5smnp#s?JgibBL*1D;O(?-4vP(;+ZA#EaN`1-}=jl6?Z8i5&hDd}k4~Vk& zLzmimZ-){vA7)ZVS7*v*TgPpv>UO1U!GgK75eQby-oY-BZhcJJI{c+@)u%<3%;M>7 zdTbHKekHb`+B0xe!N)Alw&qyANIW?>=xxis;A%Q0{{cEa zYuE2M+^u`e3HIKu9<4r>*FKL}8Un|SttI**tK-^Y&OxTS@JAWqx@ zF9y7lw^0cyjqw({H;8Q1xx%A+lYelW7fVkCi*C2g(6_Ef8KebAU zELXf$V2pRV!!aCl7~@T4m#?tFuV{>C5^`eWQ-I=S1-c&Z*F=ca5fitf6aTgznOWd(+x?IGA7pP*)!bEq(koc+%{laR|= z-Db5+qQe0UJ~_}`LC34dhGC_8{{_Kx2svi$x}bEBP!b%xYOHkAIvN?&J~Ja~Da}?f z(XFe&-ik%9LDcf(Ft40dSZ-N-s8X3#gK%{KdE1fb&D5~CnZkKWVQw@#0#=gIH<927 zk~y~gL^HrYuxJ%RYW5e}@BVj=nJvUdRMYT6Lh{v`&8WzDSy*Hfa`h<3ExTtw)0ixSbo6q^6YV;>y6}IxPQHGSND-4X~WuagPADWZZ%J7w^pX%pr6X| zVVETdou*nZEMXdowdAXnSN$SlB_O@WH!6#ZLnHI$TUa)9UlA2VUv3%b_h)hIqjJSs?^Li4rurAJ)tUH;rfKMHq2x^cWH6v;>@>KaxJ@m#OlPJ9!W99CpW=> ze?#Mu`z#5E@I(Nor2E35VD*|I8=6g;EMdWm-A@#5#0byrstbZiO0qibt|o?LVpyAK zmv&gDg(yj4TCBiJmW&|TVr*VQp2fJmz}fOFEEJ!41ZwfuYpYRe60E`75fik(s4V0X zF;Vd60oxsAi8byHp7e{tuk1>UYBjBn;OR-JdV9Q$A(q2Rf$4eM3jjmu10> zG2PpAE(Bj^gl^8Ty>;&%`nwZ@VL#4CFoXpw!3crH{fVgM0p~(QrPUX8*fCZX%mmZf z?*4W1L<#nnW3yT^C!x!!4%@8sE7&1tQB)4c~&0I1@+p=>z#;iyEg-PQrW7*&h2`w z)e2Twt2a^LfV4<Q0C+@#ud3gxIKd76?*(;1iiV$CX{3;Ztp#V@G1x_zmd4gn+0wpYmsxLmBHfI}WK`-J_F0>6 z5>XeKCdhq4Y$v;?75Dlr?{gl9&KmYDtX&A=YVlT?CsOyeBCyT?^UFp=9s=3b!1P zyeyoAh7;-rot$hF1z=;x{1alw8KFT;ORG=c%I9x&Q8+BtV=Gh`wre-3SGcE>CWoC< zFcGAWbEzQWN@fGG?NnGq(LigVbuO};pAg&9I9@Ydv|J?F67Tzd{X|L$aZJ0lk|(~l z8a)CX?J+$F6q72>0b*KgqxX&J6x@j5hInuD8pmc2P5zi!j??M(TMMOIM7Le!4k z=hQa#$lF7O#Q-Z#^4@(&SYm?LT=wyk3mO|Oc+k_jNN4h!jhzfsLLoO}j1iW|5>@y~ zLW*9%a*k4j2@rpLoFuKCF+=|&mfK4jjU6vV$|{W?LuE#rL{`EeY=)KUlF||en++|N z=7U~BTO>T=;{%azKYlMw2f}0(5&QyuJvLc4Bv#CUR$|cw{8-o<36v1+JpeUg)3bPM zd&(G%AXjEJ?b~;M`c)(V>>Ahwz~d3(OaM3>2C;q}Z%fJ!v4Dqa^5?Rs6(ei%ejM+fq8zbxIqcP0U`7DN#U{Cnt+#A^(O1GVSwq8?)7 zW|1p6VHPi3mn0-+QVXj-NP48nK+M!(t)w79sn%L3~sI>u>%#bZ*lq(!8K)49u-Me7U>l1|)q z@Ta#dHKyl?)C{*f_H>`VZoxMLAszlb#H40Pi%1JUh@q1{_G7i)=}P0^CY&E*IIv8WvY7Q4worTCKlDm(r-6Ai&#SA!th07!`#9eef?Pl`r+xH$_A& zN+IN!X$;+T(}@;kWe#OBq;7fam@U>sm@31{l}#XnxQsAqB0MHKy<80m{u-4}jd8w? zkCg9<3ahk1_R>Gn@(WbB#hFoU%^3|(qw(q5LkIjB@dVH@xM+G|(&e|+t#ezj`uZmbwmx4R}Da2POn z_PW7{E%#aVVK*YNWq>!j?nWe8%+N#I+iVnzO;(xHfiBIwy4Y>OvE33pW{^1!GU%ZZ zKwCW8!nu8ZyBFRF5ynbiesdJ4u6Ln3k-Zq%PEFp0q9WTh(TOkCnI?fi62mEWr(Mp6 zgWjX(Vp;p%NXGUrrs+7Oox5`~W%GMb-N|yNUR%5FPVT()Lxr6Kh!R!#)^(c)eDc_~ zpvYeaC|rA^YjV7=x;X|M^nrqj=Us%sJ<&8xNekKP^qvcd^_m7l3{OkcF#z4j=@OH2 z`m}}ae@t`BQzky1)6SwTTKM`~{7Id|L)a7N5E40;b6Pk{mQNNe?h_n=O;d`5J zEFS&VgblGZbiG6+5sxhd(BBPqfqz>rM9>e8vGquMy##GFxU&ueOiXl}6rLvVMC~^h z(Bnz=zOjyhTBXVX;V2%e)fD2o3Vqp|5oLvV8mrGxDjn_0*7U7{)xu$C#3a>=Y1bNV zhiQzkr_AOMEP~s3XMv${7`67TfMYsLv%4P0xabFXoQ3sNo~kG`&chQ@{`*$p%$!~T ze>_=9I;LqEPid|!2#xr-9%n+1v7U33MtaUN9BZ|&Uzz~dNV%XQ zZE=eATK#(aK4~w&i2H29bPkL980?d%Pl@!kXH`A8KDa$OS~h||zJY_Z?kd8fMFfm^ zhZzOw;)tJijJ0$tvuD!^AN9Hm@<(0k%Wp?yutwsl6Vp=*iz=6c9zL9uFQ|E=iJ&*7 zKVO-;5K7_MB=^wJIGNqyq*)}PY0y3w`6Wq{=5bMUgVZT?9lEe}L<;pi-<8FP&`~f{ zZ^5qg40bh3^YGrlMn1sV9@atUq}qV$iMgrJG&=~y7jqj;6?0o&gPdDI!QskEL9NE! zw8E`w{94SrUt4RCs9c05DbNySB&vlfZBzjwbM!AY3GCkM6grWu*o?In>rcBs7+2>= zn9d5>om0Czx^3WYVHhs2^|8p^J4}K#n0q15yw&2Qs;Xm(rSC9Sye-A35Wq8Nw;H$5 ztkgP`*ov5Euml_)6_z$(u!*GPVD8e~fW}S5T0x$;F{Q)iX*FmLu@~+@mMM!B2@d1J z1Z%QZtjhEySM|ZPCt?gV(~HgcO>Ji$&{U0yQIhL)Ev04~mnpE2I8qoHISET9rQ`hX zXeqxR2Ldn-;;?{CG>a%e8j@-c(YP<%r*@YSy$P%7+CuMqMR#0h`@xejnvm^cl6sBp z1lyLRz~!))uMX~QUs+KQ!V^QW^Xy=yeg!l6p5v1yl> z$l90nayz~l@rO{9u}Vi3h3iVz)Me)7@mfUq z-3#V#yAE&Paj&yxzOk`u$MBu;E9NasRz##C#LQ$M?4k4->D4Ffxp~93-^;XNCeY+& zwwZWe{bo+?XIcL?wIYC_|C#Xbe z;nzu}U6lbM>d@>mT%%^0Rl|EXHjP|4t2bt}lbgZ+W!|P`FU&kp!JFIS;jOK`olzli z7daIky=QQ>0aGJnf{9FxFxP?(fl-+3W-@LOiWe!pQVGt5e=HT8ZhI;=;;uRE<(EM7wZ98`0h1PjAlgybRo8;thpJ}a5CZsgHOZY4cf|VyG=UJz8af%(U zMnLi#B>0~(*1b~A20VtIn_9ZCm^%(P4E^Px9HEWgJ|XBmQF-{%g{hg@z6|~|2bKZL zp;yfkdDeSs;j2#t)u$$s)5whLbVNrcO6)f*&KXm%bAClLZ~Ci8KLYb_s{TkHyy{*c zue$NrRf_GaMVUHr-c>ulz5Ou)G}KPRz|vwWxrMx^Xy?oQ{M^zdGHF^;g_7zJ z4?hGQlaS*E7_*2%Be^~hf?sKAC)KbyW6%FMg#7Feg>_GfZdeJX;<GnZ@INU(q$QWSX{AxS~VxCXoRrrwOm) zsjx`#9x_JKI`?P^{$lW72RiXvigszLqZZzhmZqUigkQV{jN&0QnvNmUh2x5LT>kPV zc%IP})LKl$!Z~%ZlI&wV>=$7%(e`}I4x-i@U^iK@KL8M71ozQ-4dNBN@}J52bcWU> z7*^Ex-ikI0l<^F28?=N5hxtK}9RoiB4AIo|DC3eS18AhAAH@IhpexV*&8>R9)(F;aU~gKx@CY9JepP&~IPkRP)_faL*_$94hYOembtbY*LK2~Rmuc9gUmC?00;r@~~M{>c&RidAZ z?-sjDWiu+eOAW765931FRHBzOYV<_*ZMOYk;}HUy_A-a}c_6|+Jw)J_B#pJ(47 zGeQqDX|FhAywM-|gk%37$l#RsFm+0T^x$ta%j4@{tq)Ap+?BMRjso>*%ipQ zZ;|AeH>idt7iu61!*HnjgK= zYL@-;({?ep4G~=_6}UeAAkcJb zy|Efht_SOl%^M$JpL3H<@OpyPev*#XuVHWUU7ijcoH<7#y4mc~?Bb{UYA-*$T3f9L zh1J@bdawq+NN1btPg5kBu_-K7j;ytULM0)%o)oqQLds7}KrZ&%D-$^1&7Q419POm| z@mD+hcmh4Z_j>2%;Do4x&NY{RR~nl^?P~op%w}F*xrS@N+!OJx7e`P_!sY_ASY>NG zes_c1tG2UYYf})u&9$7P*~6CQ#PJj4@r!VetBr4(aZuEf{TC`#bAB$KWMO@9w~Pn9 zqVdUSWrV$xJe6nYa3n_J;&5qUvlq3nIaGjvbs>n$U88>sfsn>G4#UXxTeZ(!g7F!A z8TrG+{`eA$nCYA5H83MCuQb-S*6Ww+)%Bn`Id=}C54P*J*4DgONMMIpCBMGvDPVNL zUde&5HIk+uP!kgiQx8@y&B0ZdT72PFJ{K>k3F}IVeOpo0vr`uy0TJVwhacfHsr5gf z7L!=2Yfz;k;$1CMo!aeVB~r+RGn7A?r1kF71a6b#X*~p2LR)?8&gv7k%eN^SN z&*gWm$HirSrFR!RT(3ju+!c9RF4& z&HJf2xNh4m7oD5c@-m#w;Vgnv$=os&898Kr?jZ!5k0M25{Fp6Yst49(mfkm+Bd_Le7`MGB1BVE4ltF^N`==h9nLV$F z6;XM3W?^w5XO9_E$gU{=^5BhppB76+5o$R+3%Tr+tcqmnBq#{;a?@ntwz=6nfS!Tr^nK zG6tkElE4T4sv^(5IG6I*GL>{@@Wv!1<33k3HYbl%mx&>O-1;5$_+w9SB>cJNRwLq7 zX#O^uA8W8UAA1en*nm-L!?jad|Nhea%*846#RHW`aum`*^L}L|2W@jOkFKcyqPc&H z^xtRB_gd~LOIDh%=gOUBNT`myA~WStCZ6Q3$4**s$=wPRBnq|IzWO#CUaZ8uVcR=t z`v{Sg#3{z$EHbPmTNna2>l>RvvpM;6aigHv3%LH?DsHfUNHN~C&0wRtS#32i-m7Ow zenBqOV6Rzz@@JBsOy(__&wK{=71h@D#+g=e6I;4Zn`hO&h~J;4=L`H7e?-Kq@w&U4 zUW-bPdQD@#+pis*Nf>DG!`^^jkydwT;d2!Kqa6};AHADNN&Ay2;ePO~rX)Lf4&-+= zv(I9FcAxos&;GZ2&l2Vs4qv-``%#z46-q|iRHdlkq$+Nhg zjqP-DtBsW!_IBIu4xJQk?L)WwVT$56(o^)4GdIoOJ%u^!J_^>I`ioF-bbL3Kc{YaB zoMNfEIK}eH#ex3t%9Y`pAlReZ!#ERe6{k6fgLoTkNS2WGCsgeR7ui~s3DXCunm!nL zF?uiDg6o+4gi!w`sT0HbBOTYPo3)m?F?bvlk;F1Q)h28Pj$2GZ z!%XD{#e=NTP69z1Z$_mKMm<}9b#Kqv9^9$ioyok%qFw^f$#|`Rm6LXbPiq;M5yOo= zuDgf+$__DI9><*l5kHm|Y@eoQiI>t%4`>8HG;Dh6Y{gb0JC@-O%l6<$Ti!;MaP+sl zT2InhJvr=;l7kaM|5-wq4EkyL(bfA8+f+YlUvBv?vFtim@{>q%C?VNDN(kei&!$D( z_Titq?IGMJfd6yH{69x2PTj(%BLuf1ftz7th5MBKi?R6L0-TMR-m)d9{;A~P9z%bm z$Mgr6{JYYg>uC`^g+JR<>U|`RVdU?|LPS7lw;#*-H|gu+aAEJTFxq3E-T&y#pI%aL zsonl}drSF>t~Ugh-a2i4dbQh+`zC#!R9Ci0{KC4HnT5)M-jkYRzD34^*an-8j)m;O z`h&0E=NH;MuisYP29T3Oo73x&zM8jR{e@UiG=Ow&Y}g-} zmlte+{{52w+5U?)u1T%Cx)wAsn|L?>wi&vW?QN-zm&7H$5yw#4J{%-4iio9&qvDBD z{1VVeQU|`Y0Ro+ZxxjBbLvG_GaWT(VnEFb8Y3hP99F-H2qt;P^V3#EbcC^3%|NX(2 zAUA+N{jh`vZ>qaH5qSZ~kFoTDl^d9z_vuSqm>cXk`nqRz0G8%>!VLdFKSeSf33-gW zqoK*X1l;LW45C_27>Y1xzch8)G;K}ejhDoQx9v`{(5=*3P`}!`mdmbbr4xv~7QRBy zC;#k|pZw$(2LADTzwn8PzJ~g*cYon0=xujr?R?{65J}VbiCwz2ZN5_!xVytzEPb^H z8}Gj>^M$?%RUKUJyE%WT?}59-^RB+W-Jf(%-@u!|0?1_g`uZXxIz?{x`$$u5_1{0e zu2$9>%fw>O7od8xHcOf~zXAhiU!=IJe%##R?9zn`TCZjmiZEcAjuX{+` zd`Ej5v&j`Rn=o~25>K2>mbmBKU=Y?8Fq{0&uVQ5LbnwFOH~}8E*MNzJrW%NI%*F=) z?oAWqPc`kz@+K|H?aen|h*jYQ==tST^8C`C0*3^b+#oT@l$>K+mW*x>nUtgd-a|Iw z_?>LbaTpnr6YmtJBR~VC{CCpdqaXcfg#9=a=TkRtV6<;G>W!`DQ<|9`Kjv4*4FxD z?8fNo)tAkKP30?BBagmQxq7wg!YS1h<#^?H{p5esd#+xcUznz}c>WpwryLtv?-`4% zkpYt`oOp-Wi`MnjTAo(b(^K|@u4jFX)H*GRXCRef-c-hZmbVr@q z=mf86Ru8Z8q#~QB(H;@oWpQ0LbIwTosunKJ%-vi&nXiP6ShicyE-SwUN#*CB`fCOd4>$0-??63W(H zwOtYx)IxqF=FKvGux>y)Ppn>8N&@*PQ z5L38Lk9k{66?=S0?AQ|_+p8uHX)fUSAuyV%b)$^d4QV_mt}h-k8&k&-8?4N+dK2o& zW?{yDjV;+?m3=5!aV9du&%IcYC)DWrOShK=*xmE~5++cYWTL$Pm z^yQF#lsHu)BfjvUPj>&<8~MXxOCRqpNS)8kMuzD|t|q5}=qUc@{Os)VPb=}EsFmDD z*Ql|`@nJy~J_r!C zkIiOw0wA%3A|!4Kx&C6qqgiWuQ{~K-ddvtP2y4{ac_S=u(`+ZDF@o~ju%phEg|ZV7 zcY5Q)Vj~}ILmR6BY)n8{4X~hFj9P)4>f|ZDwOuy9E0d>I&1-P#o9I5;eNLW=%*w-J zPZbmThVaKSthtaipw-3}=2NgXu#oCS47fM@O$S%OiGb6F*qO;@yRmS+xy&|tx^p<1 z9Y^9**{|X0!e{5O&)y5S)-a9@8^G2ImIWALYzOeGSr`RQ^CW5-M;2fU3=P1?c?4E* zyKh0svcjdGQDAdsHaA#igy<7a@2JthL{Y=vdq8xX(jvkgp3~Yho=I44mOW7b@kEoh z{ZYz*6?NMgbOM;0MSsZj5??Ik(7vid_I=2%Pk@nvbFjd#O}@LHjP{Cvv&VWR$k8U6 zTDv3u{WhPlx7X&g6JkM>aD7%RVO)&JvnSiDmg9=OADg~I4wwqlANC~dXKvVF>UVT_ zwr>sEBqgQ+K?>xrfs4_d=$FAYYL5>3oF6ur654^RLrn#_#s)clSi)rGFXQ6i5}WqC zDX-Rk%CjCOXu|vR&4Y0*-EM}7_&4tJ#$#xr86=G!4V_3sDAihTjz%5ln?w^jL>`#q zUYO%~bQ-$;G*fS4k`Ae|XL!)Fh!Gc+Sb5kA57ea0T?6BG9rO|h-2y}9^|(Il)5|nn zh0)b5i-AReLuiO9Ed&?^y+d}|(^8@FU6we|ntc(rmE`aj_cgsb{53ZV*5PjjBN|UT zhrd~pYzi+ZxPa8UPsUQy#fG`*a2FnErROQwAO7MjdO-I?&ptavS3%F}XZiW(m)Gje z!pHgQ3BT(XDzNee{!5{mpZmGlzfN(V{((QhNxzg^4GN!HEv)3#PUgZ=WuaMk{_0x) zBKEIp=|aI4^gJFgkMKRc_C0=qC*}&x|42y@oy)!O{PSlk_ziGX!MQ1q2F3%zZ?)kI3H!~TNn28HrfMJ*?Mby98rE=dPD2O`FBIKD6krv~+ z3uiMH3x9xOhPfDxS}M+=_BW{{#_RnCe9`}(SYCTevru<AN z$|l^t`1~@=C+a@h-ASzFxHs)`L+lXl06I^l8aGhj`9Ux=iSwnFg2K$KznBPCVC0(a zRq`pWjYru76`#^!_C3Xq`1=mqz4%Ik8}S_u)AvE)%}kGe#D8{H-3@5E^dl~Ph#wxf zw=YXos?Wu0R zm_PiE!+35t3J3R<(A6b{kKo!wQn}hAmD3jDwV-r)6K<)5uE$@G)E^r@W;*O)G^9ur zvF+>Cnb~RLI2cF?GLffSx5ng^emBTZ{3VS}x-Q5Ha zH^L7oi)#)4{8xgV5HjvG?@m^9fc$wJ?w-a?Wo3Q=PA=()$Px_T<1zP$Et%Q#pFaMz zJ^xXW_J2Cbt-G^Z$m3z)QC8kiAUIN%8I)0u7fmjIn5lbONPw{SwKPsIL2Rc+IEHLn zsGTY`Ly>^7EgtZAV`=GnuV;=xO0CE8yh4=7q%qt9+8yqn0Th|c*U=nnaaZfO*^ zG8gsTd;M~~Qhnscy3LLwJ5XXJh5aaonggI45*~>Y*D)R{e?Y9|gBvREiPuvi&b5yL zF@BPOH+=e(9`i8UX^g`dWH=J-&pM!G@kwA& z-duE139;^>DG|Jsb>=ptkH731^W`@KZ3%O~nM8V{vk+O5L(sp=O1PJ!5~qjXCF-srQTjr!!>lS#bAkTnp>Oy`>fz(_gzY zYww#JPd8Y-S3HCU{ky_LQgeI|Q4G5Qh+9R6^h!JUJ=AwwW)eIvys*FA$z__*JH4i! zs;+IBQ+|A0?Sr1~^jc^49s9shlyW0vF1%X!DLXqT(AEOU1&Hq@U@THa+fT}SZf`z0 zI@a^mNX>o&(qz`Q(b(Q z$zpEY82V_D1g{zAPPh~`LoU}i%&JEDg+hKRjWFJB8h^_aKQt|b4i7{5|9;#~6Y8e4 z?nbC7AT)uC)h#IrkFQ*dbS$EHKt#0hslqZ)h)83W2Ahp#RwlJc?y(F{`ptIDEDaf@ zoX=yHYL5s0;1H578C7rUxwNH>q%NjhC2kZ*`KC@OZJ`IxH4&)Fjq?Xha9N zd89vhaP3jh79jNP5WaOX^S9zsB7ig5oRr`s{jo_<0GGt~C=?M!;gv2|@ROR`FN-pp zw3GwlcFaE4xpjzqm$9}cE`tB)mf8Y!J{|k|fS+NtSmqCI!|Ssl1hpnOZV3~G?hHdW zvRPh`$>|j!J5Xl~qrGJs&iY@$pK7fV&+YnF@O;n45Z(t3p#b(twu*!e)z^D zvzHZ%GrH-Bzo=A0);ji8Mg5(1L?hk&eS_@~&60t}g=@>5b%gqwN1d5F6H&Zy26AYia;4ODCrTMW+0Y1@5~do^dt%VGqztdlv@DyM5Tt3h>Gah z%UUIfSdyB?M_7LNw&$8SA4FRph=fgk5+5-?*%`$W_dca&?!S({QhY5F)~eH zN}@f8i2efk$|t>z6OcDv|I@o+*@0J zJfS3_tpu#ez96%VUA5Kk3rzs+n{UY^mMRe_f#C#FiLj0g+~YV!LfwWZ|jK4}cM^6&3`40A1ZtYZ?euV#$TB$J(i|F8pOKr}-P zCE8La5cA%K#U7`qH~O#`N|_pNuVKN5D-hdjGZN0-dG27~4hHUE;B|n3aK#l1DFxny zEd#kcdz&P;12-0~$n4gm)kq2c#yzslN-6=HeyqBW6?{ntp`@C8D3RXdBS!jQuyVT< zaWL3UZY4a@ARk~!sSu|fVQ=1vm?Wo$KuTh2zm=Vo5Bu6G9~v#h!O&0}l0Q`D@mXYG(tmQvS%3diUsTeWos_Tu~C4`+)UzRE%fwP6mrWJ2Y-Z*CM z7j93w3MU|IWu=EslljxLl?xTvgn^$$xK^~r`eX(zBR1pXSLiQ1G_!cWs=>@5DPZPo z3!TJarca9tlJP4xzyPgeBfXT{hRV!Q*h#0#S)pF-%7w$p@E z<~p0nhXF4r{?5(*AnAv}~Di4l#EC$+QyLDsqXsrg3~?0i0?o5`}SOrZoSq9BAy{o5!X8vj+Iclw@m9V%m_mkcayHJJ2uLm3Vs62#~w-~-vZs2 zx&{CnS5eznzVB)M7v>G}qG1FiJt(prfZUicou3OCT>#lZ@!RR5xCWWFeU&j}C1S2? zz~YtpfIY~K_<7St^i@5`qocWlpEy%G-zYRI0*&ZFiVg~dS;8`M!0u5rQIpJztijw) z@NmGiv)=l9T|KCfiu~`NjtvGOR4X);U_1)Ks)gkOoBb?Eo3R|6b*hDj%UDHu@Dlqg zR(xC>HnNh5b#ORmRx;RZZafjxYflGiqp{fvHlvegDW_*u_=sU{o|8$1>E!;vK9yBv zUh(#k?|fu~zx>b}k8ITHS6SrLpZSDLshuRI&RhUqtQ%Yts%_1-O4ZQVtUrYd54lB{ zfE_B(-(mi%-^p|mf0`F(VEOudtyNuK3obWTt_ADWNwVf^CjaJ>YqeHzdA-^Mc6c2? z$YeiYdYJ5M6D)9SLq@=OnfoA%9)oTahiRLs+5~R<*|p4b#}`iPCotD45FG}bq2Ye8e9Rcq8QZ#9F}T>nCUo|&o< zk36SOpZ?ayu+DM{?VywOqw=3FfiH=4#ot(7$_nY4pW(#${?j>R( zE(#0T7trSB+Q2d$8l;Qn58ILoi#13W7E;CLm$}sz%B&7(p*#Kl5;D7Amjhw%w2xg^ zg!aW%g}ls@LIIL#K}XB%Y`Q|)E3>0p@-<( z7U!~$S067Hc{cy`E*{b`VHI{vA(&&FzJ|;CdG{8+taR_p#AvVJ6t^2!XVJyn=Tvkg zB*GL8X^+4!3Ktcs@gOs0459MhT(cgL&EkT_OKio1h6_}GPZiXF)sp55A5sU7`(WXU zEv8y9_!PpF={r)&?3kTpmehlyop$Kg(7$ zgYRLTqa&sF3Z0{Nef`G-5-`E1A%B($Pm+eb*J@7$Yd3I~C=3AORtG)Tu%G<=5nTUz25VG3$d z^%!Z<$ZZ`77!X-`82(~rX4Qw5DmX;reb!dt?D1r|a~M$TBt} z4(WQ2r~0p8clg1h#p0>;#%eIR9_ZK28y{F18cL5DvUz-eV^!>_v(2y^KXyn*!^J?b z+D~h8lV77iio=uH9}6E)U=h{oP{N{Z!2Hzti&N?&jjc^~4>i$egKBl0y4E3(P+g6^jI)@E>d6$7Icz{8D;SgEc6^2U`bu3H3;i}eRRE|NQfJZ%-f;5Zb=5GB3` zisanE;}W4h?aj)7>qFwtyW*U85SaMTtA+{q8R`lXrd6W9jH|CMkP|;kMh?M()e47A z&;Tu{74(MJiF6*<5q3XFiiH@So3jJ@*&P_bzlQw?)D`&2V9!Fu;^XXj1gB$){T7|X z{1sojePQ+i@1wzWU2h2GOaqRcUd*^&Q5UBcr|(z&t?Q{WG=o$AschLaasNj? zc}@-wmewpik~vj-nbko?fwnC9M&a5#JjI&iE|&EY9$d)vH|Sm^XdcSoXU*@-@I;Z>3CQ;>?K6c%MH>RY zo@JUTjHlK$u+%PV8x@zC$(Vy*E{d2O_noGes)V8r$z0sow9VfVk7knn_K(>NuBrRP5vYK719K zy-~($$BDu~n#9cgPuMKv`;AYqdUZXR><5P$vr0$y@f7&Ruu?&+V$1uD6!U5O$Vuv2 z;!{Zs{kjRXi0bn9=Q^f40L(pn?ONt^S~+|^OpA<#cLcZh1i6MH-)_EVH+T{yUwveV z%Xl^y7gg8*&pV&FxW!GcGX_5eoKFmWg9V;@9kpk7cPG<3xL&VkGT!H&K6(e?R_54K z6FO$ngG~s`ELHN>;c`!d?OLa*_A;!w%mV|l6NI1M3yA*AGpAkW{-pVR+09Dc3p?ue z{!liy)*jr2t%+XEaiJc}&VZR#SgIT$&)DR#yAJmvtGLBysgX5xC9O@jH_~2(em$_h zd|CA6s@IMD;dLW_r1#}&27MXt!=ONm8-zMM_vf?L{dr`e`~J%LM`ll1BYDYQ&_@L) zE_pBOag`ivkS-UUy(wnxX#Nga`RX@39>YPltlj0paKb}8Dwhf8oA3jIXQj|D?N9-- zRFqi%$l5sJ((KJ$;v$Cyz&w;LAW|f4TOfacGZM-ij-Jm1^Ud(^f;vvBkouV1YF#Of zIBWe^Hyc|UmmyKIQf;wp8ONx##`R#6{3Mj$)W@Eh>GeJLk~3#KUJ8MW=N(w$ zD1SKT|*WwXX`5qwtg2V?%1SdZS5&GA!q^bk3ynQV0t;I)`v?K^e^d z7Cyr+;+#I;M>V&Wn=Lr#WiDK_PXuSoC-G8__>6Q$qkUjUAHVuq5CVC)d+E{PrM-FL zJKDKf6!0f5$T?@FVusMXwUzgd^)T z@^^&yO%V))B87y9JaFnvQFO-~iHr({UNRR#Fy70#2O)s8S=@jHQA`kc4Vul#ts?z> zy0{Syj($gSMWZnSF}>oiKW+sV&Y!G@%SJBQo2`e-miLc=3|K zS`Il=E;}WwBbhqMIc^Y7%Wtn>${h>s{~7sZOtQ>nGt9OESzMn_4z$cWbQQB5!J4aS z+Z38n7td?$2(pDhZ9WjAG(T~OCu#GFu}=ACehVN(Kp%_q`PwppA()8$8%i;Z$M7DM zy@}~L%SOTky>ayt52r4*wrE=l>dGyQpCvhaIQ_!33x*R+D| ztP;zR3JP+3;LDkf#NNtLuDTk=**+(xRH5duZmY6BsZ$F~#DlmJ!T> z%d?6)o@Ye}ULWoA@7ZRStxVOsbW6w;c+ze}rFM9xBI1_EtOPGIcXNkmy*o z>V;pT=Y^5GPa8L86&7!3@dkU5&tAt@BG?>VUrFt}@wO&H80;{R+j=%$qWq zFZ~7;y2~Z+2_^@O0WRgoCEE|oDP?yK=0@sdx1^E3qRXbX{i{ezUwAZd;i8@|!Qg#|PXWRVuA_Pxy0h8q0p0 zL@}oCuS`FXQ`KjlSyniJOXna{tdK|(H1W}0LZpjKciTlfTatq0Hant_ld&IvBNmUz z+HjMMY|=KQ!~8bH+3Z&un?dbr{qhsRjV8o-Nqf=faY4AocqT3=YRPKl;Y9#$6A|XM zDAi)HzOjfYImj&r#n#MOcB1kSSpJvhXD*V~_5+ni3X0+up!`@b0?F}`Jg+BbE9WZn z^A&O^Vnkvf>F%mYaDFl$6pI!Fr-DV=_M%p1j)jF>n7KH!NJ85&w zIQ+NK(A~U2&&=$3BQS|FVp$9YhEdc z{wZTIQT?sW)@E&85!!un6C7{8`l-O=!u+Ceg>ym*1}2D?_H)<@WQ3ZN54;pUJ1_m< zOV7T9KiR4>G9~$S6K1M^y2RLL|N3W{>`o}}|Rsr)# zW!B8WV|o4gdzFPz4xg?psOkAH@()kvE=8CFDLCrkJl(#vqHv50{O6w8H$pym8hOt;GY*y>5jdgYn1a@0=6$w+0$R{C}k+p|6cC~$M zsL)vUP&yuGh+2`^0Ln&*KC-aFg{KXkTHHe62|(6p>#k27TvlNUi1eCUM7V1)c&#{x zA&Fgd%#s>Fx9WO9k@{3Yotwi(`1~xbGTOS!Jgpv;S?bOoqWVa_Hij(JGi2+5l1YJX zY;;{_s)m^#Kms-_ZosiVA|7`(%Ubb8UB4D=1|r-?V1(yt)%;bfEJS^;6s{Jo6>4GQ z%(1LoU0Y)exx`Tvg||$Fp~7&XTsTn}DU24z3gbv=#Sc7PA)~_IY*lG`l=zl0&NEr7 zjH6kL0KxAFp|Ge*{Hs8B^ud3J4&fESs&uJ{2!zt`Gyo`5vbKTXuDfbRR-tV8*~_%z znVIqbXYbvEBg@YFupX`$MG(gvJuF(37+p3OL<4AGyBm$yVlgufOwSBR3^0qw?yOea zVFT!y!7hLvqI-5Rs|{xqk(4Y|lq$uvD~?koRirp#Sbj*ZR3bA9-F=5CbmeaKhOLt6vgGR#JHMQ2<}E4;FFlWJ&sA=YL(N4dXo z@1>8^`c@Ty%sOPegA+S(@F*QMO!f0WwG#osiSbQE-ji{Y#v9~kMR=@UI>0Z~C2)n} zDRFQWUp>8lOGtQ<{p%)^t0m3X4&5#L)FnKA^Ui-4n#b+yFtc>{j3k z^2YTgn(v9r&V0zX5F@UzG#w|}`M{L)DVVztBQyTqd|=KeB9lcM8>9&bqFFRRj|igO zR&S36@6!j<4Z|edh&G0ns+EruZbp0RvYkm&R1KlSGmtKCB?0H9f)hKcRs@j~Gc^E*t&H4;&UC_NDh}S%Tt7$-B zzDL1Dk-ZpuK?MC8i?_Wu%bz?*+EkRq1_VPMCj$#tK~%x)wNj7W@yt^rD$4>vVpvmy zyn)`Z&z?nrQE}R278saNC{?PLS({0cH`nPn!NAJpy?urmc1RwYVGjo}HhjGe^Alft zdkwQ0OwZng2#ik*@ev3lE04H|VrQy9XWGw+I4#0rGeqOUcBJ8S1KAL~@~ssH_e!pq*KXU@pBB4dS@_j$wdU2KpIgsXdn9D^8JgSxgFOTHyLV z$}sLh-U=rXLD2Ba-=aQ(P*4zjDIPq}vCVF+#3=q0uRazaQ2(RXC86}XE!`mV%9pC*JG$oM2Yiv4+z(~M+7TUN- z7|^9&t?k^aH$kbfMG(=1unOkY4NGSZf!qm205%EnUhzQ(=&(VkOD(QfS6f>dUC2%( ztDRD7n9Mb`R$}OV+aeW;5QK=fBU|ZpWDPhaM%N5_!l&MZj;U*0gZk9vgbA29D|(j`vqiA;Jkr94o=Tp^&&hfu)o& zH={N?P}?BC7tx3fPGklbsj>|Ez20LUWk5){LPQd8~a1cFb z?$i%*JG^f{S-^pIo)9N_VOf&A+8g}M$t$}kh`>ZIj&SepU1*zt{KXV77s))OKsz<2p9?8$DfNbAwJZ4KlqmQ@t_2 z2-7XkRjJRDyZeVCZiyNl5QnspIx;)%5an+Nq8w!o4f>;Sp=SNlWOC%}2jloJX0gB| z^iDEgSp_ali=S<*uh>ONi|*H|l|{?tv{63d)+5#wqEO4sb&Veq4d|-1N~=%W$#vU6 z%&;zMV0I8)Eq!xaz`yj(*Xk6qf_`c3^0S$r2Myj-D>2ZOkNpBlYCfzgP^2j1tiTw? zuE8>tzMH~0pnL{)k9l@mDz!&7<^k2nw98bk%<~k{uPiRlWrtqWQ*9*rfz8I}cj`*J z4hhXhjcEDoP_1f~@nLcBL8G>bzgQN3`uUwtB&A0&+OAE#iBvJ&K^8#ZgazA&++A&y z^Dr?5hV*vtvuLJGpIuMxGoD3Z*Zf-!#aOoQ8izqZ*5RSR+XlWe5Rt{wft%`{!@&Vg znBG5AzWOjnF^*SBF#lPA`QXMupq4>_;SmPzeML<(C(~B1`yQ@*|BL_C*{9YE(5^#X z;#hXNnWpa`2~aFYBW4@Y_kKQA>E$VG`lnxe_;)1w!pE>wA5n=(;1G2s_g4m;^_KM) z^#i2O++Io5lK;c6RA-9v9tj#!0tb|3rQLOxnZ~!gZMY~Nnd}DvBzCU}Zx;l@%JgQb9x7FC(-hyO{#giqX3D#es z;D1h#1&!wcjm3e&hF}-6gpQ_YS&P4hXIL0g82f|7+Bl=Yumy#>0y|rs_ekF*&^+Bq z>}U&M)Eq(SP?22OF>zjqHC2oKg~6wWqM@hyShDRj*>C#%WNw>+8#U7;##I4x#=|?} zNkTqM_bFDYuI#hzODTk=@Coen?KFJJqm(+FZ`5li zFnaC~1UmZtgR_>6$g(UDIVE!%U^>FWt+K2!Y63hv8;Fn?PJTMb>TNzAL1%~WEiGUk zWpbM25pn659GrNFqVgjoN#OgSNenS>5|#ww>ke~rwZ($9X)efw{aG-fyRe|!N7Np& zp!>{Lk_FvTq0}BtAx2xdl%E6%9v8$?^Ha2kU81cEl--VIlo$@ij5k<_!p4k+< z&1NAeP>T+7po*#X2K<8Fnw!K=q@E)(f#q_GCsZb~;2shaoVP@k$lh2mh}8pYeMZNuB2U&sP*O2kt-iX&#W1P&319NstR!v=&CuSEyn^V%IuG{c1(q96z-M$2tKBECq% z9Cz)2loFH3Jr@%QC1Q*O=wnt+l9~v*%qx2e>w_KAu%W4 zlKqj;W?C2|V?#_Ed*!3 zFWQ5(D6F!1=swYzo$#$)Qk&)A%-6qe5(AwkaKXqtdBZg(zyOV)Y}T4kaH{V$w_Dq< z)^8GloxBSZQ*BIv9f2}lsW2waaDQs0DHf4Lo@<`7C&mcBGRFm$-zN>9h5+Ky7<^%Y z%}a!C*ng5JC-aWMg#_Z6WKZxy_M5oUc*EF%rKLMM#IcA7V2~!jQZ@Kcs1e+?nij>7 z|4d~d$AzWbDE1;W;u~b)ke}jhK~Z4B=d<5n*LNum)f2-ONtyD_2TUQYbHX&8t4WpY zqSwQWb!A+S8?jGfwa+n|-E}iM#c*(WrzY)`lt%Z~(aCd0*HuUwU|?po*nz1C=H0D* zErr0#NY6H!{|59n84;>1S`b#9qSJw-ESvF5=9l!mw$qyg04Rzkqi|{9WkG*ch0t%d zk4bH2Rhv(y8ls#P+a6vLvH>!7QbWkuVwiKV(nLY7<5cU2=#Y#4po=QTQgW$IMA+0q z)kQZw*SJf*zt_VvXH0Ci4)!9hKCp(iTz!&ZQc-BV(xYhUyUZ0~D;JRHnrX|c^;8MY2s5gnp;=`T7VIsU-1vFPGB!hlvPjL9sb_( zQ8xQ=u;sH%px??i$?JY6k&w9Y2hL|ACRS`+2pF;> zET&zc(b!Pl647UOZ|Qq|_Ck!VKt7uweP}I7 zaG{&|%i1T8Kh|-`)#vvd$4eQF273~Vek9rgLKe6&n`JRa6=5?Hh*EQJ8&ZQU7;_{( z%ouPqMr^1mO6!51v{A>+r*VubuV|Y|Zp$$AoxtXkY2s#56BS?R*i9tL7mISIHBk`G zhV$j7Jtb6sX_K>LeAaw%a+}7^EZdVM3Rj0{L^oyHX&4vb`V)WVx8e|JZunu!St(CP zPq>oG0!;QCV*+)!a0VW@KDk@pZD!~XsA^j@EB!hnMMwpLNA$OP*z zZR7kWwM`gAVMm-?9%ohCr)=-0WV`>#tMk?CYwU4z_lAn}PgFgOkIh11lXT#vE2&bU z9Ea%rC6~Ot{;@F~!8>AoAN}ZYLfacCxp!~_yKe+@2+_;5jRFeC-_iEu{T7w3He*bw z&4zn)!IZs!QB?bVIpPx`+@{L{+(_J3kGfW8SN)}!upPMwuSIFwQM;XJHF^6f#{mx` z236?SIBRi`R||edi{NGV8(0~9MyJ!L;mbIOG@aFW_Pfc(t-($eE=-0-a`0I_%sdW) z#WH;aTI%e7fHWl4F7b5yddNWmPqZg~JbvJ+dFGzUM0c? zqidZsWiP9EQGLayQV zZRipVJh6=LL>KyqxQ26;%32}%$VblOdWQe#$vpC>gO7j`Jdh_paIw+_%&SW`tJLTu z8RnrSi@oC>`rpDDv)c|ZWpE`h%D=3+O_5d?88m{-Kq?aSy$mL35keENfFnoXi3V{b z6p~r#2AgDo(z*GoA8)VL!TE#0MChi=7f%)bLSZ0s9`cJROR@SH!^ID$vly(CDz_cdtTjkpibn45M^~JT^S#S{tpyxV3 zfNlo=^d4$Wu0>6nGO_(f;9)T+I0SxuAQKg+Z&}`g(k~~Fx4t!cZ~)woHFak)(Iw-; zm%O&`)pl-Dwy@6hd}Y!4VSi28-(u@crLqlfm!h`QKH5!^HDZswcN?mj{L8yWl0W8Lb`luQ@?IT*812o6Yw?XabfDI7?lLK-Dv zBu78XOth>5WXQ4Tw@Cnjup)TnSi*a-_QnM^^hm6tJ=Ml4S}DO2nzww5nq9_5(E?j* zYApuFv#@6L>3RSbn@9oa1MSWwJ;m^pOaT?c&M7n}NZ*PReg^(m_trV%kukq-Mn#fk zZ+?%*u{~oOPSa(`5`o-PIhbffL@QGCBKjpt5&fzs<1v{CY3*o6!~+j$MjOvuV52~h zAtF&g<*JE@`kYCj7LCWzvtAoxnqeB(3jr*#F@`{9+OX8F{sI^CPqtzqmu6m&@WOob zI;kyP6n7aRh3HK6B~0hz1-%@_~Ol!J~)2C97CX!Npa83h|#MA4`r zT3{zhXBH4?0zcW=udzDAq6E(~8rLA98ah%Ty_){c90zl|p~Hcx0mG^=QhGEx+}59q^~$h2j!~bVtxsW<#AZV+PpIl)%a(lcWelR1m>?d`%EgNR+rB zxeP0u0qXKY;K5vKJIM<}cLuFjlyh1V7mFlyB@2qlO&n9=LiHQ9x+jT?ae)wPFz^;Q zx;M?S0|F?tL<$2VY->Iiys%2-&3x=*b9?vhP90QP0%Rapg(AR7MVSX!otiX2Uf0t@10!one9*`9q2sS^j<+mF>OnOGLvb-X&;w zM-2H9V&TQY^ywksN`K0t@PQj|m@c#A2x#PJYwj?yRE&lv%6YQbC7_{$XNtZzkWyhn zVDV%SDB6aBHA2R6hI|Pn10^a{SzI(U4)WeeQ##s?l<$mj>uEy^X>Z399Sj#09TSP( zM-DesqQeI;Js+&f34xC5ts;eG0!E2uhI~XZO3t7E>&zZe91qvX z2MT;t+i2#LWe0FV318Nca3j`estTA-*Ehs>%LuTfeb^Krio7D}o^Q)-=tk{a=G!s1 z=M~pNa0FCxTgz<6ED|-%k=|vYUpxj0mFTS8xLTy?z)i$a`2Z6$G+>;Bk!o)TQHgv(mWh@rSPNZIYcB(P?JTJ zzys*(hNu7?`vL;nMS)KM2y!K;1K3O`!a0F&vd+8V%xHWQWoq%Q!qcx2$Jbo*Lqmr{ zLk;yxPa#S=AyCpx=FH!;#!R()m?;C$W}+7@rs?agtSs|hFRbapLg;UaE4KLyobnOU ziPG%292?qR{k_Lc?f*pFHQEV!6Kprf}IHPjetn@tL6 zE3vZ!mgzQFrdqf2x#%h;J(L|UEmg$x)%@A}n8lY?p1S^nYZcuj z#<0;FHjY}rXvv`dPEHKWn|b)s@Mk;;HDRH3uAj9ZI4<7 zcbSK*OPj8sXeZRxBWGnABCD*L;zEuzw6Z_K40WSj3GF*c#1oIE=11*Blip?-3n06* zyyZ}oBMp>EZ_Dtq)LkS$+7e};>B`fohA2rqnwp+W^Y^}kO*(M-i~lobCa z42^XIMTFyDQ<-wU)<+}vv4ZD+WbTx|2C z@9`PwLQa15n8M9cw#{&bsvy(6FkEdC?OUwirFc==!c%gVD*7XAalC#yn633m+u*^<5KM^f zSB7LbYOhwkFdS!eU#b>uar1uAhN;#nHY0WaqhUC{BFe`)3mJ|V(UF;RcKBocp1w4r z?D>oSEb<1DKJ~(2oD>`!O@uUl7|B07cD^tax=INW#KO@!(&(W#Laz|aHe%YakQXgh zFRxii?LvgNq_DZUxq0LoL{17?fuGk3Oxb~#u-5`R+i=jxMn;<}Nv?CUYktXb_^rfY zbv)OsNoWWLd|X#aAYMLQ*UL62g0%+TKV_S+p_%KE!w=Aqic z?6!6>lOYF5=8SyncE>5f&}* z;@mZJRy>m4m`u2+Q*BFC51o8RTnIa&6X&jHHlt-Z693Wh95tU&%`*P&$Yb;nm8l~k zDn|#$I&C=ETpuui`)I+jQ`vCTZbdt++NbDO0DUIdTB>KA^FTQ6hdF^sW=z@(6yV5N zKdJmZCL6||66lYA5S!Cg9K`P3Q4GB zCS&$kwF&D3p488kZ83Ae_rGA|ujqc5bfyd7DUpkxx))qEVg~uMP#-d4IrnWSP7p12 z@S!U!%j?&peaN{A5!g^xBHX0nki99x?AnR8>Wnn~0GXF_#*|uGCe9gCdike?-MXD_ z?bgBM4rI`?B!{kjReb8+PhLmBV!b(0E`RPiL})D{B5JYZd3kgD#@#^t||4!nM~EzehBpdWw`e06_W15{dSHNU-*FnDhMziVs{nbr=%Px z+~&XmGN$?>LwYV1NKHl5nA(P1gNkhZyWCXUiu6=0%ZtUzXxrH2Y9Yx9R*T5|)Ekj& z{3#X7^P>Ie+L9x3TTWv6JTAJynT(nlu?f-BIG6^D(YD2^X`p5>WjcCt!_VxL-iDuQ z^Qh+f$xW&XP3gq-L?3LE^uXGfGzL>i{gXD=#au9XnLDx)3!ExsM;Lo4cPZ^rG{Ro) zsa02_fFvBl6cgT$)@bB?C6_qgseUR?+$XuTD>lGxvg2J;OY{b1YJ0=vp4b~)d{UcE zt2d}DmG`kqeG3|Ua(jEi08?jlns>)(Gfylr)69F)Aebp>r+}R#yJA1Jb2Gi_jaF@k z=5jIL+*j-y(qtIk(3K|)<4ME)ao2KfcBk?@~AW25Rzvevk~2r(V6%E-?)|>!ubn=ZiCU9dn!$zB8 zn*H9B7FvQ8JdKHiZLiUDjhI{fJQZ1YXglNg4#`(+B=_DCX}5)I6@i?#YNtxDHE{$4 z|B2pg7N#(p>iG3nc@Lo!vI@_o`K6fZ(B1sclkxa0|N3+$p#&Xx%LdKPILvlDg#J*I zB9V)*k;p}u7F>kxrxLhrnZrX6HKFGXDiqjCFb{P{O(vdUKk~MlVHw5AoJ}PQRd)3B zrWtn7*gdHk_8n&E?YJZ0X)`<8uaNh<$s%XizMWwk6oKEiz)EI%*!jQY5~a-zRcz4> z=E~aI|DPi%CD^X?EM=veZriLu(HY2XqP72NLDG*Zi)*mn)2eM~H^Vj_kkAm zU<#H?2iV$WaWFR+(I&N=Idf(CTxKwfoh8%PH;?D&i785OWqEb&%JP{3xDU(?X0w<3 z{-A{6zlr4^YK>izyB{(4H8;CZ>o$8MMF@F>{O_LIxQF+S^>4bx7pZ& zC8^oP-!RaMb|MU@sY3i~ ze{|hsdY4axII0pUUv|4uPWpT-W;e31ep%mdC_t5fNg%Z@ph`p{_Zs^?4jd*(;lC>I z)DLT$Wl{nv1ecet>c7UmbIrm;UJhXrdPhky?Q7AQna_OYGniG{>NC6To?l;CsV=SE zTwAzSU0thOyN>VO$Ed?h5n_9QibF)=iV_HR7bAl9vf z_UQn#i0~A_RQ4~bD+ga9JoDRnm`HH^k?7t79zN7{T=yPkH9mIjK?4@`>MW%D6g_!@ zQRcGrMtK&~GUgMcSP&Q?S+&pu34LcP_z{gvXng~owBZkF8(@Y42PZ>|N!}!mDk)9a zd~#Yrwqg>1AvC0?Fq9{CPZx{!sS`GHDGW`4ugOctN)eaNcs|OD1%Uyp#zh0S;LQ1H z>?`aXYnGgGX@^+88v-CL8aKgdQ@_2x-MW91&Hl@9WCI@n)yP13Kv1@$Wt?yNv`_}M zx3$NJ1j+2N+#gWRsw5$}trLzZR}(Vf!h=iI8*rsfJ}8ti=1VKf*G&z^WbM3KXU?oF zx4LSSOO|=XrwA7d0^vUHQGKTlw)LPg@l6sG!3F$cjHNN~W9+pk(jtYH;U!6{M}nMS zwZb&jlfU3u1M_a0si`}QPa+lGX0@mY>Y$>W&;CmGywOzRJH<*(M>d*KE31BK)w?)E zr$cJ3xtW-`Q4RA-CC{K#qqkX$sP~Ri&vxDVmUK`1fqREF^WELMv<$jhzdIm!wd)GA zTOdEP?%Pj;$LrVhe7kOKzkZijJiTwTLFzF*^7ht#;NFqz_d;+qp^FgGzISI&=brNv zw`jH%Anz?>0aw^790y&KE$wb`R`Y%Z1SMD((o+RgmMc(@v#=%AvDE?@87|6V)zjkM ziPdZDGNp?=62%j09K2IPO|0#$Uqr!=GW|1VTu!w7U9z&t?e_;-5TL&m2YN)z9GYQ| za-i)3Jkfz>bEr+7A+WiQ&&ci-Y zn{o13_?;oh+ehh)pQEGWggfKgAI0WOOw&`@9Oarh&YbmlSK;^)^6w7aLVA6!)4G+@K9EF8AhMWWex$Qf}^RJis&+g zTo8esPb0a~p3#AbF;teBQj+1-IwjFrnY&k_EyUDI)xi~hc<2f@H6tCL0G2BX9?Vfz z>tj%=wzqZCtL66VqRwpk$va&r0S`*ri3+_UAg)68%rPonTl1siDahPDd^R5x)U@Zp=k1Osz< z35EQzwa6Hjff9=yecFMB2nAmv2`l;-SxU=p>zCOqJS!qxxxb^R!^7^mSf=kPneoLL zkiIDdE`7BsRTebU55b3jQU*R$s*&#z4G<-;_lCU`^ z!rgH3v}ApPWd_GZS2B$Lel2K%nTMA59<{c2>$zwECdVn!waQBn{;a+Lb6HUh&gIC^ z!t(lBw6gsC!X-_1drogWBt#8joDp?|?9@#%|ns`+8Fql3a{r#c%fOx zu18y+z1as7ZUgey_>tyPr>vt4%mX95S{Ty{tw1ZyEV5w9 zMLUhx>iZ;Q6C)+PAK~PB)YjNU~I0>E_iiVzIF&6wNc^3T^7i)2K zFi$Byw$S#Q ztFT`veBqx^%rE2rZ|Z;!pIv-P*w{mMSb&ebz(NK8Xt8UGT-cMfdk4|_!wq&njaaMR z#!?cvW(J3w-Z3DMwb`iczyTS=5wQyOxkYCYpFU=#m`NENNqjUxI*S347hn2ywGFvU z1Gz2AMID6pjN=8^cFmOp`r%D@2nEFibe$Ny*%CF-H>!X>m}1F8oHo@TQn4gp%$bpq zCiV}zyK1pbzqW&>4-$77({JujZ?HmROh>U;5`YDEelqH-H+AETa=VyU%PFTnKw%;t zMzO7MD7G7V#%=KMkTeMSGKPGeW@_dlZJzv}Zwg-I;S!S;UUF9vbNe>^|dKYehwO%EXA)bomLjL3Q7Z1EaP#Q>! z{Bam5=rU=RDFOb+!(XD%^B^J)&LI6oyipm;h4x+PH!Gns1sLfmj3(fE!Xw!UM@sVwXZI3uF%v$9%2HY*=Xd@+KjRU$a=i~Wj#Yn&^u`FhJ-PE36l%=zrsF_blu=SETBqZ9aFD$`s47$mnAPy60MU>0${0^Gd z{M=s9Gt;I7`u1wRNdOM6r_^ocU*j~|@t21H&pk-kI83B1IFL%c>Nb0`LEBvzpEPJd z!rmc{Y@*ZMBq{SAnO?;53L+C>#QJc=vn7nshfzlHBNoX5$wS|@fKkr8t2^?d!m&b< zbB#tIqHd~5Pxb|Yb6NN&9xYE2p+Xf5#uD~Aonu5>@30?I97F{X--tVj*bxXGep*Ev zQgxGg%5W;TQ%@|cL^!7?hZx&-I1@3kf;Ro?z=9fke;^JF9ODZR%iVhAHd>_!@} z@8C@0w`qclDbK;Lr(c8kOmVzY#{^mw?=wNKY~865qH23iZ)1t{O0$&_BqwQ;eVL4< zOti35)|#!GY6NbwmT7JfbPOU#VsvLSeHXFwiTJVH%ub3A{#MjY&Rod(0&w2JLXpUb z52>jC4iz{&6a8$UOIjQgsEHndAuU}~1OW<40M$zov}1*%U;Rk6&c~bri+G}iPnOHT zaJKgVGvCQ!^5ITC-eJ?+&kr@}BL>v}D%Ywl)zMI9{|`*}M;a;z5kqy5 z+-SQk%T%Jvvbe@WR4uCGA-a=*dzyFtv}=Pf0dJXhy02zO*P5hk8AEus= z5Up8dy?R?*IXyY2*2Tq=n~thpGs-*%(_{oUSo>WzdR)~4SttdYcs(c5>zUMxlO3X~ zWG{gK>W52$Ad++8e_4~~TBH7_~ zQOvz|n6O*Kwv_^Ql}pvjmG#9ni2Fn<)yq{JQS()hSZRZzjX|?xh!>+{#&Q`$E?&|g zU6T0>yVs4-2IcKvmIzx^pZw`5@H@To1Hxsot)1t{xASb|RGpn?H(;)?tO==)Jg0@Hjb9lIz zCwxT%I`T6<5OQE6s^}_7EZF1{5p#o-|B=jQdT#~Re&#CkA4jljf)Ce~1v(MTzW$-n zq1A!>_+(yLAp}qgql9b{fM8_BeTp%iG@r+jN!f9hCU=ZP`}Mm!HRcQGY(cf4PMqlgLY|Bkc{_1g-~~sM z<8oX)tp@(qipHz0`W>OFldQp!fz8JglrPorq(o7UBCPrrr}yV(`c|O}pzTqXp!Ih>p}2 z3fN@!&V#B|3ebi2=~BmSSw;6)a*t!?(d`!~oDSQ~Sq)=k3;kPJ__ouV$7T#6LnC3( z5RKC?%($cH2j;{;aBzp8*-6#@3ez1?4t5;YsyEg&EiYPHUQ0BoMsZd9q8#<9MGejF zM-hP8K{SYEAxOjoy@f#hs-7D~Q6>;E@j8p>6bj@v$4{4{R*Aw}Mf}F79c6(v=v~b> zv1bR(jA`5worP^_*Y_uY9RCfPZ$uF{fORx5%>qp6Nj3q0RTf?R!}|0zpvv?FTdLy? zj87Aki!g^sk>|w0?12+si%511SSbrdkoy{vYp3jn?%CSP)xh2m_9Qt~F}JBl9pfdOrIxDIhtlnLkMalGMqHo$?f(+?$%*g4beME+R}Oa7pP2 z|J6tRVpC@_-*(opZs<+y{qNOxE?cL25CF@rXf)=%t77$8@^() z`Otzup!Gxqk)(QKzIxpfrb=|OTmqs1jzTeFS;xOWkuUat`qNPaWG>%(g26mI77Tux zNa-QO?GD+@aK79$=$?lE$yXDQz`^Aefe0$eH$o3_Nb{BNDjH&ehl?xBlJnqC{Fz^i zL*RqsCydLuDFp9K@kRLB1OFy$*SNq${edRzEV`f9fCFCWH8#kWU^GzJt1As4w}&eGs8-QRTAoA=$6_urb(SIt9k|EA7g1gDi}qWn%+ zBd-R9bwKTc9io#@0%i%oAUO_dIMz zi2TJbZs2ccubKa;{7?StL9pxcx!jlb>Y&Kx%?GmBIEN4BeRr{nH@MZvH^-Or%|D~4 zD%}^qc&SS1>3(Bt8;MLliKz!oYMbBS@~SgPpq!J)KT@4 z?kmv+gZsa_w7$N*`26ykZY${zQ4UvMX3yII%yM0=<03;$A`(p~NgUh8hy!`>bYZ@Ycq?}cYi zv<^;CC`UFfXvM3Q=c?C1ZG=AJh9lc*3ZPbJoar-6w+L$bD&F$7YYS^LZ%JyOSu-vO zw4Oa*U;Bi7Rvq^De@}n^VE=pa%7fLoc4W0#>wl;p`SwHk{!w~x-#72vf42F;r#@e& zV3T~7Ui$m*c9$c^jpxY0{bYsi{ZHTHAYD^@IA>Y)n|JY&d*y@^jFN7=dPPyrL9C`hmm$%jD~4 zj(z>T?sDMbQKfnvnEiKpB%X4vRknP}0gKI#u+3?r1Neg|h>OOLBOH%gL(opi5F)*f~*=G!KNf1%c z3yd@dSf=>02K@xh=jkD8*tv0voiCho%esfZ)oPZRxT8>Z%jlvQhH_ksNb!4MGl~{y z94#umvbGK;h~ODRRZ%K_;x$KBBl8h*GfiL9?W4G1wFR9|ufLZY_xAT{JKWtjceZ!8 zTj=zW@=S-%eJm1SMkYFDE`~{?HQ`YMsGF**&8I@n)MDMA`Hp&+Bs~r)uM!x~*GXYQ zKSL;EX<0cA0XcGooTb8uy3+h*4bLGmW)bw~grMi?4!c{st>!M-4=t5#57q9q8aH39 zZQi@LOS8J&H}aLDb30yEy3C_g18x;Ft{SrPGyYL>!dnsS#y8f=(?p4*n;CD2ZOn^c9B1|Xa<0`xSSu;+PDa6bGa-#_t>W0HZ*F2L%- z|M_UIR^i|L!Y_QoUB7@sn7|RyS*>7ZR6+XCZN!zmOj@ z-j2WpJRfN&bh81m;+=ZqZfm=-ck^}~zCBGed56Ior-cueFL8Y>*Vsq(!T}bbTfA;V zx5{Pc%cfpG5rOqN*gueDJ|!;Jsd>@*wt#zJ2f}cMQUCUp7Jyq9x(b#NOcX%~TA2+7 z0+hU7lN6SP?m|31SiVLXTf~DhHc8Wm9o!E5g2H2}uQsc!s5OY4vSPhCs5BL0L8QJI z23}xiaOG#TD0Qx}H(vZmP{~OFxrGNc1jG{bk0R+S(lDfbBN+e?S+|mZ@yXoRC{(^L zEX{L7bN{img{2!DLc(1v0Zzi<07DgcgME*^*=Yfx6D(ELB8`-Wy9 z5__C3R#rwxyH*aYY;OjGY87~YMh&W)_LE9U7t@H9ba_H(1zr7&Ndf5w-HJ&B>hM?R znvhR0;fMu=j9AzZ&8f-B{P)^qTEv0gIiqrUhBXk@SMX|3hPLi3;uYSD#&N$sz# zsl;eh?fK=U%Zm$8gR-PWg_q&@nP2hFmPrBG>)eBLxFl&qclYbJwhv|pCP_muJk450 z3=>kA1!5zw((O(mdTkH)Z2+HiL9UW-u#(#*gXbyEz(6y)wNtORqGpYfN0q2qXi%m* z__=pCLLQV|n|xIA*J=gEfuU~`6~GQhHpryaCfzE^8$l`eN1FEvBdd+w-8z?sdPK+# zsTCM&2BGDufo*a?$3YhY|7+V+cgm+q zor635X%h+UGC&1#g?lOqYK>H@I#ppbdVYK7+;$DvIAyrowl8((!BAgxOGU;n1!9OP z!+i7_0`3s0&4Y48cc2>Zv3?iP5EYNqH@6D=$Z><-8|}KXfMlZ)na+w@chDhs>NKW! z#v>B9DV3%P4;odw(AeRLMLnW&qx$bP_95l#=RtZ{28*N_jS0Y|_zOtjxCsEz4uCUM z4!EAS6_+4&Xsl7SmpT-{jg_qHO@2hc;lo#%?8k|_#SSU4lPvLn(e=r{A~-a6#VpK@x9THKIgB0{6-6ekhu?v^y~N|yQ2q~0{b%wADa<<96f*|ct1~p zuO%dd6dO*4)Ldhqfshb2T2!g0OB^;w=8Bla3;xSyD;oI9n~lbsd|6W< z>UAL6*?y%y(BI!M*P40IcNI_n{)N8VWW=p}cv!&iS5#OIlv)tqo7)d?f+}YP^sbzJ z23;t$c*P%gf*bTv=jUzZ^O!b%G-@8@hpc=y=|1U&6H( zToi`u_l|Hu>bnX*>X#Ce{_ieyg%x0|kVM=srcT>2xg(p|EzXN-we^AG49Gq7jZ85t}=45Cch$xny${xlKvvB%TIa+|xhc5sYok}^yH zA^}PU6sD6iFmS|a(w+*`9LN_&pn0mVH=DD!wS^iAG6%5dqdaYo-qMyJxKdA4z>#RYBlJ3+NIt)^Wh^=nWL`-vMI zWb@?1Oun!A<>YHCIoO4^>1G%ex9px|ry^5=fTjrwf{lIS?Y~CQpO4o_;?hc4k?+Pe zVivb@ML8xWbw zEWhWghYvV_vcsoxhJUj*ZSG^)@+>~h%*~X`WAyRa=age&q@Wyrky4=umE13atE7J_ z!^4-^1R-dUK{$dLmIDj<)hlQ#-EZfnapwmLs35?6h}~6ypOSK*aGL`M$e8Mj4C%R4 znDeasxhogK9PuX9w*Fmis%=HODE1S!@$Awq?56gOrJ+G%ubjhu!W2e#Q!O&LjtCDk z42XuA+a9cR7z65!$n}OP)>WNLamCsXJrvtrOLGzA&~tg91G30WMokIMBWb95YN?p1 zsVyBv@ix<-ST(`hw}&dJ(wpi&qZ`!I;z*jNoNwj~va2KyE3t#(v)Q&LC6&r8DP{YX zQWs8zGmny(IT}tDF_gMXRG|p}k6`hJnx&>9RkZw9D9)#^t)hFwD(iLm&a+rO1R<{lx zTsqZU1of~Q(R+SHOcjw0mn#eKD>f=B_H1+aCTh5TZD!644Q(iHvD~^XhF|-y6=DdEjXl6gc>&GZw|3qJVO_1lc(Cgx_M`7>_2WBJxsEih1@U z=$n;>e{7H~+j(nJ;%#gX8qvsboKNK!0wy3@3a^J3iZG34oC@Wmi}n3xZcy8_o<*@K zHm$Xef-m?sLsg8I?LR`tp9)<=nSQw#F62xRj&8dC0v3hOHTx*R}64)g(vSfGK$QF%}-RV)-gw=9oux6=< z`wH8lBwF=?5CnN0CW8G*S7wzT8i5L2Dm6H^(DFW0<6-DvZc;@B7w&2tk^?~4>vYa+D_V+7|e)taGynf zjpiXNK4R5Xu^X@_3jQ3eu~P~t|3=kC{svzTP?YL6rqWb~42J6Q9^TO}=CI_iw0PdtAIK+A+3f%Xc2n}8YGQgRsYE}(N`lb{_d zpO|4ME8ny=`58T-n8klsU&6y5v&X!AzuU`_iaV#of{)oF#yoqc9WVSomApL(FgaLI zP(+>vSBkbLRJm9Tr4~qzA#VbY!9|5kfju*TEwHSC5e7K6v_Z1mKng3UEB-%|Dr`(* z_}iCnA#nqq%8rjDpS~bp)brmBgF3QW!vx~}SUf8+-Q&{wZ@zi>&=b6;7a?^2CWP)u z^gdbWK2_j8h7Ib|fv~}i3{W~&c-@4dn4j$d0VfRtz#xP}1C7#GxjaM|H-NA~c|Zdn zca_jGZ`KYEEJAq3b^>cH&sP?$9u(PBL!V-D1Q6n2w%WFOw@@jl1}Vw(usis1Bb~h)D4wRtOj~}QiPq* zim*Qnbx^3keu&j-%^^#N=W%jNQKp?(`sw9reJ5KZ1(jmE^N^cY9P(lDgtOT6L~u?k z@{G~kv)Xx3jQq=>q_vW6E+^4jd{OC?Pe>Frn#zm7QC3zNk%hFtlvK1zV2vf;i z8;oy*3TGE16O{@A@pD4Y?-a9=RvD!`6PJA+x>70#CKvdz+Z3xpDdN#rR_7@Y*FVC4igTBCV$ar@C1h8h1o^eP_BZ;r|GBaiyb~?# z)$s#D_NC^Yp~+rZT%Oz6BU=3>L8o1B)rsD1B31M2AnmpcJzNAU5-%v?6oE34i6}_Z zgozPAB;Sfh@~zH*2@p5FRw@Y8^XPqC*WDWS@$Hl9J9u!|s>7YUWwH|!?{F8#1Rud&9qyZ&yW7*@9y{?< zju;Cjoahm=M2dB(FoYnu>Z2q;oZ3rW9>vLa-CWhJs9yhg^@VyJPcPqp0q(T@H;NdK zq+D))UEg3ULM7#QA1f4uTRw&!q0?a4%;6#pr&OPhFob;Hny@~K(_r5mu z)G=>8r@_Vzus)~3MfH#5=z!d4_MT0bK86p$t6v5AVw3FUPlfx6px(SSlaXg8O-7z| zs;_x|)$962%}4y6qgiL-+s`x?y%*+DbD&PC=X4h(@Vu5Ke5Y3;<=0&uzSFp=|N5W# z>%$R^KrDMhh$RdtLfJ*OL(#8jW|mN5a`ZSjUnRG) z$S=w~7}U0y$8xukvo*j;R-_smJB>_kW!jp;HYTwtcL4g;8?k#Vz(jo4eozg&;ksld zbJ({H1elN~IwFaBS$?Wa#3&LdYU!ArQlS4I=oC>7R@_+PD*EhxO34T-exTsR2YxhLr(4a!bDQs1Q+&3>}b-nARWhZ z?U=^84|T|#;3$<9lD%5>C#xU{CZBM^yTMqF&Svm;d9#bmxbWtKEsO-92(m-Pt2baK z70$3Bp8+uvJTDm@uMrM0QZBVwxOxV&m#Dwlxsft>%l)y)p4uTr`&mSW}y6j?%)cC-Q zyFYo9b`;Jk3+)XM4YF0(UmCL4;m}Y+y&MkJ=Wf9h1({qc3{g0JP~S7(Mo)#pC&`c| zMX>30+CG;H(ord|HKc(soWr|w7z4$a{q zoc_}fO&TjJ6mN$t%2gn>C{Y`*yoYkI2g>3SfotvSriLc$0EsWKdAciCvMCRZb;4 z!71UhOP9oG6i13@GDV}U@1`n-(Tf#xQh#`8`#5Sg?vXPlaDaK@>4X@RU@{>^C|6c0 z#)$hcfyvh>oMY9kdmyrD<8NPrc&z<@?UBe(rJ1{cP3ls0tulZ0qUJ86*jPZ2ouKu2 z?!<8ZTp))Zv%B@(#{T_}lFP38ta7KNJZrTfCpj_`vVr$4_wJLOT)2wIV7(Cy%KSqk zig=cEBCME(8m*22$maVQ zDM}kFkiF$$%-tWY;FgrM?xJ7~yDn4~7hfRH>};bC76W4ksUW{(u)pfj8i^nQR@7Z*NWrTNeIjci0Lx$KKC{kqy%U8dQ{c}CETXy)OX z^dkFq9tTQAL5z5GwMWBT^|PO{jB3*vv492cCmT$yGjZ9~f@$vgELQK_{MCrq-(Ii8@R`0j@%E zq);T47u+HOJ%&s6b*{She6_kXGR#u^_zeTnV^)?f{;InEp}zkrGN;@lykEkR{pWOL zGH3Q1|GqDV_m%`P#S`D&`|%$q8@OZ^+MQofYkSumnR&RE;QvGP%W~Ud?>t+Mn)%c( zE7dDNHU?iPhl{-=&~Sr5R^}GT+op3*NLz&dsIVAF#=!Qyjsjv1nFUs`3WH*^^OfuU zQAW?EdO^-voH(Rc^)5=UP&x7|~&*+zQe z@d>fLGl-)C`@%$U@RtNVPU9MN&)JzpO@iQ_BAYW$BNCuM56(dHo%6^Ln!pF;XH~d| zjg$l}N*DQ#=5jh`7$)3bZ#CKw*!)<>+NLXc1e&d5(%fb zTGE0Oh?#lNLmQa?k~xA%8l4>=TIa2^`ud~yojv=_Z=OB7ymI#JHH4`wMZ(g)2t! zbX;{C2=^aBtkF|h7+4&-!Rk4XQHLE;VT=^CkODa~1r>or?}3?w-uU2Y>27@=geT*u zhVaUE+V%oxJnvzMXDsfgkT=pTbttBK(ot+oWES9!8u42r+LNDuh>doY{|RJ)%2Iv3 z22fqLeEgMY6InJw5Vr$RDhb+{7IRFT_r7CHBWl@<^9=0FFZ?JxxHR^+hKLt%_`vW8 zh6GJXY1}*U&Vl+q)D;$%+C|yi+=N^T{pTFPR1mR^1gBYj6!)B19?CC^FD-)NwfC38 z)3LcNC~4~KLf1a=HT+l#CRi2lwH;D0OM-5c+@CR-q)0JWUTYA8rOrFKY7Tq0^7)cd z_B47X^PUU{f!fSkxy;_*80#nRZ_P6q>`pu1OPuE@j)4mbkv^P-j5}KP*jKXVImLOw zdb1N2$w7DwY>acr3FMIGD|s&5j2#syt~+Kty^vTz;LC+y5gc>lBI4Z?&y5u=o1kv7 zWTb+2RPQgPF+mp6lTx|+o{eCgdq#7L4Z;1^ejV!W&DKpF=jS@a0Yifv5O;{xU7VRc zm?Zb0-7!H!Ix#1&5Du!YBsp(&up>EzH4JktxV{}NCOUU5jR}n5Tl2*J44s?ef6|G4 zymNI-U_Foe0Knd_6%C2R*~7^p65`Q2J%V>~Z5BUG#su`7FtKitSHdcLB`g;EiP)ZO zJ_%MZ1ca7ozo;}Opw4cbb3M0EeLhNezQv#a=)86VwtN1-U(^CfN-iw!2TYa~|7yH| z3EyJ~@(UHPM*JYtH13<$@Yl#tpKZq=p>t#r6 zm&>pd1tf$#`>Nbjk)k@_72=DkPKm0DzgUqRV!ts%7lMPDMd9iZUCcE4`kF7WKt&Sk z_uDc##~a4tql>D_Hp{r`gAh~PYu5K$@ywYY;tHci!(pnk*jpS)tJ5yJ$o7?bAk|{l z#I?37j#+QxJlWMd1NfCgmzP>pS2Z%_mCTmmj;js`dmub}+XAz3h0QcEO2~I_WdKyu z@_->WT{hkF*+1)>`JTSN)YmuE_rbmv`2#1n)UY39O`d_5dj;}K`R49ldjJ{GrS-)> zu~*-KxjwLRW-0#@^*lxV++W*$eTN?wmZ}G=}rxin=>{?yPbR8#_KRgVVUX#=V-4(s}4`wYuzvHQ=F?u z*{432x(_{?Aug&7^k-hjX!_8F!)`M_RyQ&Z(WS~-m1P6w*H`vY#hVl`8121)-ONj0 z7Ko*>dZ`)wWNQ-S7Lo+=H8@}rZwVfAUytUmR#tMbLPC1S8lqPM06!+LUyfh$vwT+K z&m=lf$dP%=bP4F%DC}Hqj2`r9QFoZ_TZQv-Wg`#p72Y<8>|YzbKTFXR#W#n?*(Ylo z1ZN@j{n&HZy=8&B>J}Ps5hg@(5Og5#!P+EegcByh>9&YmB()l?DQPe=$_+4aPNM=w zj+-K&#;ro%V)e2ynMi>Ip)m7e6h)D26#TOm2Kr1hRVtYITFSLbi1G~LQ%tlj2QTUf zI1liYgj*u@oj=oX`IA6kzabC}x&XlF7!(~d6*GNg6ETpF-h+lX!R09IZEv_n8myu7 zd~$LU{plO7DaTRW)15YU;`cmdpciZ#C$DCb&@SJ=99LhFAI(b=OSnXWZTVsORp6_A@X}2uAh!H41bZy{6$KioS=sYY7q56?@nrdtjFG9XBnnvY?pC> z=~U|yBhmTC+sjvt8eQkp07F&rhyRh8RK(0g)kxGza*ZJMA|8*X~G&HU!L z)C7uqLX(QClT=}@kJs4yVg}LBpOmv3WF;C+6|xiSRGr;$M|Qh|Ww6)TY9-Eh(_wsP zXE&hcs-6{|X98z8x#BOW;mqq{H4EHqt#63lkeN{_-V}I9v$uGTa`W3{XBhRY$s%@F z0XF3mUo-W=-R8helQGp78A4IyD*N!W9ZD5LPif1=d9r!2W^3AMzT@aU?7X2$T-s|8qr&Nw}3I}d&@6?|Lv+gAH8!bH~W>QPjPY{lxj->-hseLky;3TFB zQVeR5hhb0T0jnryIGGqU_Wc-PzxSmjmaj$Iz<(}*;5YXITwHNh*A|YE816XnM^zy+ zWPWSntf_BtA!sn!G7wf)B5qDBclfaoG?76yAHIWykE_sn67`Wfnkw#s^Ytw-Hrz`t^hTH;$$A)R`_W&Q<0=j+|J_xxV8q zs&PTiPoz2>NUD=hSvvs1zu@dz?AG^h*JsB_RMam*ki;Z%uq*|;_!sC_^0^ctns8qSbV_gXpz8_5C{bJ1ss-F<*L# ze{a6@(o5^=QU4-9UC0X$lw;U}I2qZeCczol>cY|$NU}q)xLpgl3MbJFs_{BC$+Sx~ zfqv7QAy!Z7xuuRI%@@fX3>OFc!Ny_kPVMSOeg$XKzk;!_ZF9cyp+W~%9{{W^Ua%ky>glL?0zLWN?#2gq2Or&OuDk2jx%Xxl zuDwg+0>(-gY=TTsipBO*4Nj1b!dwu*4FFp08%D@8^(BR=l_J z_9_IjV%xX?CXGZf+4{IioIPgxS^kY-U4b8beP!WVMfo&ChH|%bC$y0MPO?dDPv;<> zTI(c17i6pVgm+`~$X-tkMH6LmUEhp`p6b(TC&nr$bs0g?vytcoCrbod2IP>@Kcxk9 ztwbdUo>nGZo@O&H+k3n9V1V};d$rvB9|I_%$-s$ zc5|CbfVLLf#-hV7)&wWopr?TKF{LaS0L~!Eb;3^BvH^aREF27Jr$502}m;4 z%2}X*XsEO0)7j+`Sra2k&^F101FEy+(l(z^q%FU5iCMzCM5&3jJys8nr1l`qAz9TY zA7=8RD)JM%R#d# zJ!_k?_UbiHd-X&!gDR}nHbqJ1vihf;bX{i>bX`ASbCkNSw$i$|5F43zn_wfKa>$3m zuPh2;F%TdpFa3ItSjvRJQhfOQTiv^`aApj8FJ#GtPh8Ve)oa(aZRUe%5@pjTj}b^o z@zx7?+;fpUu1+Rop=PZpNM|^q&#o>roQ&X1MJFw%C(U(k;)t8NWhdrE?KA{+$K8_^vYD4ZL7BZ|mM z;P$QD91e$tRYo9ov-O>llFp|?C$fjgMFCwx4{3u@i25|aB+a@9T~5StS)VXb$5ND( zrre9?5by~j37UWL6M4vN;W8n={9pXC3A91KY=cBR8Cb}hxF)TL*lUI`MUMKQt#iI{ z--!^-1xdTIx)$Xe(1&C+=OOO{EAe%LBe-paNmA6uUl&9#B69(9GCFvM$i>Fq+I`v4 z_VYx-sJYH`IKTr55P?AZQmA*ud;w}ess-V1u}I>Nq^Cw#vaXt{ib6WttMt1#w&{>; zJ^!TY2TRwpBtJz9w4G$bd(rNn5Qvf4yp+H*+4kMYZ|1l1KuZLo%fafyCZJt1Sx=GF za~+Yl>|6XxVhUPOdKo*t5nlzrHhY1$+6{f*)b}lYug_k9=^LtY{&K#~8Tu>KAy09w z=hqvaso?Dn-*NKXPIH3USWGdRy zwwGPM%AVZp(8sFz%0ty@_2;C3r1j7llOE(B`}IwBK|OWlTm}|E$vgDxr+lqc7FMh6 z%7D@7;-p!u7G+?iSofL1EdgpIZlLF9g-)=S&L#^+&(Y(*589td55O7+# zqN}?tlWmlCv=H-FoCT8ttV(OJnqX6+-CcKf`-Y#>=UA-a7$bB1%O@PGW-Z3=CV_?* z3^YJ@^$D=4de$VwoHEd>zl$T)BydShW;P2`m`z0i_Qg-=g~#jd=RJh#kZwC?p(o&?4izV! zhpB!3BRzF(w$>?nhd$qbz1?}(L!YP3VQ&mh={yv$J7|CBG=)%d-ec!sZ<{o)zJ!A~ z4m11c-cc!U*EBgxQM1Sh+c(d`qzU`?V)jmO95H<>Zm_ zjz@j#-qIXV-~JFy_>L6nn^6)S z^P|Y3-ZmST*QfarKT&O?2?mXM<@<%_}mCYxcO#amR3e6Otrn6|9`; z(}IagP}T8KFfik`xB8u0qi|#U^;D0Wo;Oby3&H$yTsO9`{++q_&rZP&?f>dkJpE;U zd2tb1O(sH$8`?zAv5A2uqodwaD)3(&HNOt&ezU{(cl769(zSQfHsPsjcd}CgWA+Ix zCreLcjhQM<89x=}h%cK|Aw-$AOh(uzGVTL(u|<3bPgnh>=a7^;T1%P3j1YAa+x9t9 zKB`oe-qbD=5n(!VEN4*$_p@!5Xc8yFdt#GN&v^6vCK$$aS|`QR(}=4+h=0=|s$I6u zUM*Zf$?c^I5&Wu4Ng76#PD?lN{?p{Rjg)nb3V z@KxlKVA^v^5R^2KajUUk-@d(f^OgGjCP_V6i5Dwnp^RW$@r_`B)(^87)g^X2S`6N> zb!f>Q65B~M2w~vaBJErrP~s#w_>)J}of3qh)7(=18euck&^Lri@?CDVj-fV3duaD= z<%|P2>0i!z^n#Nu_9MbS3BJ{2MB4on$wG#T^oc&hPy(V@S6)|@8acI~SR|KkiQ6aE z+#lP0A@Bv4P|IU@fP=QZ>rGort?aJ9oPG~oJ3E;-@muF z2M63yZ4dss@9o0Lz4BbI*iei+YS7ZS;nl?&-GKdiGY4#1Uo;)ff6Q0B5i!(+n7jHS z$gPO+X^thrR5C+&h4;1dY$1`%VN+q)!T5pfJZJ;i#liQ@(4|d`@H2h}C?qtLn2k3kXqFy5X=_X`a@OvS8hbtWbiDTS))}V1?u1D(M&H;jp~# zjPhk+)WdKlzg%6-mGb5MR6^R-#dUlg%TMRYJP}rCS*VshSJ|Mi6Zr{NSK7ONsq!-U z^kO;VjoF$eTTu%l82HMAdsrgT2)WR$n$?g(xQg1w7P)+na(WZ1@f!Fh;wpij8f>y6 zAM{}r(dG~T?AzG4yEdH)Rce1-3!)eJGj#*|k)u$yZYBg)CI-9FE#fg!6E4|^?v$Xh z`XClDt}&QGFd%SKZ~ei?my%gn>J;JiWhAThM1U|5@J^J0-to&F%l&~Nh`Db%)tF8N zv$dIdU_&}$sFa#H1ED1U+w=EtLfC)vm6^=@R+gQ4uP|khs%297!sb(P`mhF{$8k8a zg*4G^)Qis*3T!-Xyf6q^Rw!h^oO2j zN)UWVd-!OL2b^Rvs4?Q{-qxSo)dt*7G&KB#^$zK5$e19$X2OeEhdNV>+njwB zKM~trCXHtV)trjZtHsNtBQWKO|4%C+b0_28{dHYo> z5p>SeuNg9JR|e(keIE%*l^;9mF+7r932L0wg0Lr(;&=`7USg@+ex=x67sk~!rUivT z&ppEy?H?K)+F{Q>`LT(K36i73ZDIm4dR9$#vjISIr{1{Rg0k$*+jZ!+aGW9jwLgQx znJgV<1Oci;4UbYdCce!G3PM8to+Weih06_l72TR7D-)fi9ptNrA0s_lWB({VIX zgE3{60ac=*xAM31cc6!C8?9imR=Eau>;%O5k?$a)2R4@tEW^|^K=0##!eK|#Ne2<{82=Q>1 z+k;jv9uZ8h_%KoAd9N#A><8@Dnk`aW)-z#Sqt<0YD=LdG{BYHG>LKfMvTXrmNp*lP zs%ms+b}E1~rv>t;;cef;XooltEll%)o;pov9F!XYiF?N68NEr1`)Blq?9K*G~Ds zP=0j5q+`;Z%BHIlk_&jpH^7VoHScXOKyF;U@sR_rKhPAwfTP-aGWfOE%}E}$j*WgK zy^&PmBi2`U2D*k&f-&TX1@%P1{pCow>XG4cqN^eEdA#chh%^Q`oj1PvG9b%eE7^ z-N-!#Yr28XW4(0j?X~TJCr8tRloCGZn)sWSt8een=6fi|E=z6Oif+NW$H(@&{@Csc z+SKq}XK2ICZaq!mz=2i|1=zIm)hOncg zU@D9*jD2o0N{>WygQD44!!xA$&~LU=B3}W~tFl@(&KmjNs%`AlNqPZ}cp}U%2!NXJ z{q*o%^y3s$KD@p6Dfs5p3|RU$FrZnXi78c#A-ZuP>U}^tmOK-qjJdkTS-h$GF>u4W z2+5%5s<}_{#iFjlb*1bM=#aQFgu1A8c^N^xMA;qOfMHYfTm%2tJiBm`L{VZc4@g7P zNW2)qnDRI1LUi)^l^uFfOFoQ5Kd{;O{7zk2lt4mbS>np#3;FC&tqLi`-~E=l*htvn z_kG`kMr{*+u@3vw&+mL9p|_}05e&oq{IQ_5WN8>Wu+YW|f|so~6XRM~J4Lgcfwn?u zAzz@F+iGl*9Nea30)byWuy$v=8R4%Gwd&1QsL%$QTsXvP!GV9A=Y zNV>wkp=4Fonbxm2YgAUEt87jT(G2JlkZ2i{Aja~AQ9R;_HXptU3YMA9n+O~?ctOmk zRCKTbtOMer&Qhd!Mir&v8kvXIR<5qS14N(QZ=CtgpAE?6V+FyFwQQr6we`xPwpMgh z%|)%asFn4OsIurO8j=Fw`;-D?ILKY;KYE$@T8qO{ClaM}vKgj@wNUJ}%G&(ZXy5^< zW>WP=zIk?}2b*DIg*N#a z`rS3?crUG`Sg#l>oFw;ln~nO^^UUlGcj{ygu4d9cdd}%N%{j%5HjW-Rr{G~iATyb( zif46{_j(-vu9~*#`RP9uO8u%CZkHClO?d|I93qMfh^5*{mAP3jxQI z)$?1lSL^Gu!0k)OdC#FbFiQtis zW2LfE+yw;_JHhFiV`!)Ht9O`3Xp#ZK=|a07c=OTiOuW4shCLe%V`~m4Z=`@u1Z!}k zd)pJnx)ux#7^P*=`PM>)thIH0;13j#*>45g3~JF@dK;RCCUPTJxb zR#VT~w7HLExy+flnQ|F^w)=9=KKGoWHUc2P^^2@yu8PQ^&aw!ulK!a-4_{_8bTcz6 zGZ)+!gyR}Q(b&ENkGxN4E~d(V^fCuLM&(#0v=TCa_cMh z>2bijr3b9{ZOhNG^{kgc()c}|@JYS$NWzk550C7UoD&Ek=WBYnzfawv&x#4_W^(FmB#r2(_5gFq zWWf(LN~)$1Dcf?U<9IlU*@*cVOkGuHRRdRNTQGg7a2!8K_QGIZ>GyqDcSLcU7Gw`y zATxtXvFXp?o>WI(U#62(1l_(}F#@Ri&ruuT(L1dhotJmGyw4h1+q!$IK3UI`9fSX$ zy>|hQEIZG`dbwQ33oYnLQ4$$hkE7-e(Eu(m-HirjuviSIf$5pSF3=b@8uM6+JKI1v zX21o|v)zpu%xY_AERjoErYJ_1%qZoQT#1uPQk#eD*kw^tRFW&&$YMzqJsel6!o(G- z!bqYk3S&K74w3IauY1mY_3Z~9GmE=B=zGuOKmYm9`#=Aqxt-&&&Fxz%-G);3s_YZrFdO!vWHhmt&Wt!(;A9Y^_Fr{FG8k=o7)8^uo}E- zR3BYOss+APwF*w*!&I$Xlt2Wkk_C<~&Af%8@Sj9G3QED}+YOtxn+r_NW7OHq*p-8mx6FqQo01z0hDGC)!YE;(xYu>%A zaa|_2-L}r-8XQf^TSW3ol-P&%cIxe+=l;{bFP=;$8}rFzCc{%c9~2dl15uNcaswIu z^VVA=YQP^2-v|rO7#PD{P{Qm&GRYa$219`^%rR}?KeV_Ghu1>BPU--d7tKvu2@~>Q z?Muo%9&!^8$j!)ApgMxvJ{1SKDMjH?Q1Y|}2cL&bhQuT(x$Jf>7MKl{?$ryUQJO`E zAS`)t(e&b2qxs0p3{Gvjf^oAdzJ>4~nTrGFdG5UNz4zXGgn!IVFg`)a&JkQt_* z_2osNzsHG8y9?b`&NYOVOTnsDYjdYs+pAS);n{NCF#{@2bS(4bSPKUgkk~E_z*uE` zjS)TpiTecESEdYD^F=6Rt{pxyJ2o<8b;{c|T~InURJ#uZlx?F2(^DQcjB(X&UpB<% z!m&n+)(Dym1vf#NrsJn|n60qnH8RE>u3g~C?FJann)j`5Duj7xOo|Z(O;2t&`fEws zkSev7rrWtGk^G$kI4y#cLjkK!@#3$T(TF;VE9iFgKFs*{ zb>nL`<7&a^QN(jZkC#8Z`nrvC7>q=arEW{-?I@Y%HIK<;R z7E6O(VNEI68e3R1T-$E&|NFO82JjRwTHOI!9SIa8)jf1cL7ETQcA_RAm*E?s9zrYE z17ncn@}vFw^*EBVe|GYmP~e0DClq+!P~aDj=AkvnR#AB0Q2eB#ClolL!25>+M>E0l zQvZot_8=7K#6CQ>|8k!OnB38uCyGAkf`uI~=2uH_U|II+glGNYJf^xp@DY+-{pb38 zD4b&2r(AIa)=2`7kPTDB{tffv%e|kA4Y>%(Aix2;%u*?64ReM`iJQjYHax&A{O@5@ zUbtf+g;$XT!Q9jaqQHO7WD5LmW{Lj{)8z*4Rhi+LtpZf$P<%FBP~ zTHjF7-ro)_mIy;f0;>d+Hi*Xl-qcy^726 z|0ju;b(q0{@ev9`5OMA0j#xTL++)}8)EYImr;Pu-u?BtIppsuDnC#V8U;Xu0U!@Z8 zhyLmZv3SQ{9VZgpR4H_VI6!;{6<1`#k`-vau~>e&IA5;SQhx?P0&mB3M`WZ18kK5Vr{XVf*q`QC6cm*%P8yXKzj2a#5Hxao zU*kXvOQWviiMC$2^o@KXnEXIXZRb1w7B(*WK!j-UPoBe5x^y;`03sxDjDbzb?3iJfUHP?BK=19 zCJY&alct3IVZ$oc=T+aK<_Yg&ht!n7VeDIff;N0s_7m?CG+~Ha1U4l`v~jn-9?y&e zWY$j1IOJf30j3!GYsNt+6O&kI-qg9px6tUM-vc(|a47oQu?zX3z?3frh8|oX1TnqO zGv0vCzDGJs-tW}5a;@%M;hhc&zUY;4wZ;QAb$vR$v5Q5*6m;=@CLJV>ZGZi|_Q9zGp17eJ67LtM=nWamQA9y6Y`XE45h(3-|+($w}(V6=+QQZ%j7TzE3) zs;TzznsdW;k0*Ug3=6sbb~a6USN@ar+?Z5`-LAzB$LLGknHUZvFq6^dm01goVGrn9 zexBR5DO_GCexJv>-tp=x;L3Kj^^<+oXr#QiI~(?Zj4j_36w<WcWMB>vZ|qP>+m$9vq06<9$CA%n zvb>%i0qtfi1@DP4L2x1MU0+LOq(C?}t!ZUfga3ACwvh}kJ|iWDyfz*a5I|P~L|vP2 z3^v5rnf*pG4k>XYyMjI2aBS98wOYv}w+Y}HseIh*IC2NWhJD5^U%%c(KBAr3K@8Hh zHw8IiNR+$tK+u`TBirSeor-}fEE3<15wE3dqw#t=)X zH)+RkcylK;U>G$V<^giVxwa0?P$TswcWdj_E+N$isji^4Ot^Ll_h8N6pu&-#zjEHA zXF|DTM)~8^3 zzf_bp9Pqf4m#}|?wQas|wagL=D|%YXkZ%WJglTk?+r!mS)BKR#VmxzTUXg%u6BKWD zPrlJn7sV_2YhWm-e1w5QLV}t+Pl4j`0Ygj*iFu=q;Y=V_Q{#$3`s&M z7OLI-eylnI-)m$M%Xna?O4~)wa?K<6Gx{yUG;>JCh#c{ZIU9JleeGe*R~?{BQ_UxK znh)7dbJWs&u=bjBhFIsxaGUIIiyboD`10CjTmAkTY6*82&Tnk=-jeUq^;b8h&Vz=~ z0S_HRjFu&8HPs8Ml~%2_xm`<1{pMTXsuyTym6__~A=}euM%c(1C#kaGj?17C8yqyg zOl$awL@p<=@%26(Y;EO3liTM*Gmim?#0jK+d4=okH4D??b=GuNk2 z7vwJMd(x-Rj-OjkpH5Gv3yX#M^y!beG3;*R!VZ*ohMqg9XK-+67~9U53tW}muhLG3 zj#u~|UTx@ed~0uP>(yr7IA#bfZBGtfiar;JT%Cb#=~CN+e!jW8)@;F8D)+GAQJ={f zHUmrb9;(-ReThW!7gY5yim_K#&OkIME(xWFLC^xC$GS0h5G;W5(%-nwTyGS} z{i8?SOo`E7DzD^H6^HyGJUb+OAAVXG^V`etJJ)v{iq))%6b%0jU14ebS0<&mYitRx zH`&WWFrb%UudpKfBwO+7mPlAt6V}6h^c^rs$ShKJs^QCUT6K*+ zJ_(?xJ9{Z6UOD7>iOqvVMS%*D?uLLh2W(dX_>%^#dF%O@^~FDsd6BIWtTej>;@uE+ zOoQ%ueBLx*Mb&YNSFFS?i*{UP*VqC;TqVFafGz4CuN^_Jvm6=9!)bp5ZFm(FD+wf* zL9HvOu!rvzLi=-oMUe2H$iB+pyAjiFmN4k%zhzk%?D~n(hYvaq?Zm zOM$4yFVezY$#N(2#t_MIaHFQErhw=K1)tOR+UIxW@in!u*rmytUU zfP4_F@bNIuUJ^ef^ik$yyMdnQsVe4(YJDC4 zSM?k;xr+Xlq0akBRLAHhqO!c^M1loi7k4ORsQ-Qvy>tbgmP5GC$tZ{HHQt>Iz}thJ zr=MurQ5Vj0+?K^$hWQQup;uF73F{>gvltf~_2M#za8-?oYXCOKZVL?s0DQ_*>!{-y_`lSc9o{FW#>VM7i7kgNkE3Jk z`q@HpEC^arIekGQcJ}O9?#v#JW$4s>0nE1C@XR%GK`ei6r~V;5jrvpH_0!%9>6~%r zAH15YgY-s=WSqVF=-Vv(Wio@h_~$2LvR8s>`Olo zmEBhT*1gL5?(X(1=q|}Co#ezqwUhF4u09$+&VgjE!&03?yNHT%M*!KrMG6R;& z!~KCIA|-DtxZ1V#78BkdM{~I`MKbygAR9T|3L}@K*0*~i7pPSnz(Wo7lludA52_+@ z+TW^>w;8=izH$K6j*q0TgZ@dZ4hnO$zWy1v-^ER5^-uVk;%0Y_O|uf=xVDeerr&<~ zos(hCXGLpN@P60DtaviaJ6wwd)gy*^XRA^V^iO4i*9m)R4PD9px1)I?7TRqr%zWwp z(wkT-?QMxG3x_N33SFegwRGqk{DJLpdY0QfB31nx-xy+Bo3Gb~PM<~y{qsMiZ+ycO zh!FSD08Zlprx|~LON5b9D3<2t=EE9mRCcQM?KS$|A`xqEy(SH*Gs|8dx$pa2jgh6r zYJC^B3-7>I3BOo^FF&{TzMX{Q-b~RQID`eA2^`;cj8)9SO zjbzt514E@yG1$bVr6l?)HD0t`QmD=`G;@QRvtILlYUu4q#gdj-`HN(*<%lI3;!VNTR;rin)mYpQlhCBbD(cF3tSh-{JCer zIaxs3E+9z2X?(JPL~I81_Qqai zP@A9l5@LR-u1Q0xD^fuBA_TsA6wo#49w2tAWJtSM+RWxO7IrRa8_?FEuFmmTZe9%h z(J_r0M{P0^Mz=R!g_wDy0Tv@V>_qXsJPr zl(i~rTlkAZ?T&q@{d~uVTJ97l@uzB_GR9ALQkBf}Gd?{n9i6yGz!&Aj{H#9+dx-P2 zhj0g#@^t|+xFrJWv^Ybvx88~>-h)lZr#J`8!#Ur^h*P>cuLC1}a?k0&j1j2vS_yOK zZNO$^a0U*WBy#<13PV^%E;<+1>$^J{m^2-BMo4&<|J5&2mX{?)nx+se5ms|<(080% zb^=1c8Atv=HV)SvWAIO7Tz_!IJ4aj&@(eE^60WCJ5~Y~eS75`Nw{;!%#X$N|dMz_0?>>12SuZI2^5XT%wx?Z;a`2dK**RXuIHvPaj{ zu6YNt&x!x|AN-)V5|<)pjZaT%N>0p1ix)c;#j`w_-o3MYyWWGDOistxU+d}pPlc}yvE>aO=@UF@VIH%n6nlPEyo0@4ws!V<2B^NU{5i!>al%m`JGvQPzSrIl>6 z9>>!#>JlT>bWkcWlU&%7Hu+!|XQAjy-=i=&)%2XeEMktVWx{+8bikkuBdh_YrHvad zj57-xI+9SEJ6OH8YdbAiSQG*(ss96&EiErD&gJJ{_N;nS2CGbBE?l8%VkrwaC3rgJ zGCVby(xGPvi}Yv~DoqcXNm{K%sOPU%O`~0*{&?=Waryp~5f=SA7!iFcFzz3DLsg;P z@PO~{4hV}C^jPW42~|9rX_HcWE`0M8sWUfaFkk|?x^114C8}KRinJWd*g5k)zQ^u! z-(wGy@3FPD#0Q}zRf3VsC3qyee@DE_ADPt?YDSvxBi`(GBuC&KUUJ%Nb8E`rWgK*E z$sXt!kz|Z&%&X4p>8WM=x=WgdRmnJ>%6Xvq1~=W+sF4+|TVSHyzFljihUQDGTw1ui z3fZ_^#YHFm)>yHSFP)j<89W{0tg-W# z2+Cu!RJ}btr{)bXcpR{HoJnWO zIqRHrrjgP$rf6*SEsFTUhSQ7_93tAj5ChYU0cetz$CKuAE-WbjX!54u7*b9E zn8zj=^N`vMiR}@61tDc37y?}Y;23+Mv&?W}phy%*3|t5-Rn~}-pcXLTHO9ss%GxtQ z2E_4WvO-^x<9u=}j3kuAtwnP%3i@#9~ z-Z?!L${{^L($DHWoT4Jc4wto1br0wj*9{tWQ$60>&i}iRk5WzNr|D6|T5M z%M^ne|yp% z%ie}&_`%4#^W5aSPQU52xHDZ0?6RH186lY`+yV%VM4h$zSH8my2|MJ-%i^;JC(G@3^UK9ciwpDRlM!o<$J<&aGcKojywk zH}N3A4ATjWbUKXZAcJ{0`HFv-rR=5CVD`x3gZZ2v<5OLBj}i>wq>BD?bT*Ia`d!H~ z*+Pe=5ShM0?99D^&PLS8NHIyPG&GdF3$@dt7nq`7NM!^B8NJKJ0rUK$gfq~D$<#*y zW>XK=YN|1dfj$0+i#2c$2W;rK@Jrh)!BkJ28l4$1wYv~|x=LDJYo|{a0%LuuUo{e* zfqtH6M4sy(I}pq)!48zHy>yyBi7O~$IAfZ^6!Q-$5a&r{=eZy*3FKtqxtTIJiZ09% zy9Dp;(K&;?2pjfqD84G!c7eFV;2^l?=$nIsgVn(`Sm4~bIpa&msag~+i?yxohC{JfpRDEwY~9o5xr6<}nr>UlE%zNk<9iv*sq0_NAR{+!7zKX3~&3!{Fn|opyY_&r=B! zK~zkiOG%PhfLR1=>A2qbNHSPoNNpgVRSP+tErXNR*7=4dllh+BMP$3u0~08=Fm{!w zx_R^ja^hUv=|-=st&72;b6H=?7#bsMXgc`wUJk66kL?rI)z=HwZ2|-WQKZ|nJ?Rnu5-rOUXG}6!Cu(KtC79+#3`JH(`P?mJ>ah5E+Y>c z+8H#1WZd_f=!`L2VxEeQ~!+TMQ=~Tw|AXGQLHz0k=L&R}~Rg`Hy{hNM zPhj@8^GRT?ZUWm3uzU9O5S-d7H+XumlBkc9*(;cyorWrU9_8=J?A1B-PiC*qX=dlJ zM+&%uPuU^;pS=Y97CrxFaPV8t+2xsEylgWd#`{9CSSV3CyPEQguRsb4nUCl1N>)il z-1{QE89Hb6jg4ll)l6-)q&Ox{Z{jeBm!*7p{t6pr>NF7yvnEJ%S}p`U@OnT_A&67hxyzwzAQAn)qNA8uKg zn~5<3du0+Bpz!(~^u*-g;CBXn0vE0_Tw-&lLf$&1To2p5dlx#biW4j^?%9Rhuroli z3TJV5K9JHzb-d}w&j;zXkBfwfTu45d2&r?qNr(kBpCUI9Ti^XTxb0v*w;j`lK#b(v zfy=kMQw90b6I^)<+#WKKBed_yPL9&UKhL)6_j!#36I?Rr3it(Q?s+m6?B&e4EG>%} zX7I#Z2A%tMK5@!Oad~lh&Sb=eFy36wToUq@{R5_o4(1}drBXVec0IhxKg27QJpYFZ zr1$p_ijY_q!?6@d5u=jOwVI8hLfDnWnf2-BOdG;TVV!OK@H^YJ$F+YPZsQpuO0Hs6 zWo=!vkX;1;FnuxSC@UbWyv#(p<)x*CvY~ktk-Nw2T@_vxO5g#g$EZqBi5ACt+7QDD zT#S_SAm;aw3B))!TG3~#ORzm8hN5)4sh8*1ek;Lp2N_I%QCd6mTp@eJnQ_-VZ6@SfCfqdJ z$%G)E6oh6+D!1M4GCM>{+!E;~fyg*A+cpt|=ywlUT`RG4kAEam<5Q~MiNpoHKMoew zm^LH;PA868{Fp97bjHuNBT zQ^b=nI`pg%V{{mT7j0KqGAHA-vA~0M2I??!ph<&09vg7$YI$qjH<>AyMn=F~sf!?b z8=C0?(n}-%m45mUeZ+t+i}}amcTAT`FH~~ZRft=NRigR9>+PkbE&VVZF8!g@b+ufS z>pOBe4GV%Yy!l{f{Z6C4Q{QdQ7WuYGN8R1IUAxsJSKG9!(!pEx_1CdoSB3pJdORmWZKz&QE3%w6Jn3k z@KT3{ZVcfpkiS|`p6vLqbP8!}^_a&>y`f!yZJ}_T-Q)6C za;jG*%Q6rVgJr40Mc8~x{4@Q$_C!B?hZgk*T5_4;(VL_nXX$$Piz-oN^SCesf;gd&a(!!?6m2{(A&K|u*CgtouUUdzc7h>wI2NR=@ReMb!Y}c>PmGElj!5OwY+{p2v zoEYFQyScjtTk?};+ot`VW?KH%Qp>~acVOzGakSlx9i5K9^7_u8pK~0lZ7XY zpX##|?BJ70|G*#m0OJJX=ROHmhqe(<2IM`wlwA1`J4mz)HgQ>gcbXpEJC{rBldib$JRjO6QIi+_%E`quRm%BI#wKt9YbI4QE9K`4J_6EuKAfAs^0K;&R4IjV8--f< z>My;h(EM+L;ppJ@hcwhBYN9x0n9)ElxI$h;%v5R(=B#5hroB;a&sQg-s0Dub#kP8c zzwmnk{-*D|&4t`l{yM^iJc23uv2n0oVCNN8!;J?XnhMWhqD;QTFYl+I!A2w0&_vT? zNpQ6lgSaIX_zgZajZ`tbd(bSyAn$3(@}MiG4HL<(CLo>3X1<0_K+=c{U)*9%i;AqB zI6=V2EUL`j0M9n*rPgWdflsVa}x3}%u-|H)PZcS_UPy|OvH|k4h`Y| zVJ9G$j)mRR006>Rt_G?=Nr)EsGpdy4PE8bavAO+bQrVMUEj+)~syPK5TixKSvuY*S zv0@7j^6(&GQe$QY5&)~KOEbdrMSe5Cc=MIQOyLc-?K3EyOBn%OaK&c8MZ!*_AZZ2K~#gMBi$}0fmXlbEO_Zg-W8Z$#Y zrRh8lT|C&Ba95C#;N616TUbS+=1Y4?6U&)e$)0bsR!Ku^dJXzCy+tnp;hefBOiAu$ zkdj=^U=_*p1tX_ab043>zFCQRWrn%Sd3~eVf=eo``Ku8(b700~YMlQUNNk z^M%q)_HyASt^-)PaHE8tYp2apkLK~P9vEcx3u|35UtTTc7p1;z*8A+SHkvq zSF*e+m04uI?}7eyEbl~SB6ve0oo_Sfxk1fN<@?m${)}Oxn-=mvSW>5zj4GWuz=C^E zc#b-+WpLxM;LNiIKfNrpS)$b0hV#LE=OD4%xoO0=Fi_v|IY_L*dNK5|W6cBEi|)CO zSL2Wo@pe?>bk4V2@bQx`uH@&-3(IgkW{(q?7>0%E7LB9LFXLyOzTDB|z2k85h_ghz zw2=ooB$C^U;MgpjW1I_(op7d|v!SuzJ2^STu3jaj1lmMHIgYK(R-_0W)qth=wNh~5 zM~|A5$vRoO_wpbpR@D(H5-1h)$#)V<$pyEf>}OMDpClp_SmnhGk;I<;4X#4KEw6SS z)up${#+FVWz*{BP?G@Z(q?B_Rw;@X8zDHB_eL^8}d7 z7z_+K-fim*ruV3>Btx;9kZ`CgHk$qrJ?YIV$#yEc^4txL)#Z&GIuQYiE%eFdJh}Yn z2+BL<69Jv^i-6`b#jSgL`a7bM(mcIhN@r~+cb*JW3 zH|KV0TWkY7h@Ucf5CDYqMa5#U+0YCg?qH-78{6C7=l4#1{p*QSUzfX~ue;A5;1T}Y zRaJm&@}a_-F#Ah^nW#yH5D>L$xGWE|ZZ;PMOQ{)I06)d0L@<%2ipujw2)86-a7zNm zxoM?kA_Z@5kaSPihiB-&HG z14*gqK}v#vkLA)5heCQ}OM`3-kqTIM&>rzJzWFp2qha-qS4P2-HTb9t9SGMS8N%qX zv?%L!jU8wpD2d-Cgep>?NS|U`E@SXgt*F})D1SKy6-i;(Fc zomNMMWeE%K0#s0zj&KvTfGxtSC3_d(-YiUemaejy>ttSt7>+YfBRGGpaCKvqot=U6;j56OoRK3< z1mz0(l|o{lQNmo|>MAC_#H0N`2bjcu;rj^&@-03)guFPvY6sat!dg2lybDmFS*Ys@-1Q4dJw7&F**nIR z6d(<~S?)7)Xa*JX_1>((Han05n3}E+_}J7d_^?w9{JP4m|3z}g3iY)XZoWMSfov!n zC|yg_sTCOuUYv5X@V`E}f+)t`&)30QQhm24%6 z4}~i#W9G%#jZP}|-VtfCsr%T9!t$HL$X)HiFX@Xf3GxJ~P87hKmUw{m($ipH`RegF z)3XmPr&=tyC4S_pJ!Kp06?sNy5LDaX=7lp3Bn`B45Ut&k#pypw&OZ_#$Wj6$!v9JF z4>DBW;Dx<#@xKt&ume+m(I*z$od*-Q&KPMhIjFBmLo~JYbqK$%#Wjd08!8;+&!b(o zkkXF7UfA>8aR~S4;Cc=*9EP}ozPE^0Xsh9p%NqO^*_(s!TMZvNGwXMuz+e zp9qoPx{m4Mz&@7A8em}aFBK>F`kd4f7ncQax>%;lMq)>B&uiL3@z&Gu0y+` z^6mi*KBycLE1z6kC>L&FqnckT+~TqUDctj6vm2FwHpJ0MhAyO2Lml`h^K5XAWM5M= zCcA#^7)XNpVCK~iaX(|e-2ejGZ5sk6bG849F|8Ub$CC|%-EI5dYr&=s6`Uk_aoN3s zHVhwX){G^|kl)l>b8C-nq_x+zRzP<-_G`bvObz6V;|4=pFP}(B8!WCB7$&U1V2U%D z-nbp$_DFC`Uf*fea8Irdj5u=-*`{A^c5C`&`>vtj0qIB60!rqY>%x2MGs1YEL<1SF zs7zPDb5Q6}ctDaDUZ|=&#Oc;#S;P!!cNa5ZB4lN)@Wlzr$U;UrC zc^?Z9D{nJv%h~>fl@d(9J}pLn6tr!6FJPgIzb~3F=DENnXU|=6a;XP=i)}70dulBq zaYaU6N7o^?h;@Zt5oFv$hWagKYa`kjD)KXm{sZ{FScWX{6_0QjZ_ua4I_m|&&_rJjFoCDQ?t>*tZ%&yKC=uW@cKw#{I$nfsF zYg;=_=O?xo|08-3Lcqme308s@#aJ;rNFEi;VY$djL@9u9<)3dzytm(kec?oLb@6%u zPjSI%4lmCYP$4&a)1bk-?Pw6EYLU2K4X$ZNRoZ%axGbtv#M@_h<$|k*R;08fk-@9H zT0Cjn(Ek0{x9!6IeqrBk^8GlKDpVi$vFMv#j>#B2X%U+C`CNNUT7)J-bBO545y}?c z!-a8gXkEa5ArtCQ49>)G`ms{CxMl;{f7QDT7@Mi2agPk=UvgIr-G}Dxc5039g}3Et zFUu~MmRGOB@(intzv&j{LqG=IpKhld+%h{i~X>>4zyt1!|zyW85xOl{R> z+JtX=(<@aT2`CU)yG*xd20UO8A`$5(Z@=MrsAz~`w4oN4q|IMm$}>f0e@(lopa&u2 z65QTdLkcpkdC}r;6aQb6{cZ<_J6Cls+a79ZwKxy;M(>rAVhiGm36@fI-X2PH?b6zn zsO-itWou{Y0gDREi*h@#hgNU1#PfpEmSE?EakDLZs;-}sww2+k<;aTft*uSiTHpx^ z>1kJ6?>@>Sl0sEu{q?(bsMSUSsqZ#+IEGTLx9=rYYbgIZ=}k(|9U^GdGEEjL=;^w) zLBIe{Erq#L(vny1>{-$aZrTlH-0sS{!0g5?-dOyG5H?zd)zsWk4D>p*#uXGcNWp|m z)oAUL0Sb7jV5L%t%)rww6eF5o%L}}mv~EdSBEWSfuL|=5H}J85&dmHSLFV9;ffw8= zRzB<#M)Iy|u4)ZaSi*z?S7g!kWTe*Oeo-`$MyL10`T@<%JcWB`(t7c(s;1EtVIy*A z2#kxJ`VLJ8Ge(g2dq<8s@oOcuqxdk2jDNIm7PRw)opK@Z69abfF3i@19y1ulwcCx& z)`MGoSVKzlks40kD2Q%6q8nz}Loax9T3tG4+-w>*D=>q)UaxG`n(H;L&3Jw+r}}l^ z6ohD{Q5-dY#D}7_5V*=cDIGLu;iD%oDnVCO&~;E)tlG6S?#P}5#hApS6|C2a5Pq`+ zu@qpW>LtwtJ|&o(ap9)feWmg$jFu>))b6cfpX69@Z7!ZdmDMitSG;}Zf%|szu6oBW z;=JFVc_2eXbdNv?jT+JT6i4GGeYoX&BFI1lA$#+?l;@>C|JQaGG`O(+T{{%C>wAz< zX|nSA4yD;v)%0a?H!*OwibX2vc(U}+V| zD9qYbOr<+^6~yXXyVcuPLUo5uHYPn%4?7i?k^)wz+l`*O1?_2$qFa!eaJiAPk9s-d z1n)cQF)|(H^u=@(nUeBYkMdfV@_b`!1Qo`k#GsXJc~t~+#!=l*u7kC_$@qrT`8j&DR`u190MJA<#NWU)h}OJ{S!#KUR+oy!*CAFcDyOg{n3$%>zb*! zaqV`48~5NQKBS=!dZ$3+Q{}24n4(Ys{m{R8kqoc&6_Ce)E<7XaCKM0*Cc@Imz1o+D zD_2@PRK&^XiYGm#Yh~`)NKw@&J^hoo-1{3_yERb;|7&1Esf*b1Lbd)6iuZ12+SVi z@v47J8kZDa{y;k$+%RtB*I+?Mv~6&QGg5vzcG6$ApZF!%`OL4sYkuf=JG9Gk;%3vO ziWg5dFDGZxxM=Y+1!~NJZe_K;3mqeJKgN}uV4BnI$8x49yIcW`oxf-(1$j7Vnx1x& z)51LgxGC^+p2;YsOd4lVX*)lR9cP4PodXaLMB8X~bb^cn=X*ri zaZYVG9bmakWK)}PgU=k- zkErbt{Hy4UOpEO|vyOWF$%d0i}67G7qL3v)11n~%bYasGQ(&2pXqFthr2Ij3Icu^om_STLwt?gkztw_gM9~soreiNx{eK- zK_sg=Y+AsaftoJRlny%h%vVugfXW{XQo=GLBWM-fSiJRRojb$PEZ)vJS13crx;Qqf zT2e*p2o+#;3vX&GQc(omG5}i>mk3f&GUQeT89iTRQiy3xRa#$!3b3&BrnVycSp^rc ziHAW35o`n)uNo0OhD{*8oW1~+KNzHhWkxFM1`?bS1~jR!R9`?O8bYm=084b-WIk9D^xqWM-Z>|t zKXu)k{JlhWWagO*jD!c)CDme?bqiP6xFa8kJYn&)U z12WqisiD&&<0BhTJ&1Td&&W&S=^^b+)^NhQmSjoEWw2QY<|&ijW1L=b*dy+TK9L8W zTz^%ji3?9AC$Myyqyp3-lQpWlJ5?@QuES(x@7uOZ<#5XM_o^BF=^?5xDfgcXJ2sb(<;p36gGhVLP83=86Ev zh~U9icKBW{luCt*2LaoMnnX{Ut^?yAx6a|#t-Ibi6 zapB~8c@MA;r+d0>7+-dOAw9_VG92(1B1#dRtIUXZqk5d`a7wlj$Oj8Sf)k@<1Va-G zD|G}wvUmmuz36KLY6=^&f9K-gih+Op90{Xz<5e5ei(7J#TX;DzybTal0XC>A9fXYO zBq7L`{G@T;8h9gU`|wkI@Y&s+O(-eXrZO-|T3PQlXKlNFuXd}tSy_j+)8=|}HZufx z0ihUf+>D*HWjDm#xsXdmT=+3AKnk9unA{ou7YQaw^<88TF+4(M&2fczjBBgDQ~qme z*Pl3fVlG32n*Vwl4V_i_n1fZrp#aB_R(#g$*v*rF!njOU9#YfN9qbxiLMivDYb<#? zDZOoK`$x&OVX(9FGng6aAGRuV!-M~Ci=RqzHko{p0(caDb*xAqUAg0j{1aCpGzhg- zVCy0LQ~0NwR5ff^ViB%e7+E!Bw6op)4G9Q&h=6x^;kqWjxTwr;k=yj234Z=gU@*L- zectxxr+kgocbi&;wAtKIy8CX}106Q&+E36vEG;~+Cp>yCJshu2V|uEG8r8G4sA3PLwtcEc_qZB4 zPx?05!s&QM?iU5k$+U;2cyOc(n;cL_-mUe(?gA5g3u1`&*+Q7`FnNr2;A3re;NIQ$ z{{H^Mq%+j(-nm_|dgIS`h!NZTGyY>i__ok5n|5%1m69iZm6DEqeF>(F=e`eHc#{`L z9H6*9YmUgT(v%_0C2a>ND`>N;$~s%efb;wv;XMb zUl%bgJHc<;pYOT}MTFkyH_7Vl8 z*7W1JdB2VPs%TG+fE2Ni>nmA+dlbB=II~Rz2}1vRYJNhiAWGS^{%_xXH#I~yq=>U+ zulUBzWiKoKY#W|h_V<7P_uC|iV!O3nc_l+;O)ywq;0rM4wa5^P=V@joU&oA;%p3YK zlDl7BfinxRv7=iZ08esE=tc3G%q#}uh~pHT*u~KXzWl)_n>XL!3GoMzDJ?J8jjsGGkDvd*85>f& z>|hQ)2&^uopbo1_6OmPN>ll{=9%8m50TDQm1ilu34m1vJ$U|uH^VG(wI=aQ3(+`2Z z?mH?zl3MeUJEz7w8g8 za>EbpE(UX#o^eb!TAq8NUXPRU?~&Z=2vFl#V8my6_Zoz+Tx~CcJn1!=d2V?J8bnITQ)LCb!b-(UU&BFYN zPQdRQImT=)7Rm+XtW#cZHadcYYw@90`bI4P*U-`@W$ACG8@1gIu%4o_?&EqJ`8p}@ zER|P%yq^bMp?|TfT*oC7lcE&s_3gXZ)79^`HtRdLcAGT_6b>I3Bv0^&PXU^7%<+4% z5H$bP?{8LN2pFb@mB_|94B!nIFsHe~wuURGO(Y-MO>Pr>>FviPt#H) zS0h@HYSTXR4QKswG1nH_8tOe+Y*tcF{9^M;{PB0NDK8!@_ydOixGXmRb6=hVCgyPg ze}oGT;|mTXF~j!Ye9-}dYGJd^bm7@DX}Jql`63t5vugcoiw>0U<(U90w1REm4nWm1s_(@$*l~;llh-a7F>!U)LMMDGHZwduELU)ELbf|+m&Xk)*yc% zT2U#`h?0`_hHfi2m_$0Re&ax4rZS-0$hjUcW~6N8aAQXS7LU#+y@_m#NLudvP|<{O zpJRtGNxciK`avP734?P(=Z&cFIEdza1&WcRgVes)p@(_;8T7$z(wtAKejHp+pVyzW zehC?QCR6HV<%Ok!0}Dthu^)qJ;K0v;FnPxA)*D!K z0NC2qC?+&iP9aXP(;8N68rnfNb|3JkMwuVb0^7hhlY!i?POSzHI-f)~N4#7%OrnB)36`Vk1Z=qLo~Hwa@LFCuw0zc^ILmnV3O!u8t} zT2g2sqO*SL)3htL`-1=W((Vgg7(6ZHOJ}CY0~whz#s6t#&orGL(bi4VX+*8D{UMA7 zyquCIPmNqM#Raj^lYGSyaSgM_?%%03YV3wb(4_X~O z;}mYdd&f#jMnLXy(-%gmiA~8LER^(%pW*%eDYbmkI!bHj^(%!^fiHE53-}awX#7Vk z`N}Q;f@Gvv8TE&u_>cS=gu8yi38Bo)Mr5=Al`o3YK9WrS{1HB?X5H1-q=O=#|5w1K z>eF5V)!u)k$(g>9&gBX@GF5paoyn!0m+60h;EkuCg{;ynr(Z>q(epL+%~i`pE8om$&OI@U?L@| zNbsm{!T85mdvF>{A94eoA%~+Fw5++8b#7f2bF|Rp_Sc7Qmb|3UrMdO4_;kQ!eaaSb z*@gKsgW7syqqQko)&*gcE~KuPmP>_&%SF2(0x0{FnzHTcn%6DQHh$~m>52mABf7ot z64n>&WU<&)>8^S=S^c+VVm*FLHdU<|`WMY`a% z;xpz#7BGME2{uPIee9Jft(M8){&nOCIH>L!Yu)xwAHjY2A2eDcb}Nbn>MgxK9C)jS zwgcZHv|qCmiKo9wI~pzxqS`-jKIW^wpu@|Bo4MRdp`0dxSL_0oi`$R zL$)HUr*Vu6EAY@P%*>!m5>I{CPlHQq@8E+)i!u|~ALmK>c!abhj*`ud#wDlV@sE*9w8tIA%hyoTGT%w@=a zI^TZh%`HmurJFJ>4_`qz+uCVzKt%we%t%Hl-ytAWkpB3EYLkj_5tv^tu9Qo8+2kOif@amm6jJ5 z=koI}Gsvg$c&nG3^WUW_mT!fwMSYb_uce3;Y;kPU6;&%p{lYvF%VYzecKODs+F_7e zDsIT3>sBSOPtta9Se{xNmU6~vv`s6$ri>}Qi1+aZmnFDdT3)?M#MW1_q2?`y zCKhJ$f(at)aH!V&N(DtqU}llZYi4lPhnJ7|VSPrfU0#SFT-P}|>J*|BjYW_lz;gk2 zr-CoAU4sAxG2igOG`3*-O78F3x8Bm+-%RG?v=Ctf;_`nD)*ye4=7(0%gLDqf%hZ>q zoXL4xClHKYmoKU^xV&MVRPlyMt^x0?QQ4{1w^L9H5!oqTC#FF6%YCEpX#C@VaPd`z zt6vX47gGmr)w~m*aX);0p?rmHVxA}6t(2PEGsAvMVSA$)G3{=;Q)*^dP0o8NZgF90 z0o))H6qfKpX{7)rk(|jPbMJ>wrgTZP%uX5{8V*2oQp3O*2jB}0t&CnRsA_!K@YZpm z2vKv?1vOsF;3C~#W82-6ZnRup>O`sz#Ui%xox#E7($e4(R)po!Ab!~xUcdF+;NW)# z>vf+p4nRl=pgLU)1!d2u?1O&^Nb->Ywa}NeXX%0)`n=ADEGRe-`rvm8iz|ho=<5P^ zRk$IYW;E1rv81)>GJ?v@$b3Nz-YA`DCp`jJ0apcgJ@! zlFOu49-#*!qEu(%hRbQECPaV~9JzK0IFEb_*iJ^QSZYU}nPGe$@3kcVQt2t_f+`7! zT1&=sD0eD@b(tRwXfeK8T3E`LZZa^q!GNP+_^xL2SMnvu{-;UVQBpt-O~^_K5&U!t zOFNE+YA0D42M2F$d~ZOkez1*<15kyL)GZo|e{tb`q&sgO(GQFDkd9;{xQG5Oj_`hV zls?p_Oy3W2c^W+-ql*sWCrleGI@PoDbBi>bj#sC6o|qN~&yPBkP9bZedx_cmjqVZM za0VmjST`I)%RMO#7r=U?ZYg$hx;fi%DBT=gOfAu!!r(g{>rOHL1dZln-zoeYGj;VA zV~W3bsO$dtV?I;RfKEUJQ!VUW&Fp?ASqJTPxcjt&Z?CQ>XmF~I^)!gZJ}w2-1z*`~ z$~e~Y)AK6TbEh`=RZmKj^ft;v`60(_<9$f`H@eS1xC2@AuF2(6`22RUYJHcB3h-g} z$yK;agd{arO9v0*T7G_Yb!o=VmD*wrPZlcyYn6OST$rC5y!#aU=}&lWy`nIL1XZg6 z4FI}^l#G!f_ero;MXW|7cJGG!-bw`s11-##w~3Qt-MLM|og;MR&yV0abG!%d(VsOA zY;!-EHuyJ^6+53_!Fm7>plN=)Tq@)jhtCHF%FFWPTW_VX7Kq2E2lgZUW?WsR>uYiq zu%NZMd{O)|U)_*%hqZI_S6+_Pz7{v^9p2OndyuLE_WeI=?yg}ZkQoWw010HE2JS)R ziK>iCaa&%Y6RO%dO^BU9L63;vHs0ywap6Jn?b;b^!1QwB-JQnTjOl%Y;B@-92ZzFg z3RrD1ta@W*^tef!Oo#Hc(iJW!X)ivIo}|lUkBlP{Dib!LylM_k-nCZl-A;XCco6$oR~ES`QRaKhmYYLU`|^xcj}4_GRS(WPxySR=Bqw4QYX`X4uWU!^jBk7 zcd-M|((Ob8SDh4SDdN- zmg$o*Lv-6B@q7NsIOmo;-p?B6L3T`Vk}*bg|1`pb=Hw?>sX9n8I&fW*+!WuQGeXJP zK9~FNmJW2Y{=PJ?Qz~38+_;LN5p4U1B05<1-qLHOVM!=>EYx6Nz^j_izYo^D&c6tK zqD?t?sL-k59R)mKTidnqfn%znPl}4s_LL6Y#?T);Han-v)~>dT27?ns$D_7L0aK){ z%GNDheeT=_Zo{yI5pdK$6#EWOqD2aO$%`#LQ0ZQldjJ#uBFsZDTzf+x{O)4D*oAEO zi<-9uz47j3yDxayjVyDvjYz5D3wFVPbh8|0v8q&)ScWKYB=5Didz%zH%CdFELMpCr z+5&{vCk?R#c_A+CSD<%{ILgXkD(rF1Ads3oJUbPJBcD<6ygfSlwtRTN2M4KV#Hd`i5`RD%D%NJ8-?Wz1eEjs$^wciGpx_8TU(=VBvwb z9>=E8;z)BJ3wD8ixr4h6NSkcHN5<*1<8Q8~PlH{4?lNqZ;18U38PhbDQ zWX(z;3Swi($-v|Rjh{?rG6P*O;boG4yXI63qX@JY>EM~9XBtKnq{SbXRTpYd0}OT2 zUeL_MTyB~RDnL|$hbQz%(1tqHxFpFanTnC^4g~||KU|1q^DkRP=xw1espiQp!)S_3f@Wtsi0zrD4|1$mGIf>k)V`~V5`T;R(uy}_rI2@3!jdxINR<_45>;tz{d-%Y6t zgu&kvfkR83GW`rHh9GC$~W0pY^MGZ{z1dja09P_V%42L)(=c>Q+j$02fb@!oA- zB}g!CBb}<=Grs4PH{^qVpLO_z=Z>OPMXLdaj&lj(n2RdPbhF$ z6yS?ayd@+IrJG?9vBD=~rRqG<`F=i~7k`rDgaTbr;AB9?8@Rc6$^5DE{-8q*`GG?% z%_{7I^>w5leE0t_@$}P~%nRxyfRAB*^r3^t2NSnbSC~FcFmamD$C|O;4m=!A=z#}k z8&#Zfw!sNa9A-#=LLFvY-1*yKqAXENUCJ*kDs)-n-fi$9%7y$z3ZmBw`HS|+@S`em zW{W&*S0vG4`$?Srz{>D(LYJtUiHqhtWx;eW`;6tp>{ z#iRkQ8YJ)B;-vy0`d@<~u=-;Os+|Mc{%RK0;)%tNQNA$0+7C#oCL9G+=ixrC5E00r zmTIB`%~XHIGpha)%FhkFsw|BI_X#g|!LLDLO9A!bLvSDV@5qOs^ae;~*~wp^>+R3= zGAKL>cHu9OdnF@9 zn6sE9i$?l7Y-Lz6UtTTc7nKDsd}|w*Jtq>tIq31gqMqTU8)X}~uvXUF84Qsy;R+aL zd^fjhFQ5fK@!&jM@7}4+Ht$sG4?a%s<$SgF+BW>vH|V?4ptuKB5%+r?JoW9ht@;}H z2zM#~TSHmfbpx`7SMQ#&1y!iDyFXcyuX$nwS2EnRSX!;0&2si>30mc8< zbXl?lZd$v8iUlS0R#p=*K2n_c0ksv~iK;K!f+{m#5tVs^s&J>~HkM1dAS|sgFUs$$ z_K8G@z#(MWf@L~L#AI}|uriasS_qQj@C$Eb z4dD&B03Ud#AQPU;u-+a)cS&E{_Pc7zp8F~HuDnsNf6N2%qHuSrdcLR6bF29sb(n0p zpvviy@sW*Ojzv75XABqdr-xuUVl>ODl?P4k(U^a&C0SCs%Qzot)Pjtgdfie;V;Mf1 z8Dd`&3{NJGO7g2RP23`N`R9{WX*h#yVNft@RCjl(WHV=h)*v80`5+0)v)1g9HAE=vt!@TeU7y#bOsc+F#bHSs4;Y)qS(^?e;@J>CUe^xr zd+*6N4Tlq1WRw|H{umjv*@=m>+4RKJxyjtwvyubkNPo*u9K$#=v_b4Jj$JivbC$OM7||y83}wptrH&;Ekb3nA;s~ zBVI?7V}YXpnL1g#5!${AqN*H+tm?uG!B%*;8BNE2l)ZO-+)sD7}W`|?U+0}Ih{*SoSn{|oklBWX|l7hi3Mm3In^Ae$PwKl z3I$-`V4AWU6RjBo`GRC5tMuN@%n`RA~uy zQVxif6JPEw7vcQrxxxav0Q1>+{q;x&$;kjgdmq{W`Mcb8@Zg|-fSCOy(i3)HCRKl{ zf6s^Fby9y$IgV&T#nb7)`EkBL`IZ+6CLT^lGH|G}k;FJzU9|Uhx6dBT>T=YBr$0@N z4%IoJhrXf1;td+RCFHn`SN=Dt??-h0E*5)hM}%$BV5LOFaNk_l=(L$ZrMqyzex(5S zwAg3Llib5P<}B(uU=U4??$1CLV-tT1MFIgR2JC$sAG{V0WF5(da1!?-}%2vKzj zZA?|kpgfXj@<+CxUE>34)c4hRI-X4+dkpmp)$&FUR zHTpfNpNxN(;>OIZ2BL`6!w)Y;B0c3F-SizgcUXPLSXXpaj49^Hnn{8h$OuEr9%Q2m z`ik=2k7En_F{5W4)U5Ts?Dlf#My!!Mg+YF6V4GvW?4>p>%~S_FQu=Wud7MUAVqa2P z%s*W>!N~|C(uMVMU!Uz{xQI4^&FP~!?90L*mkov@be|94_VR&N7K?SCOX0K*>q6!f zs2YWSBf7=0#M-EbCZiE{z#E~1p59@oVV^7o1u_YHWb)apOT)x~N5L$e+9Rb)cuXmo zmQWoCDIwTlZ?gF-`BDm!z(F2M7s={nE0gBVZEX|$Fvs783H}G?*T(nGC+CtjRi>Tf zbka$#CCRdklblI1ID8(@kq2nr9WrBCXhcFyDU-{9IT}P$5cyA)HEK2v6Y4QQ4x^N3 zN5|l^VstE<%j9N7dH5^tM|=&}-$IBEz<@Y~ys9*M?RGWvwk1nicvOG0)~E~f4rn)0 z`)2Df_TX~P!TklRKI7za{CAvukPDyKq)4j#j&o1xI$XpZMki|Nsh{#E zj_TX~*}YVEmA%DSAUzc%k zO<_XH{ja&qSQ@3SCd|w~uCW5BCu{mf(=3*B!)BM*XFsNKkNgLXZ&5 zf9XA!<0Zj7HRTc^qd!y=g^N!CE;E+DcoF&_NVUTA8>LV>UY3Oar})k4cnhcDM2lHH zd7`bdx#7fif(*dG!c$irxGJ0`vW67!$_S2ywC4%<&cwQO3OcK>8pEP-J#yQui=RsmpvXs z3gxjXvJZnkBi;%OVcNThDSPfF`RLxPvWtb4c~3u`Fm%kNjqGZrRat}4>swo!&DKo( zz=2Z!@=_j}=4SQ*dor3Zw3sDjimQu@O!$oVg(x9nnEfd(U=@)GvNT%_?G3rMpY~>a zc@G4r!k|w`d#PiHUa!LmMho4tvbKf4P|HRiZEjb#wl@FY7P_?XI2>`!1yc`=6pZob zoLq){fsD~#^Dl-*5=Cy&km&kuav zm8H-kOhzdh+*I+@*p%^PPG^SCjIfb214*pvojayrRZ%%%36dZSuv%+lQ8pDOvh;jlfWDL{KX{m_i~ zA$ro7Ta*F)%C4y&fUi_54Y+c6N?G^T3S~;M8W#i+WBkNUhpli=}sJa?#-w zr*{f3EtJZuuv#Vwp0hs8GCwPpIe(dEqRJV*NV0T+yd7{E`Pc=>rs}wW7|4Irgl(nI z%9=NGsVlmI%%-**VN!dJ`kU1%{iaaWTYy;$tJ&K$fmLJU!^n0J6vCLJ668;!9(&+Q<{MPx9kLbzK6KJ`G!pzy zjWB&*exL?}y@m=J5MwOVji3(s%Cz0UTnWKuY1 zK*+`I?c29+Z|+b?@nX}Ad(%i3m{F!KZ0_8sVp}fHj{xU=U~cs*I7W(6D};vt-6%Lf zX(z1URi}6nZiwjTS4_k#EDNGuJ6oGO1Z&G#cdAa!F`37ynzM#rkby_?-{E0KN~p`L zWma0gzHm`*+qwTC*81U?r>mmn9nU&(;v5#?nXt!Go$27Ti({SZF_C$OQCqyMIwq4&oD{5F zf+5Z;aGNY{Yq3R8jJwMC z9=I*zdjryyLz-Cd6=lAjf349yFVdYi>qEV7eE3WhW7*gH#$xv+x0TZ|`$dn-vaghY z4umTEl9|239d3k7qPC?YO~M&_3Dpt6&41B%y=z<UlUe<$a^qEqfedJ`fz2Hldk>sVAz_D`el z+isaN?iGDkbN*X2HO&NE^gV|6c)4S6%h?f)ACJpa_tG_@yR@x}pD_NA4&ZyPaC63d z9LV5?aYdJlKaqMZ{hAOgNDpySk;Fy=*E}$5IV`I%3ubfLbH+6w9INb;NurFC9(Gb$ z{&&JjUsvx$SRN=}W(MS~|9!CX=>qyz6YTu$%ItD+W?=Q|MY<}Io{qOG%~q`e3YHnU zJf0nDW$r=mTPFJBKjtybH~wnC!vex$2K_sK88czW$+l*Nv*rRgG_1H>W}GBzA0HYJ zav7?UsN>a~wIj%oQ##UIXLbOX9 z%amLhl1t+pX)1qzL<*-Fcz+-v@TPeA#Hqo^hyi2&H&IVyrmEQy5L$kOaIXcBoSz|X zo8>cQM^X>4CfSX*$70%+Onh*O=rcyP9LEgfjzK}f?xgS$IKqCdr{|kblaI!pKpb&q zG+ctC@H;&rGN27?+T@j1J_~meA0)e*b|mk_@5p}5MTNX6D0?q>QITfJX4kNB>7|rk z`?Z7Z2b^-e8eiZ@8?>%boHTM8NbAmP{4ZmXqAxZ62eFFkN1{v1rNYAHq6sRZ=SK|c z-!wt+cTINLd5zW~bFz`Gqax#tgou97O-Y`@y%j4#|KrA0Z)jh>CFu`v(&&X$oe!CK zMCr?r2`wt3#wU|RDAlZplSx9ZB*t{)nI!B_Zr$5wv^r>N`ivAE2et#(DFT)>VlzPaz8j-j>o+=?n(rhNF%=aKo8V@VQRb=C1 zw*^~`6B27UR00Z2-mFHu4E@eZ;43gQV0aqoDJu;bH~|4etF)P zQb0KfMep9N7<)o@uWflm@+0z@hHVc2@A#v-oa4a7ZSDnp;#?@vgL*q7Pry}Ca^1PVF z&&ituEhyNo?J*_MelxAb51ce^qhx1N{6Ok(-hPu&>>l(R#7XLLap1~xq%T3N`XSjs znE|ewrc$jzq|FnrS-x3}82lT0igF{}{=P~oKD73gYaVjilJ5}mlOE{}dF!ZeiJ_pW zq(bD)vOimlB*x9Qt4KA-HOey6y;9*ofp<${+0I?JAT<>ytcM#tX

esrA7YC`tFU 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

Xse3CT&plTf7 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≪U4UWwVNYS4`<+T?ZJ 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�E7BC>O7OD>;&`Bb-qk57LvfsqU0+E+h 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

I);H-n2w$X@rFe9 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ÐG${emez?n<^Y>HSLWr}H?-LGmc5m9 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

#lx9JgXIqz{WrVEB0xaz4pQ_Flwol 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

fEB%kzY&=W0XiEsxDrTuq|VmXD;vym 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 z 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

BM6mkGV{yO97@t4g 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%0Al(Lo5 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.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≀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%0DX$RQVnLiN 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

&*5Jf6v& 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 z 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

3`#D_J3G|-R-T5dCntG!*TeKt1cZrJ?# z@YMR;4HLriPht&lxHaD;#vGe8??D;VFC})oW-~F3<8|%S(|+x7R2{)I*1;7Y5mC{w zCa_7H6~2S7T&8hSOqN+F3GcBy4I!I`oK19tjY<%Vj82H0zK@yx5Fh?E83{q^Ny_MX zBI60b%!fda@?zy$M%7d}{HQbshT)o}IY{k?$QnCAf`TS zPNOF*Oqgkfxg1vZtL=P7+h@BnxqT2y9e?JSyd_X>cTNO5^tFPPBQ$6oR&yFfL>Cng-#!X8iv%Lm zESZ)!-H1SyjYptixc_-{z2c5naZqXE+TUxscbi=M=_augEwBQHvlBK%$=RS8X2{P* zPa|`NFt&#a5%c&>ogP|*_e@bJhrowE0V32)zNC_}039;HPUJ+F+lC{TXrxe+(7OJu zNWI24ilq*N8v>B~S1~qEmkJ4Epc$_MikF{(i6=R>lUA|{)HX>8Oqp{LebKB887vGj zokX~!jE&L?TFSpY_U2S0Tqh=y(FxWtEoLLite;ny4F?({`;)Tzv3#2BxV9}M??LTB zdJhh#l3}kf^XT!#9r5&96RFUwo4r|nJYlm4Wlh>JgXbBZC~X+(HtgRpgZT{8mMEYn z<3Q?hcAI_vT{>w^$tiOPkTl<60C<|^7nOTLqvy2w_Z9#Sb(u4DaCY;>D(P%4+yH

~TXe6~x=p@X+Bp{_PiC4+S~n(~ib)N)x@?sUc2L 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 z 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 z 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 z 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%0AMK4(}H~-dR7-gu@ev<9il$=_FE9| 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 T& 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≪^!XFVE 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

1&&lT5p3Gd32BV+H2F(=kh_p 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 z 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

Z0Ql{o2jPcv7jT;T~t(+({}v8csFcO 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 z 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�fmDfkb$Jm=CVKQMtwO{ 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%0DE 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

$G#8PSt{xqIr)cabjnvT! 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
iaO zh6Kxm+6b(GPd_vzX#Y5mJ|oMUcl!odM;Pi!u9s_{h3EO_pa0jxXKyKht2g$~^vKF1 zF)_*yt^wdlQ!|Bw;XmOjQPIkVQb!A`>=8_^_JuUy3Sa`bXqWBRBo-F^b%7Aa%hcKl zN0xkdnyeHSN=qYiXHlmEY_}xl@(@as5F4Oq{?lXKla;xWE6rYn_Mjiz5!%04y{#D{ zZdc9uUd2NUUSFG21zHPIE1f4(w?*@r;(W|4i$!U>w(cfpmlm4&`O@+^umveo{w zL9LO2y|2USydVp9!RVJyW5ZV>hd^LcV`0Prvub?TXlAC7n6pF(X*b&CwIpel>($13 zasmvsW+omJ4o467t7e7cc{`4xp@8Ngf~z}h6Kl=4A37v$p+PdHQmb!p-;%EfpTu=`K=lFaYiJ(-~=7@1W+ z48Em`_H4qpebWsSUlk7ccMlZ|W+ z9)DupU2inEo){;&MWP{V4aRQO7qK|EJNp9|7N%T1)_@^JyC)MB{9~Ho--l)58f{Fc}FB`UOVtljXz;8*a^E3bs(AyOIA;?4HEi=G~6r(!>fPNm`KPPG}ik#Rn@ z9~j^MD4-vIG!6_cz$$;`DiIt^O7u-P6$KI0WlnBBH+TI8$TP!IRG#Kv$j{|-i(n)0 zpupPjw8Gy;Plg^hlY;9bm8;lg4^)o0L>?S6Z5=wBj(GFd<+zj>=}T(G-oGxPF7roM@WSj&_Gc0Ak%HKiF)HyyM3* zUTa30XOOe`3x#=ko=UOgmW?vW^3;T*`3At#Rn5FV`VP1^Da|3YZOOr8u7=T*(aoL zRKrN7dRn%=HM5KIS&tXgjL`a}z(EN|I;G5Cg?(Sr@)A!jsM%OA|f(Z239#pMlpEwIKh{2*>l7 z=&d*K812an+>ih^J%y*WFS^af%35OuUJ>~e_s(G^Or;T{%&`-YNiTCM?SY{ua)7D^ zR)Kmy=_8dkEryWl!;(}61u=TZq~LoLH8rw5TQ*6&11+0_P6#G(Hh{#MJE9PLtzCOk z;9%6NbI0zO#BFxTRtrK;QMH*8=C12OBusYiE+OV zHkX{spU*ALl~~*04K6GjQE-T?-bGgEP=8} { + do_test incrblob2-6.2b { + set rc [catch { + # Prior to 2015-02-07, the following caused a segfault due to + # integer overflow. + sqlite3_blob_read $rdHandle 2147483647 2147483647 + } errmsg] + lappend rc $errmsg + } {1 SQLITE_ERROR} +} +do_test incrblob2-6.2c { + set rc [catch { + # Prior to 2015-02-07, the following caused a segfault due to + # integer overflow. + sqlite3_blob_read $rdHandle 2147483647 100 + } errmsg] + lappend rc $errmsg +} {1 SQLITE_ERROR} + do_test incrblob2-6.3 { set wrHandle [db incrblob t1 data 1] sqlite3_blob_write $wrHandle 0 ZZZZZZZZZZ sqlite3_blob_read $rdHandle 2 4 } {ZZZZ} +do_test incrblob2-6.3b { + set rc [catch { + # Prior to 2015-02-07, the following caused a segfault due to + # integer overflow. + sqlite3_blob_write $wrHandle 2147483647 YYYYYYYYYYYYYYYYYY + } errmsg] + lappend rc $errmsg +} {1 SQLITE_ERROR} +do_test incrblob2-6.3c { + sqlite3_blob_read $rdHandle 2 4 +} {ZZZZ} + + do_test incrblob2-6.4 { close $wrHandle close $rdHandle diff --git a/test/incrcorrupt.test b/test/incrcorrupt.test new file mode 100644 index 0000000..eda65e4 --- /dev/null +++ b/test/incrcorrupt.test @@ -0,0 +1,127 @@ +# 2001 October 12 +# +# 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. +# +#*********************************************************************** +# Test that "PRAGMA incremental_vacuum" detects and reports database +# corruption properly. And that "PRAGMA auto_vacuum = INCREMENTAL" +# does as well. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix incrcorrupt + +# If this build of the library does not support auto-vacuum, omit this +# whole file. +ifcapable {!autovacuum} { + finish_test + return +} + +do_execsql_test 1.0 { + PRAGMA auto_vacuum = 2; + CREATE TABLE t1(a PRIMARY KEY, b); + + WITH data(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM data + ) + INSERT INTO t1 SELECT i, randomblob(600) FROM data LIMIT 20; + PRAGMA page_count; +} {24} + +do_execsql_test 1.1 { + PRAGMA incremental_vacuum; +} {} + +do_test 1.2 { + db_save + hexio_write test.db 36 00000019 + catchsql { PRAGMA incremental_vacuum; } +} {1 {database disk image is malformed}} + +do_test 1.3 { + set stmt [sqlite3_prepare_v2 db "PRAGMA incremental_vacuum" -1 dummy] + sqlite3_step $stmt +} {SQLITE_CORRUPT} +do_test 1.4 { sqlite3_errcode db } {SQLITE_CORRUPT} +do_test 1.5 { sqlite3_errmsg db } {database disk image is malformed} +do_test 1.6 { sqlite3_finalize $stmt } {SQLITE_CORRUPT} +do_test 1.7 { sqlite3_errcode db } {SQLITE_CORRUPT} +do_test 1.8 { sqlite3_errmsg db } {database disk image is malformed} + +do_test 1.9 { + set stmt [sqlite3_prepare_v2 db "PRAGMA incremental_vacuum" -1 dummy] + sqlite3_step $stmt +} {SQLITE_CORRUPT} +do_test 1.10 { sqlite3_errcode db } {SQLITE_CORRUPT} +do_test 1.11 { sqlite3_errmsg db } {database disk image is malformed} + +do_test 1.12 { + set stmt2 [sqlite3_prepare_v2 db "SELECT 1" -1 dummy] + sqlite3_finalize $stmt2 +} {SQLITE_OK} +do_test 1.13 { sqlite3_errcode db } {SQLITE_OK} +do_test 1.14 { sqlite3_errmsg db } {not an error} + +do_test 1.15 { sqlite3_finalize $stmt } {SQLITE_CORRUPT} +do_test 1.16 { sqlite3_errcode db } {SQLITE_CORRUPT} +do_test 1.17 { sqlite3_errmsg db } {database disk image is malformed} + +#------------------------------------------------------------------------- +# +reset_db + +do_execsql_test 2.1 { + PRAGMA auto_vacuum = 1; + CREATE TABLE t1(a PRIMARY KEY, b); + WITH data(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM data + ) + INSERT INTO t1 SELECT i, randomblob(600) FROM data LIMIT 20; + PRAGMA page_count; +} {24} + +do_test 2.2 { + db_save + set fd [open test.db r+] + chan truncate $fd [expr 22*1024] + close $fd + catchsql { PRAGMA incremental_vacuum; } +} {1 {database disk image is malformed}} + +do_test 2.3 { + set stmt [sqlite3_prepare_v2 db "PRAGMA auto_vacuum = INCREMENTAL" -1 dummy] + sqlite3_step $stmt +} {SQLITE_CORRUPT} +do_test 2.4 { sqlite3_errcode db } {SQLITE_CORRUPT} +do_test 2.5 { sqlite3_errmsg db } {database disk image is malformed} +do_test 2.6 { sqlite3_finalize $stmt } {SQLITE_CORRUPT} +do_test 2.7 { sqlite3_errcode db } {SQLITE_CORRUPT} +do_test 2.8 { sqlite3_errmsg db } {database disk image is malformed} + +do_test 2.9 { + set stmt [sqlite3_prepare_v2 db "PRAGMA auto_vacuum = INCREMENTAL" -1 dummy] + sqlite3_step $stmt +} {SQLITE_CORRUPT} +do_test 2.10 { sqlite3_errcode db } {SQLITE_CORRUPT} +do_test 2.11 { sqlite3_errmsg db } {database disk image is malformed} + +do_test 2.12 { + set stmt2 [sqlite3_prepare_v2 db "SELECT 1" -1 dummy] + sqlite3_finalize $stmt2 +} {SQLITE_OK} +do_test 2.13 { sqlite3_errcode db } {SQLITE_OK} +do_test 2.14 { sqlite3_errmsg db } {not an error} + +do_test 2.15 { sqlite3_finalize $stmt } {SQLITE_CORRUPT} +do_test 2.16 { sqlite3_errcode db } {SQLITE_CORRUPT} +do_test 2.17 { sqlite3_errmsg db } {database disk image is malformed} + +finish_test + diff --git a/test/incrvacuum2.test b/test/incrvacuum2.test index 6e8e1be..2219d54 100644 --- a/test/incrvacuum2.test +++ b/test/incrvacuum2.test @@ -188,8 +188,10 @@ ifcapable wal { execsql { PRAGMA journal_mode = WAL; PRAGMA incremental_vacuum(1); - PRAGMA wal_checkpoint; } + } {wal} + do_test 4.2.1 { + execsql { PRAGMA wal_checkpoint } file size test.db-wal } [expr {32+2*(512+24)}] diff --git a/test/index3.test b/test/index3.test index a9f9b7a..0cdc6e0 100644 --- a/test/index3.test +++ b/test/index3.test @@ -51,6 +51,6 @@ do_test index3-99.1 { db close catch { sqlite3 db test.db } catchsql { DROP INDEX i1 } -} {1 {malformed database schema (t1) - near "nonsense": syntax error}} +} {1 {malformed database schema (t1)}} finish_test diff --git a/test/index6.test b/test/index6.test index 8414b11..69fae49 100644 --- a/test/index6.test +++ b/test/index6.test @@ -296,4 +296,35 @@ do_execsql_test index6-7.4 { SELECT * FROM t7a JOIN t7b ON (x=99) ORDER BY x; } {/USING COVERING INDEX t7ax/} + +do_execsql_test index6-8.0 { + CREATE TABLE t8a(a,b); + CREATE TABLE t8b(x,y); + CREATE INDEX i8c ON t8b(y) WHERE x = 'value'; + + INSERT INTO t8a VALUES(1, 'one'); + INSERT INTO t8a VALUES(2, 'two'); + INSERT INTO t8a VALUES(3, 'three'); + + INSERT INTO t8b VALUES('value', 1); + INSERT INTO t8b VALUES('dummy', 2); + INSERT INTO t8b VALUES('value', 3); + INSERT INTO t8b VALUES('dummy', 4); +} {} + +do_eqp_test index6-8.1 { + SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a) +} { + 0 0 0 {SCAN TABLE t8a} + 0 1 1 {SEARCH TABLE t8b USING INDEX i8c (y=?)} +} + +do_execsql_test index6-8.2 { + SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a) +} { + 1 one value 1 + 2 two {} {} + 3 three value 3 +} + finish_test diff --git a/test/index7.test b/test/index7.test index 0f341a3..557fe21 100644 --- a/test/index7.test +++ b/test/index7.test @@ -21,6 +21,31 @@ ifcapable !vtab { return } +# Capture the output of a pragma in a TEMP table. +# +proc capture_pragma {db tabname sql} { + $db eval "DROP TABLE IF EXISTS temp.$tabname" + set once 1 + $db eval $sql x { + if {$once} { + set once 0 + set ins "INSERT INTO $tabname VALUES" + set crtab "CREATE TEMP TABLE $tabname " + set sep "(" + foreach col $x(*) { + append ins ${sep}\$x($col) + append crtab ${sep}\"$col\" + set sep , + } + append ins ) + append crtab ) + $db eval $crtab + } + $db eval $ins + } +} + + load_static_extension db wholenumber; do_test index7-1.1 { # Able to parse and manage partial indices @@ -37,6 +62,15 @@ do_test index7-1.1 { } } {14 20 ok} +# (The "partial" column of the PRAGMA index_list output is...) +# EVIDENCE-OF: R-34457-09668 "1" if the index is a partial index and "0" +# if not. +# +do_test index7-1.1a { + capture_pragma db out {PRAGMA index_list(t1)} + db eval {SELECT "name", "partial", '|' FROM out ORDER BY "name"} +} {sqlite_autoindex_t1_1 0 | t1a 1 | t1b 1 |} + # Make sure the count(*) optimization works correctly with # partial indices. Ticket [a5c8ed66cae16243be6] 2013-10-03. # @@ -277,5 +311,9 @@ do_eqp_test index7-6.4 { } { 0 0 0 {SEARCH TABLE t4 USING INDEX i4 (c=?)} } +do_catchsql_test index7-6.5 { + CREATE INDEX t5a ON t5(a) WHERE a=#1; +} {1 {near "#1": syntax error}} + finish_test diff --git a/test/indexedby.test b/test/indexedby.test index f95c167..413bf07 100644 --- a/test/indexedby.test +++ b/test/indexedby.test @@ -1,4 +1,4 @@ -# 2008 October 4 +# 2008-10-04 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -9,7 +9,6 @@ # #*********************************************************************** # -# $Id: indexedby.test,v 1.5 2009/03/22 20:36:19 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -58,20 +57,45 @@ do_execsql_test indexedby-1.4 { # attached to a table in the FROM clause, but not to a sub-select or # SQL view. Also test that specifying an index that does not exist or # is attached to a different table is detected as an error. +# +# EVIDENCE-OF: R-63761-48810 -- syntax diagram qualified-table-name # +# EVIDENCE-OF: R-58230-57098 The "INDEXED BY index-name" phrase +# specifies that the named index must be used in order to look up values +# on the preceding table. +# do_test indexedby-2.1 { execsql { SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'} } {} +do_test indexedby-2.1b { + execsql { SELECT * FROM main.t1 NOT INDEXED WHERE a = 'one' AND b = 'two'} +} {} do_test indexedby-2.2 { execsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'} } {} +do_test indexedby-2.2b { + execsql { SELECT * FROM main.t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two'} +} {} do_test indexedby-2.3 { execsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'} } {} - +# EVIDENCE-OF: R-44699-55558 The INDEXED BY clause does not give the +# optimizer hints about which index to use; it gives the optimizer a +# requirement of which index to use. +# EVIDENCE-OF: R-15800-25719 If index-name does not exist or cannot be +# used for the query, then the preparation of the SQL statement fails. +# do_test indexedby-2.4 { catchsql { SELECT * FROM t1 INDEXED BY i3 WHERE a = 'one' AND b = 'two'} } {1 {no such index: i3}} + +# EVIDENCE-OF: R-62112-42456 If the query optimizer is unable to use the +# index specified by the INDEX BY clause, then the query will fail with +# an error. +do_test indexedby-2.4.1 { + catchsql { SELECT b FROM t1 INDEXED BY i1 WHERE b = 'two' } +} {1 {no query solution}} + do_test indexedby-2.5 { catchsql { SELECT * FROM t1 INDEXED BY i5 WHERE a = 'one' AND b = 'two'} } {1 {no such index: i5}} @@ -82,11 +106,26 @@ do_test indexedby-2.7 { catchsql { SELECT * FROM v1 INDEXED BY i1 WHERE a = 'one' } } {1 {no such index: i1}} + # Tests for single table cases. # +# EVIDENCE-OF: R-37002-28871 The "NOT INDEXED" clause specifies that no +# index shall be used when accessing the preceding table, including +# implied indices create by UNIQUE and PRIMARY KEY constraints. However, +# the rowid can still be used to look up entries even when "NOT INDEXED" +# is specified. +# do_execsql_test indexedby-3.1 { + EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a = 'one' AND b = 'two' +} {/SEARCH TABLE t1 USING INDEX/} +do_execsql_test indexedby-3.1.1 { EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two' } {0 0 0 {SCAN TABLE t1}} +do_execsql_test indexedby-3.1.2 { + EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE rowid=1 +} {/SEARCH TABLE t1 USING INTEGER PRIMARY KEY .rowid=/} + + do_execsql_test indexedby-3.2 { EXPLAIN QUERY PLAN SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' AND b = 'two' @@ -184,6 +223,10 @@ do_execsql_test indexedby-6.2 { EXPLAIN QUERY PLAN SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid } {0 0 0 {SCAN TABLE t1}} +# EVIDENCE-OF: R-40297-14464 The INDEXED BY phrase forces the SQLite +# query planner to use a particular named index on a DELETE, SELECT, or +# UPDATE statement. +# # Test that "INDEXED BY" can be used in a DELETE statement. # do_execsql_test indexedby-7.1 { diff --git a/test/insert2.test b/test/insert2.test index 6876d53..977fbc5 100644 --- a/test/insert2.test +++ b/test/insert2.test @@ -16,6 +16,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix insert2 # Create some tables with data that we can select against # @@ -275,4 +276,23 @@ ifcapable subquery { } {1 2 1 3 1 4} } +do_execsql_test 6.0 { + CREATE TABLE t5(a, b, c DEFAULT 'c', d); +} +do_execsql_test 6.1 { + INSERT INTO t5(a) SELECT 456 UNION ALL SELECT 123 ORDER BY 1; + SELECT * FROM t5 ORDER BY rowid; +} {123 {} c {} 456 {} c {}} + +ifcapable fts3 { + do_execsql_test 6.2 { + CREATE VIRTUAL TABLE t0 USING fts4(a); + } + do_execsql_test 6.3 { + INSERT INTO t0 SELECT 0 UNION SELECT 0 AS 'x' ORDER BY x; + SELECT * FROM t0; + } {0} +} + + finish_test diff --git a/test/insert4.test b/test/insert4.test index 889d5e7..3eece87 100644 --- a/test/insert4.test +++ b/test/insert4.test @@ -560,5 +560,10 @@ do_test insert4-8.25 { } } {1 3} +do_catchsql_test insert4-9.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x); + INSERT INTO t1(x) VALUES(5 COLLATE xyzzy) UNION SELECT 0; +} {1 {no such collation sequence: xyzzy}} finish_test diff --git a/test/jrnlmode.test b/test/jrnlmode.test index b1007c4..2ba56f2 100644 --- a/test/jrnlmode.test +++ b/test/jrnlmode.test @@ -555,4 +555,18 @@ do_execsql_test jrnlmode-8.28 { PRAGMA journal_mode=DELETE } {delete} do_execsql_test jrnlmode-8.29 { COMMIT } {} do_execsql_test jrnlmode-8.30 { PRAGMA journal_mode=DELETE } {delete} +# Assertion fault on 2015-05-01 +do_test jrnlmode-9.1 { + forcedelete test2.db + sqlite3 db2 test2.db + db2 eval {CREATE TEMP TABLE t(l); PRAGMA journal_mode=off;} + db2 close +} {} +do_execsql_test jrnlmode-9.2 { + PRAGMA locking_mode = exclusive; + CREATE TABLE tx(a); + PRAGMA journal_mode = off; +} {exclusive off} + + finish_test diff --git a/test/like.test b/test/like.test index 923272c..18a01dc 100644 --- a/test/like.test +++ b/test/like.test @@ -749,7 +749,7 @@ ifcapable like_opt&&!icu { count { SELECT a FROM t10 WHERE f LIKE '12%' ORDER BY +a; } - } {12 123 scan 3 like 0} + } {12 123 scan 4 like 0} do_test like-10.6 { count { SELECT a FROM t10 WHERE a LIKE '12%' ORDER BY +a; @@ -790,7 +790,7 @@ ifcapable like_opt&&!icu { count { SELECT a FROM t10b WHERE f GLOB '12*' ORDER BY +a; } - } {12 123 scan 3 like 0} + } {12 123 scan 4 like 0} do_test like-10.15 { count { SELECT a FROM t10b WHERE a GLOB '12*' ORDER BY +a; diff --git a/test/like3.test b/test/like3.test new file mode 100644 index 0000000..a1faf76 --- /dev/null +++ b/test/like3.test @@ -0,0 +1,112 @@ +# 2015-03-06 +# +# 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 file is testing the LIKE and GLOB operators and +# in particular the optimizations that occur to help those operators +# run faster and that those optimizations work correctly when there +# are both strings and blobs being tested. +# +# Ticket 05f43be8fdda9fbd948d374319b99b054140bc36 shows that the following +# SQL was not working correctly: +# +# CREATE TABLE t1(x TEXT UNIQUE COLLATE nocase); +# INSERT INTO t1(x) VALUES(x'616263'); +# SELECT 'query-1', x FROM t1 WHERE x LIKE 'a%'; +# SELECT 'query-2', x FROM t1 WHERE +x LIKE 'a%'; +# +# This script verifies that it works right now. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_execsql_test like3-1.1 { + PRAGMA encoding=UTF8; + CREATE TABLE t1(a,b TEXT COLLATE nocase); + INSERT INTO t1(a,b) + VALUES(1,'abc'), + (2,'ABX'), + (3,'BCD'), + (4,x'616263'), + (5,x'414258'), + (6,x'424344'); + CREATE INDEX t1ba ON t1(b,a); + + SELECT a, b FROM t1 WHERE b LIKE 'aB%' ORDER BY +a; +} {1 abc 2 ABX 4 abc 5 ABX} +do_execsql_test like3-1.2 { + SELECT a, b FROM t1 WHERE +b LIKE 'aB%' ORDER BY +a; +} {1 abc 2 ABX 4 abc 5 ABX} + +do_execsql_test like3-2.0 { + CREATE TABLE t2(a, b TEXT); + INSERT INTO t2 SELECT a, b FROM t1; + CREATE INDEX t2ba ON t2(b,a); + SELECT a, b FROM t2 WHERE b GLOB 'ab*' ORDER BY +a; +} {1 abc 4 abc} +do_execsql_test like3-2.1 { + SELECT a, b FROM t2 WHERE +b GLOB 'ab*' ORDER BY +a; +} {1 abc 4 abc} +do_execsql_test like3-2.2 { + SELECT a, b FROM t2 WHERE b>=x'6162' AND b GLOB 'ab*' +} {4 abc} +do_execsql_test like3-2.3 { + SELECT a, b FROM t2 WHERE +b>=x'6162' AND +b GLOB 'ab*' +} {4 abc} +do_execsql_test like3-2.4 { + SELECT a, b FROM t2 WHERE b GLOB 'ab*' AND b>=x'6162' +} {4 abc} +do_execsql_test like3-2.5 { + SELECT a, b FROM t2 WHERE +b GLOB 'ab*' AND +b>=x'6162' +} {4 abc} + +do_execsql_test like3-3.0 { + CREATE TABLE t3(x TEXT PRIMARY KEY COLLATE nocase); + INSERT INTO t3(x) VALUES('aaa'),('abc'),('abd'),('abe'),('acz'); + INSERT INTO t3(x) SELECT CAST(x AS blob) FROM t3; + SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x; +} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'} +do_execsql_test like3-3.1 { + SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x DESC; +} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'} +do_execsql_test like3-3.1ck { + SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY +x DESC; +} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'} +do_execsql_test like3-3.2 { + SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY x ASC; +} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'} +do_execsql_test like3-3.2ck { + SELECT quote(x) FROM t3 WHERE x LIKE 'ab%' ORDER BY +x ASC; +} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'} + +do_execsql_test like3-4.0 { + CREATE TABLE t4(x TEXT COLLATE nocase); + CREATE INDEX t4x ON t4(x DESC); + INSERT INTO t4(x) SELECT x FROM t3; + SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x; +} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'} +do_execsql_test like3-4.1 { + SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x DESC; +} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'} +do_execsql_test like3-4.1ck { + SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY +x DESC; +} {X'616265' X'616264' X'616263' 'abe' 'abd' 'abc'} +do_execsql_test like3-4.2 { + SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY x ASC; +} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'} +do_execsql_test like3-4.2ck { + SELECT quote(x) FROM t4 WHERE x LIKE 'ab%' ORDER BY +x ASC; +} {'abc' 'abd' 'abe' X'616263' X'616264' X'616265'} + + + +finish_test diff --git a/test/limit.test b/test/limit.test index 5d6ef33..d727497 100644 --- a/test/limit.test +++ b/test/limit.test @@ -251,6 +251,12 @@ do_test limit-6.8 { # Make sure LIMIT works well with compound SELECT statements. # Ticket #393 # +# EVIDENCE-OF: R-13512-64012 In a compound SELECT, only the last or +# right-most simple SELECT may contain a LIMIT clause. +# +# EVIDENCE-OF: R-03782-50113 In a compound SELECT, the LIMIT clause +# applies to the entire compound, not just the final SELECT. +# ifcapable compound { do_test limit-7.1.1 { catchsql { diff --git a/test/lock.test b/test/lock.test index 6ec85ee..f785c4b 100644 --- a/test/lock.test +++ b/test/lock.test @@ -241,6 +241,9 @@ execsql {ROLLBACK} # Test the built-in busy timeout handler # +# EVIDENCE-OF: R-23579-05241 PRAGMA busy_timeout; PRAGMA busy_timeout = +# milliseconds; Query or change the setting of the busy timeout. +# do_test lock-2.8 { db2 timeout 400 execsql BEGIN diff --git a/test/lock_common.tcl b/test/lock_common.tcl index bc1eb86..a758e7a 100644 --- a/test/lock_common.tcl +++ b/test/lock_common.tcl @@ -86,21 +86,51 @@ proc launch_testfixture {{prg ""}} { # Execute a command in a child testfixture process, connected by two-way # channel $chan. Return the result of the command, or an error message. # -proc testfixture {chan cmd} { - puts $chan $cmd - puts $chan OVER - set r "" - while { 1 } { +proc testfixture {chan cmd args} { + + if {[llength $args] == 0} { + fconfigure $chan -blocking 1 + puts $chan $cmd + puts $chan OVER + + set r "" + while { 1 } { + set line [gets $chan] + if { $line == "OVER" } { + set res [lindex $r 1] + if { [lindex $r 0] } { error $res } + return $res + } + if {[eof $chan]} { + return "ERROR: Child process hung up" + } + append r $line + } + return $r + } else { + set ::tfnb($chan) "" + fconfigure $chan -blocking 0 -buffering none + puts $chan $cmd + puts $chan OVER + fileevent $chan readable [list testfixture_script_cb $chan [lindex $args 0]] + return "" + } +} + +proc testfixture_script_cb {chan script} { + if {[eof $chan]} { + append ::tfnb($chan) "ERROR: Child process hung up" + set line "OVER" + } else { set line [gets $chan] - if { $line == "OVER" } { - set res [lindex $r 1] - if { [lindex $r 0] } { error $res } - return $res - } - if {[eof $chan]} { - return "ERROR: Child process hung up" - } - append r $line + } + + if { $line == "OVER" } { + uplevel #0 $script [list [lindex $::tfnb($chan) 1]] + unset ::tfnb($chan) + fileevent $chan readable "" + } else { + append ::tfnb($chan) $line } } diff --git a/test/malloc.test b/test/malloc.test index 8614567..dbf4699 100644 --- a/test/malloc.test +++ b/test/malloc.test @@ -923,6 +923,27 @@ do_faultsim_test 41.2 -faults oom* -body { faultsim_integrity_check } +reset_db +do_execsql_test 42.0 { + CREATE TABLE t1(x INTEGER PRIMARY KEY, y, z); + CREATE TABLE t2(a, b); + CREATE VIEW a002 AS SELECT *, sum(b) AS m FROM t2 GROUP BY a; +} +faultsim_save_and_close +do_faultsim_test 42 -faults oom-tran* -prep { + faultsim_restore_and_reopen + execsql { SELECT * FROM sqlite_master } +} -body { + execsql { + SELECT t1.z, a002.m + FROM t1 JOIN a002 ON t1.y=a002.m + WHERE t1.x IN (1,2,3); + } +} -test { + faultsim_test_result {0 {}} +} + + # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} diff --git a/test/malloc5.test b/test/malloc5.test index 6abedf7..c046499 100644 --- a/test/malloc5.test +++ b/test/malloc5.test @@ -71,6 +71,23 @@ do_test malloc5-1.3 { expr $::pgalloc > 0 } {1} +# The sizes of memory allocations from system malloc() might vary, +# depending on the memory allocator algorithms used. The following +# routine is designed to support answers that fall within a range +# of values while also supplying easy-to-understand "expected" values +# when errors occur. +# +proc value_in_range {target x args} { + set v [lindex $args 0] + if {$v!=""} { + if {$v<$target*$x} {return $v} + if {$v>$target/$x} {return $v} + } + return "number between [expr {int($target*$x)}] and [expr {int($target/$x)}]" +} +set mrange 0.98 ;# plus or minus 2% + + do_test malloc5-1.4 { # Commit the transaction and open a new one. Read 1 page into the cache. # Because the page is not dirty, it is eligible for collection even @@ -81,16 +98,16 @@ do_test malloc5-1.4 { BEGIN; SELECT * FROM abc; } - sqlite3_release_memory -} $::pgalloc + value_in_range $::pgalloc $::mrange [sqlite3_release_memory] +} [value_in_range $::pgalloc $::mrange] do_test malloc5-1.5 { # Conclude the transaction opened in the previous [do_test] block. This # causes another page (page 1) to become eligible for recycling. # execsql { COMMIT } - sqlite3_release_memory -} $::pgalloc + value_in_range $::pgalloc $::mrange [sqlite3_release_memory] +} [value_in_range $::pgalloc $::mrange] do_test malloc5-1.6 { # Manipulate the cache so that it contains two unused pages. One requires @@ -101,8 +118,8 @@ do_test malloc5-1.6 { SELECT * FROM abc; CREATE TABLE def(d, e, f); } - sqlite3_release_memory 500 -} $::pgalloc + value_in_range $::pgalloc $::mrange [sqlite3_release_memory 500] +} [value_in_range $::pgalloc $::mrange] do_test malloc5-1.7 { # Database should not be locked this time. diff --git a/test/mallocK.test b/test/mallocK.test index dcf00da..65791e7 100644 --- a/test/mallocK.test +++ b/test/mallocK.test @@ -134,5 +134,42 @@ do_faultsim_test 6 -faults oom* -body { faultsim_test_result {0 {12 13 14 15}} } +do_execsql_test 7.1 { + CREATE TABLE x1(a INTEGER PRIMARY KEY, b); +} +do_faultsim_test 7.2 -faults oom* -body { + execsql { SELECT * FROM x1 WHERE a = (SELECT 1) } +} -test { + faultsim_test_result [list 0 {}] +} + +reset_db + +proc isqrt {i} { expr { int(sqrt($i)) } } +db func isqrt isqrt + +do_execsql_test 8.0 { + PRAGMA encoding = 'utf-16'; + CREATE TABLE x2(x TEXT, y TEXT); + WITH data(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM data + ) + INSERT INTO x2 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400; + CREATE INDEX x2x ON x2(x); + CREATE INDEX x2y ON x2(y); + ANALYZE; + DELETE FROM x2; +} + +proc str {a} { return $a } +db func str -deterministic str + +do_faultsim_test 8 -faults oom* -body { + execsql { SELECT * FROM x2 WHERE x = str('19') AND y = str('4') } +} -test { + faultsim_test_result [list 0 {}] +} + + finish_test diff --git a/test/misc1.test b/test/misc1.test index 173b77d..7ae50e4 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -13,7 +13,6 @@ # This file implements tests for miscellanous features that were # left out of other test files. # -# $Id: misc1.test,v 1.42 2007/11/05 14:58:23 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -621,4 +620,68 @@ do_test misc1-19.2 { set fault_callbacks } {0} +# 2015-01-26: Valgrind-detected over-read. +# Reported on sqlite-users@sqlite.org by Michal Zalewski. Found by afl-fuzz +# presumably. +# +do_execsql_test misc1-20.1 { + CREATE TABLE t0(x INTEGER DEFAULT(0==0) NOT NULL); + REPLACE INTO t0(x) VALUES(''); + SELECT rowid, quote(x) FROM t0; +} {1 ''} + +# 2015-03-22: NULL pointer dereference after a syntax error +# +do_catchsql_test misc1-21.1 { + select''like''like''like#0; +} {1 {near "#0": syntax error}} +do_catchsql_test misc1-21.2 { + VALUES(0,0x0MATCH#0; +} {1 {near ";": syntax error}} + +# 2015-04-15 +do_execsql_test misc1-22.1 { + SELECT ""+3 FROM (SELECT ""+5); +} {3} + +# 2015-04-19: NULL pointer dereference on a corrupt schema +# +db close +sqlite3 db :memory: +do_execsql_test misc1-23.1 { + CREATE TABLE t1(x); + PRAGMA writable_schema=ON; + UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)'; + BEGIN; + CREATE TABLE t2(y); + ROLLBACK; + DROP TABLE IF EXISTS t3; +} {} + +# 2015-04-19: Faulty assert() statement +# +db close +database_may_be_corrupt +sqlite3 db :memory: +do_catchsql_test misc1-23.2 { + CREATE TABLE t1(x UNIQUE); + PRAGMA writable_schema=ON; + UPDATE sqlite_master SET sql='CREATE TABLE IF not EXISTS t(c)'; + BEGIN; + CREATE TABLE t2(x); + ROLLBACK; + DROP TABLE F; +} {1 {no such table: F}} +db close +sqlite3 db :memory: +do_catchsql_test misc1-23.3 { + CREATE TABLE t1(x UNIQUE); + PRAGMA writable_schema=ON; + UPDATE sqlite_master SET sql='CREATE table y(a TEXT, a TEXT)'; + BEGIN; + CREATE TABLE t2(y); + ROLLBACK; + DROP TABLE IF EXISTS t; +} {0 {}} + finish_test diff --git a/test/misc5.test b/test/misc5.test index 14ba44e..30176b8 100644 --- a/test/misc5.test +++ b/test/misc5.test @@ -583,6 +583,24 @@ do_test misc5-7.1 { catchsql $sql } {1 {parser stack overflow}} +# Parser stack overflow is silently ignored when it occurs while parsing the +# schema and PRAGMA writable_schema is turned on. +# +do_test misc5-7.2 { + sqlite3 db2 :memory: + catchsql { + CREATE TABLE t1(x UNIQUE); + PRAGMA writable_schema=ON; + UPDATE sqlite_master SET sql='CREATE table t(o CHECK(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((;VALUES(o)'; + BEGIN; + CREATE TABLE t2(y); + ROLLBACK; + DROP TABLE IF EXISTS D; + } db2 +} {0 {}} +db2 close + + # Ticket #1911 # ifcapable compound { diff --git a/test/mkfuzzdata1.tcl b/test/mkfuzzdata1.tcl new file mode 100644 index 0000000..8af45f6 --- /dev/null +++ b/test/mkfuzzdata1.tcl @@ -0,0 +1,113 @@ +#!/usr/bin/tclsh +# +# Run this script in order to rebuild the fuzzdata1.txt file containing +# fuzzer data for the fuzzershell utility that is create by afl-fuzz. +# +# This script gathers all of the test cases identified by afl-fuzz and +# runs afl-cmin and afl-tmin over them all to try to generate a mimimum +# set of tests that cover all observed behavior. +# +# Options: +# +# --afl-bin DIR1 DIR1 contains the AFL binaries +# --fuzzershell PATH Full pathname of instrumented fuzzershell +# --afl-data DIR3 DIR3 is the "-o" directory from afl-fuzz +# -o FILE Write results into FILE +# +set AFLBIN {} +set FUZZERSHELL {} +set AFLDATA {} +set OUTFILE {} + +proc usage {} { + puts stderr "Usage: $::argv0 --afl-bin DIR --fuzzershell PATH\ + --afl-data DIR -o FILE" + exit 1 +} +proc cmdlineerr {msg} { + puts stderr $msg + usage +} + +for {set i 0} {$i<[llength $argv]} {incr i} { + set x [lindex $argv $i] + if {[string index $x 0]!="-"} {cmdlineerr "illegal argument: $x"} + set x [string trimleft $x -] + incr i + if {$i>=[llength $argv]} {cmdlineerr "no argument on --$x"} + set a [lindex $argv $i] + switch -- $x { + afl-bin {set AFLBIN $a} + afl-data {set AFLDATA $a} + fuzzershell {set FUZZERSHELL $a} + o {set OUTFILE $a} + default {cmdlineerr "unknown option: --$x"} + } +} +proc checkarg {varname option} { + set val [set ::$varname] + if {$val==""} {cmdlineerr "required option missing: --$option"} +} +checkarg AFLBIN afl-bin +checkarg AFLDATA afl-data +checkarg FUZZERSHELL fuzzershell +checkarg OUTFILE o +proc checkexec {x} { + if {![file exec $x]} {cmdlineerr "cannot find $x"} +} +checkexec $AFLBIN/afl-cmin +checkexec $AFLBIN/afl-tmin +checkexec $FUZZERSHELL +proc checkdir {x} { + if {![file isdir $x]} {cmdlineerr "no such directory: $x"} +} +checkdir $AFLDATA/queue + +proc progress {msg} { + puts "******** $msg" + flush stdout +} +progress "mkdir tmp1 tmp2" +file mkdir tmp1 tmp2 +progress "copying test cases from $AFLDATA into tmp1..." +set n 0 +foreach file [glob -nocomplain $AFLDATA/queue/id:*] { + incr n + file copy $file tmp1/$n +} +foreach file [glob -nocomplain $AFLDATA/crash*/id:*] { + incr n + file copy $file tmp1/$n +} +progress "total $n files copied." +progress "running: $AFLBIN/afl-cmin -i tmp1 -o tmp2 $FUZZERSHELL" +exec $AFLBIN/afl-cmin -i tmp1 -o tmp2 $FUZZERSHELL >&@ stdout +progress "afl-cmin complete." +# +# Experiments show that running afl-tmin is too slow for this application. +# And it doesn't really make the test cases that much smaller. So let's +# just skip it. +# +# foreach file [glob tmp2/*] { +# progress "$AFLBIN/afl-tmin -i $file -o tmp3/[file tail $file] $FUZZERSHELL" +# exec $AFLBIN/afl-tmin -i $file -o tmp3/[file tail $file] \ +# $FUZZERSHELL >&@ stdout +# } +progress "generating final output into $OUTFILE" +set out [open $OUTFILE wb] +puts $out "# Test data for use with fuzzershell. Automatically +# generated using $argv0. This file contains binary data +#" +set n 0 +foreach file [glob tmp2/*] { + incr n + puts -nonewline $out "/****<$n>****/" + set in [open $file rb] + puts -nonewline $out [read $in] + close $in +} +close $out +progress "done. $n test cases written to $OUTFILE" +progress "clean-up..." +file delete -force tmp1 +progress "culled test cases left in the tmp2 directory" diff --git a/test/multiplex4.test b/test/multiplex4.test index 9c304c3..2caebea 100644 --- a/test/multiplex4.test +++ b/test/multiplex4.test @@ -59,6 +59,14 @@ do_test multiplex4-1.1 { multiplex_file_list mx4test } {mx4test.db} +# NB: The PRAGMA multiplex_truncate command is implemented using the +# SQLITE_FCNTL_PRAGMA file-control... +# +# EVIDENCE-OF: R-12238-55120 Whenever a PRAGMA statement is parsed, an +# SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file +# object corresponding to the database file to which the pragma +# statement refers. +# do_test multiplex4-1.2 { db eval {PRAGMA multiplex_truncate} } {on} @@ -84,6 +92,16 @@ do_test multiplex4-1.9 { db eval {PRAGMA multiplex_truncate=0} } {off} +# EVIDENCE-OF: R-26188-08449 If the SQLITE_FCNTL_PRAGMA file control +# returns SQLITE_OK, then the parser assumes that the VFS has handled +# the PRAGMA itself and the parser generates a no-op prepared statement +# if result string is NULL, or that returns a copy of the result string +# if the string is non-NULL. +# +do_test multiplex4-1.9-explain { + db eval {EXPLAIN PRAGMA multiplex_truncate=0;} +} {/String8 \d \d \d off/} + do_test multiplex4-1.10 { db eval { INSERT INTO t1(x) VALUES(randomblob(250000)); diff --git a/test/null.test b/test/null.test index f3782a7..e8eeb97 100644 --- a/test/null.test +++ b/test/null.test @@ -278,6 +278,23 @@ do_test null-8.15 { } } {1} +do_execsql_test null-9.1 { + CREATE TABLE t5(a, b, c); + CREATE UNIQUE INDEX t5ab ON t5(a, b); + + INSERT INTO t5 VALUES(1, NULL, 'one'); + INSERT INTO t5 VALUES(1, NULL, 'i'); + INSERT INTO t5 VALUES(NULL, 'x', 'two'); + INSERT INTO t5 VALUES(NULL, 'x', 'ii'); +} + +do_execsql_test null-9.2 { + SELECT * FROM t5 WHERE a = 1 AND b IS NULL; +} {1 {} one 1 {} i} + +do_execsql_test null-9.3 { + SELECT * FROM t5 WHERE a IS NULL AND b = 'x'; +} {{} x two {} x ii} finish_test diff --git a/test/orderby1.test b/test/orderby1.test index 6674e32..3e785c5 100644 --- a/test/orderby1.test +++ b/test/orderby1.test @@ -463,6 +463,9 @@ do_execsql_test 5.1 { do_execsql_test 5.2 { SELECT 5 UNION ALL SELECT 3 ORDER BY 1 } {3 5} +do_execsql_test 5.3 { + SELECT 986 AS x GROUP BY X ORDER BY X +} {986} # The following test (originally derived from a single test within fuzz.test) # verifies that a PseudoTable cursor is not closed prematurely in a deeply @@ -495,5 +498,34 @@ do_execsql_test 7.0 { SELECT * FROM t7 WHERE a=?1 ORDER BY rowid; } {~/ORDER BY/} +#------------------------------------------------------------------------- +# Test a partial sort large enough to cause the sorter to spill data +# to disk. +# +reset_db +do_execsql_test 8.0 { + PRAGMA cache_size = 5; + CREATE TABLE t1(a, b); + CREATE INDEX i1 ON t1(a); +} + +do_eqp_test 8.1 { + SELECT * FROM t1 ORDER BY a, b; +} { + 0 0 0 {SCAN TABLE t1 USING INDEX i1} + 0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY} +} + +do_execsql_test 8.2 { + WITH cnt(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000 + ) + INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt; +} + +do_test 8.3 { + db eval { SELECT * FROM t1 ORDER BY a, b } { incr res $a } + set res +} 5000 finish_test diff --git a/test/pagesize.test b/test/pagesize.test index 0eebbbb..8800530 100644 --- a/test/pagesize.test +++ b/test/pagesize.test @@ -216,4 +216,22 @@ foreach PGSZ {512 2048 4096 8192} { } [list $PGSZ $PGSZ] } +reset_db +do_execsql_test pagesize-3.1 { + BEGIN; + SELECT * FROM sqlite_master; + PRAGMA page_size=2048; + PRAGMA main.page_size; +} {1024} +do_execsql_test pagesize-3.2 { + CREATE TABLE t1(x); + COMMIT; +} +do_execsql_test pagesize-3.3 { + BEGIN; + PRAGMA page_size = 2048; + COMMIT; + PRAGMA main.page_size; +} {1024} + finish_test diff --git a/test/pragma.test b/test/pragma.test index 09b9b6c..587a03c 100644 --- a/test/pragma.test +++ b/test/pragma.test @@ -51,6 +51,30 @@ ifcapable !pragma { return } +# Capture the output of a pragma in a TEMP table. +# +proc capture_pragma {db tabname sql} { + $db eval "DROP TABLE IF EXISTS temp.$tabname" + set once 1 + $db eval $sql x { + if {$once} { + set once 0 + set ins "INSERT INTO $tabname VALUES" + set crtab "CREATE TEMP TABLE $tabname " + set sep "(" + foreach col $x(*) { + append ins ${sep}\$x($col) + append crtab ${sep}\"$col\" + set sep , + } + append ins ) + append crtab ) + $db eval $crtab + } + $db eval $ins + } +} + # Delete the preexisting database to avoid the special setup # that the "all.test" script does. # @@ -59,7 +83,11 @@ delete_file test.db test.db-journal delete_file test3.db test3.db-journal sqlite3 db test.db; set DB [sqlite3_connection_pointer db] - +# EVIDENCE-OF: R-24197-42751 PRAGMA database.cache_size; PRAGMA +# database.cache_size = pages; PRAGMA database.cache_size = -kibibytes; +# Query or change the suggested maximum number of database disk pages +# that SQLite will hold in memory at once per open database file. +# ifcapable pager_pragmas { set DFLT_CACHE_SZ [db one {PRAGMA default_cache_size}] set TEMP_CACHE_SZ [db one {PRAGMA temp.default_cache_size}] @@ -71,6 +99,8 @@ do_test pragma-1.1 { } } [list $DFLT_CACHE_SZ $DFLT_CACHE_SZ 2] do_test pragma-1.2 { + # EVIDENCE-OF: R-42059-47211 If the argument N is positive then the + # suggested cache size is set to N. execsql { PRAGMA synchronous=OFF; PRAGMA cache_size=1234; @@ -189,6 +219,24 @@ do_test pragma-1.14 { PRAGMA synchronous; } } {2} +do_test pragma-1.14.1 { + execsql { + PRAGMA synchronous=4; + PRAGMA synchronous; + } +} {0} +do_test pragma-1.14.2 { + execsql { + PRAGMA synchronous=3; + PRAGMA synchronous; + } +} {0} +do_test pragma-1.14.3 { + execsql { + PRAGMA synchronous=10; + PRAGMA synchronous; + } +} {2} } ;# ifcapable pager_pragmas # Test turning "flag" pragmas on and off. @@ -620,9 +668,10 @@ ifcapable {foreignkey} { } } {} do_test pragma-6.4 { - execsql { + capture_pragma db out { pragma index_list(t3); } + db eval {SELECT seq, "name", "unique" FROM out ORDER BY seq} } {0 sqlite_autoindex_t3_1 1} } ifcapable {!foreignkey} { @@ -631,9 +680,43 @@ ifcapable {!foreignkey} { do_test pragma-6.5.1 { execsql { CREATE INDEX t3i1 ON t3(a,b); + } + capture_pragma db out { pragma index_info(t3i1); } + db eval {SELECT seqno, cid, name FROM out ORDER BY seqno} } {0 0 a 1 1 b} + +# EVIDENCE-OF: R-23114-21695 The auxiliary index-columns are not shown +# by the index_info pragma, but they are listed by the index_xinfo +# pragma. +# +do_test pragma-6.5.1b { + capture_pragma db out {PRAGMA index_xinfo(t3i1)} + db eval {SELECT seqno, cid, name FROM out ORDER BY seqno} +} {0 0 a 1 1 b 2 -1 {}} + + +# EVIDENCE-OF: R-62725-03366 PRAGMA database.index_info(index-name); +# This pragma returns one row for each key column in the named index. +# +# (The first column of output from PRAGMA index_info is...) +# EVIDENCE-OF: R-34186-52914 The rank of the column within the index. (0 +# means left-most.) +# +# (The second column of output from PRAGMA index_info is...) +# EVIDENCE-OF: R-65019-08383 The rank of the column within the table +# being indexed. +# +# (The third column of output from PRAGMA index_info is...) +# EVIDENCE-OF: R-09773-34266 The name of the column being indexed. +# +do_execsql_test pragma-6.5.1c { + CREATE INDEX t3i2 ON t3(b,a); + PRAGMA index_info='t3i2'; + DROP INDEX t3i2; +} {0 1 b 1 0 a} + do_test pragma-6.5.2 { execsql { pragma index_info(t3i1_bogus); @@ -676,8 +759,10 @@ do_test pragma-6.7 { four REAL DEFAULT X'abcdef', five DEFAULT CURRENT_TIME ); - PRAGMA table_info(test_table); } + capture_pragma db out {PRAGMA table_info(test_table)} + db eval {SELECT cid, "name", type, "notnull", dflt_value, pk FROM out + ORDER BY cid} } [concat \ {0 one INT 1 -1 0} \ {1 two text 0 {} 0} \ @@ -685,18 +770,30 @@ do_test pragma-6.7 { {3 four REAL 0 X'abcdef' 0} \ {4 five {} 0 CURRENT_TIME 0} \ ] +do_test pragma-6.8 { + execsql { + CREATE TABLE t68(a,b,c,PRIMARY KEY(a,b,a,c)); + PRAGMA table_info(t68); + } +} [concat \ + {0 a {} 0 {} 1} \ + {1 b {} 0 {} 2} \ + {2 c {} 0 {} 4} \ +] } ;# ifcapable schema_pragmas # Miscellaneous tests # ifcapable schema_pragmas { +# EVIDENCE-OF: R-63500-32024 PRAGMA database.index_list(table-name); +# This pragma returns one row for each index associated with the given +# table. do_test pragma-7.1.1 { # Make sure a pragma knows to read the schema if it needs to db close sqlite3 db test.db - execsql { - pragma index_list(t3); - } -} {0 t3i1 0 1 sqlite_autoindex_t3_1 1} + capture_pragma db out "PRAGMA index_list(t3)" + db eval {SELECT name, "origin" FROM out ORDER BY name DESC} +} {t3i1 c sqlite_autoindex_t3_1 u} do_test pragma-7.1.2 { execsql { pragma index_list(t3_bogus); @@ -1281,18 +1378,23 @@ ifcapable pager_pragmas { db close forcedelete test.db sqlite3 db test.db - + + # EVIDENCE-OF: R-13905-26312 PRAGMA database.page_count; Return the + # total number of pages in the database file. + # do_test pragma-14.1 { execsql { pragma auto_vacuum = 0 } - execsql { pragma page_count } - } {0} + execsql { pragma page_count; pragma main.page_count } + } {0 0} do_test pragma-14.2 { execsql { CREATE TABLE abc(a, b, c); PRAGMA page_count; + PRAGMA main.page_count; + PRAGMA temp.page_count; } - } {2} + } {2 2 0} do_test pragma-14.2uc { execsql {pragma PAGE_COUNT} } {2} @@ -1701,23 +1803,90 @@ do_test 23.1 { CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d); CREATE INDEX i1 ON t1(b,c); CREATE INDEX i2 ON t1(c,d); + CREATE INDEX i2x ON t1(d COLLATE nocase, c DESC); CREATE TABLE t2(x INTEGER REFERENCES t1); } db2 eval {SELECT name FROM sqlite_master} -} {t1 i1 i2 t2} -do_test 23.2 { +} {t1 i1 i2 i2x t2} +do_test 23.2a { db eval { DROP INDEX i2; CREATE INDEX i2 ON t1(c,d,b); } - db2 eval {PRAGMA index_info(i2)} -} {0 2 c 1 3 d 2 1 b} + capture_pragma db2 out {PRAGMA index_info(i2)} + db2 eval {SELECT cid, name, '|' FROM out ORDER BY seqno} +} {2 c | 3 d | 1 b |} + +# EVIDENCE-OF: R-44874-46325 PRAGMA database.index_xinfo(index-name); +# This pragma returns information about every column in an index. +# +# EVIDENCE-OF: R-45970-35618 Unlike this index_info pragma, this pragma +# returns information about every column in the index, not just the key +# columns. +# +do_test 23.2b { + capture_pragma db2 out {PRAGMA index_xinfo(i2)} + db2 eval {SELECT cid, name, "desc", coll, "key", '|' FROM out ORDER BY seqno} +} {2 c 0 BINARY 1 | 3 d 0 BINARY 1 | 1 b 0 BINARY 1 | -1 {} 0 BINARY 0 |} + +# (The first column of output from PRAGMA index_xinfo is...) +# EVIDENCE-OF: R-00197-14279 The rank of the column within the index. (0 +# means left-most. Key columns come before auxiliary columns.) +# +# (The second column of output from PRAGMA index_xinfo is...) +# EVIDENCE-OF: R-40889-06838 The rank of the column within the table +# being indexed, or -1 if the index-column is the rowid of the table +# being indexed. +# +# (The third column of output from PRAGMA index_xinfo is...) +# EVIDENCE-OF: R-22751-28901 The name of the column being indexed, or +# NULL if the index-column is the rowid of the table being indexed. +# +# (The fourth column of output from PRAGMA index_xinfo is...) +# EVIDENCE-OF: R-11847-09179 1 if the index-column is sorted in reverse +# (DESC) order by the index and 0 otherwise. +# +# (The fifth column of output from PRAGMA index_xinfo is...) +# EVIDENCE-OF: R-15313-19540 The name for the collating sequence used to +# compare values in the index-column. +# +# (The sixth column of output from PRAGMA index_xinfo is...) +# EVIDENCE-OF: R-14310-64553 1 if the index-column is a key column and 0 +# if the index-column is an auxiliary column. +# +do_test 23.2c { + db2 eval {PRAGMA index_xinfo(i2)} +} {0 2 c 0 BINARY 1 1 3 d 0 BINARY 1 2 1 b 0 BINARY 1 3 -1 {} 0 BINARY 0} +do_test 23.2d { + db2 eval {PRAGMA index_xinfo(i2x)} +} {0 3 d 0 nocase 1 1 2 c 1 BINARY 1 2 -1 {} 0 BINARY 0} + +# EVIDENCE-OF: R-63500-32024 PRAGMA database.index_list(table-name); +# This pragma returns one row for each index associated with the given +# table. +# +# (The first column of output from PRAGMA index_list is...) +# EVIDENCE-OF: R-02753-24748 A sequence number assigned to each index +# for internal tracking purposes. +# +# (The second column of output from PRAGMA index_list is...) +# EVIDENCE-OF: R-35496-03635 The name of the index. +# +# (The third column of output from PRAGMA index_list is...) +# EVIDENCE-OF: R-57301-64506 "1" if the index is UNIQUE and "0" if not. +# +# (The fourth column of output from PRAGMA index_list is...) +# EVIDENCE-OF: R-36609-39554 "c" if the index was created by a CREATE +# INDEX statement, "u" if the index was created by a UNIQUE constraint, +# or "pk" if the index was created by a PRIMARY KEY constraint. +# do_test 23.3 { db eval { CREATE INDEX i3 ON t1(d,b,c); } - db2 eval {PRAGMA index_list(t1)} -} {0 i3 0 1 i2 0 2 i1 0} + capture_pragma db2 out {PRAGMA index_list(t1)} + db2 eval {SELECT seq, name, "unique", origin, '|' FROM out ORDER BY seq} +} {0 i3 0 c | 1 i2 0 c | 2 i2x 0 c | 3 i1 0 c |} do_test 23.4 { db eval { ALTER TABLE t1 ADD COLUMN e; diff --git a/test/pragma2.test b/test/pragma2.test index 0dbc977..3ade8c1 100644 --- a/test/pragma2.test +++ b/test/pragma2.test @@ -39,6 +39,10 @@ delete_file test3.db test3.db-journal sqlite3 db test.db; set DB [sqlite3_connection_pointer db] db eval {PRAGMA auto_vacuum=0} + +# EVIDENCE-OF: R-17887-14874 PRAGMA database.freelist_count; Return the +# number of unused pages in the database file. +# do_test pragma2-1.1 { execsql { PRAGMA freelist_count; diff --git a/test/printf.test b/test/printf.test index 7322272..6103d8a 100644 --- a/test/printf.test +++ b/test/printf.test @@ -472,6 +472,18 @@ do_test printf-1.16.7 { sqlite3_mprintf_int {abc: (%#6d) (%#6x) (%#6o) :xyz}\ 0xff676981 0xff676981 0xff676981 } {abc: (-9999999) (0xff676981) (037731664601) :xyz} +do_test printf-1.17.1 { + sqlite3_mprintf_int {abd: %2147483647d %2147483647x %2147483647o} 1 1 1 +} {} +do_test printf-1.17.2 { + sqlite3_mprintf_int {abd: %*d %x} 2147483647 1 1 +} {} +do_test printf-1.17.3 { + sqlite3_mprintf_int {abd: %*d %x} -2147483648 1 1 +} {abd: 1 1} +do_test printf-1.17.4 { + sqlite3_mprintf_int {abd: %.2147483648d %x %x} 1 1 1 +} {/.*/} do_test printf-2.1.1.1 { sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 0.001 } {abc: (0.0) :xyz} @@ -526,6 +538,9 @@ do_test printf-2.1.2.8 { do_test printf-2.1.2.9 { sqlite3_mprintf_double {abc: %d %d (%1.1g) :xyz} 1 1 1.0e-20 } {abc: 1 1 (1e-20) :xyz} +do_test printf-2.1.2.10 { + sqlite3_mprintf_double {abc: %*.*f} 2000000000 1000000000 1.0e-20 +} {abc: } do_test printf-2.1.3.1 { sqlite3_mprintf_double {abc: (%*.*f) :xyz} 1 1 1.0 } {abc: (1.0) :xyz} @@ -3466,6 +3481,15 @@ do_test printf-3.5 { do_test printf-3.6 { sqlite3_mprintf_str {%d %d A String: (%-30s)} 1 2 {This is the string} } [format {%d %d A String: (%-30s)} 1 2 {This is the string}] +do_test printf-3.7 { + sqlite3_mprintf_str {%d A String: (%*s)} 1 2147483647 {This is the string} +} [] +do_test printf-3.8 { + sqlite3_mprintf_str {%d A String: (%*s)} 1 -2147483648 {This is the string} +} {1 A String: (This is the string)} +do_test printf-3.9 { + sqlite3_mprintf_str {%d A String: (%.*s)} 1 -2147483648 {This is the string} +} {1 A String: (This is the string)} do_test snprintf-3.11 { sqlite3_snprintf_str 2 {x%d %d %s} 10 10 {This is the string} } {x} @@ -3685,6 +3709,9 @@ do_test printf-13.5 { do_test printf-13.6 { sqlite3_mprintf_hexdouble %.20f fff8000000000000 } {NaN} +do_test printf-13.7 { + sqlite3_mprintf_hexdouble %2147483648.10000f 4693b8b5b5056e17 +} {/100000000000000000000000000000000.00/} do_test printf-14.1 { sqlite3_mprintf_str {abc-%y-123} 0 0 {not used} diff --git a/test/printf2.test b/test/printf2.test index 21deeb7..fb031bd 100644 --- a/test/printf2.test +++ b/test/printf2.test @@ -58,6 +58,9 @@ do_execsql_test printf2-1.10 { do_execsql_test printf2-1.11 { SELECT printf('%lld%n',314159.2653,'hi'); } {314159} +do_execsql_test printf2-1.12 { + SELECT printf('%n',0); +} {{}} # EVIDENCE-OF: R-17002-27534 The %z format is interchangeable with %s. # diff --git a/test/rdonly.test b/test/rdonly.test index 938cc78..404c613 100644 --- a/test/rdonly.test +++ b/test/rdonly.test @@ -32,6 +32,11 @@ do_test rdonly-1.1 { SELECT * FROM t1; } } {1} + +# EVIDENCE-OF: R-29639-16887 The sqlite3_db_readonly(D,N) interface +# returns 1 if the database N of connection D is read-only, 0 if it is +# read/write, or -1 if N is not the name of a database on connection D. +# do_test rdonly-1.1.1 { sqlite3_db_readonly db main } {0} diff --git a/test/releasetest.tcl b/test/releasetest.tcl index 746fc9b..a429d83 100644 --- a/test/releasetest.tcl +++ b/test/releasetest.tcl @@ -14,16 +14,19 @@ optional) are: --config CONFIGNAME (Run only CONFIGNAME) --quick (Run "veryquick.test" only) --veryquick (Run "make smoketest" only) + --msvc (Use MSVC as the compiler) --buildonly (Just build testfixture - do not run) --dryrun (Print what would have happened) --info (Show diagnostic info) + --with-tcl=DIR (Use TCL build at DIR) The default value for --srcdir is the parent of the directory holding this script. The script determines the default value for --platform using the -$tcl_platform(os) and $tcl_platform(machine) variables. Supported -platforms are "Linux-x86", "Linux-x86_64" and "Darwin-i386". +$tcl_platform(os) and $tcl_platform(machine) variables. Supported +platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386", +"Darwin-x86_64", "Windows NT-intel", and "Windows NT-amd64". Every test begins with a fresh run of the configure script at the top of the SQLite source tree. @@ -108,6 +111,13 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_STAT4 -DSQLITE_MAX_ATTACHED=125 } + "Fast-One" { + -O6 + -DSQLITE_ENABLE_FTS4=1 + -DSQLITE_ENABLE_RTREE=1 + -DSQLITE_ENABLE_STAT4 + -DSQLITE_MAX_ATTACHED=125 + } "Device-One" { -O2 -DSQLITE_DEBUG=1 @@ -197,6 +207,8 @@ array set ::Configs [strip_comments { Fail2 {-O0} Fail3 {-O0} Fail4 {-O0} + FuzzFail1 {-O0} + FuzzFail2 {-O0} }] array set ::Platforms [strip_comments { @@ -212,6 +224,7 @@ array set ::Platforms [strip_comments { "No-lookaside" test "Devkit" test "Sanitize" {QUICKTEST_OMIT=func4.test,nan.test test} + "Fast-One" fuzzoomtest "Valgrind" valgrindtest "Default" "threadtest fulltest" "Device-One" fulltest @@ -238,6 +251,10 @@ array set ::Platforms [strip_comments { "Default" "mptest fulltestonly" "Have-Not" test } + "Windows NT-amd64" { + "Default" "mptest fulltestonly" + "Have-Not" test + } # The Failure-Detection platform runs various tests that deliberately # fail. This is used as a test of this script to verify that this script @@ -249,6 +266,8 @@ array set ::Platforms [strip_comments { Fail2 "TEST_FAILURE=2 valgrindtest" Fail3 "TEST_FAILURE=3 valgrindtest" Fail4 "TEST_FAILURE=4 test" + FuzzFail1 "TEST_FAILURE=5 test" + FuzzFail2 "TEST_FAILURE=5 valgrindtest" } }] @@ -296,6 +315,13 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} { set errmsg $msg } } + if {[regexp {fatal error +(.*)} $line all msg]} { + incr ::NERRCASE + if {$rc==0} { + set rc 1 + set errmsg $msg + } + } if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} { incr ::NERRCASE if {$rc==0} { @@ -314,7 +340,13 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} { } } close $fd - if {!$seen} { + if {$::BUILDONLY} { + if {$rc==0} { + set errmsg "Build complete" + } else { + set errmsg "Build failed" + } + } elseif {!$seen} { set rc 1 set errmsg "Test did not complete" if {[file readable core]} { @@ -329,10 +361,10 @@ proc run_test_suite {name testtarget config} { # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but # CFLAGS is only passed to gcc. # - set cflags "-g" + set cflags [expr {$::MSVC ? "-Zi" : "-g"}] set opts "" set title ${name}($testtarget) - set configOpts "" + set configOpts $::WITHTCL regsub -all {#[^\n]*\n} $config \n config foreach arg $config { @@ -349,7 +381,14 @@ proc run_test_suite {name testtarget config} { set cflags [join $cflags " "] set opts [join $opts " "] - append opts " -DSQLITE_NO_SYNC=1 -DHAVE_USLEEP" + append opts " -DSQLITE_NO_SYNC=1" + + # Some configurations already set HAVE_USLEEP; in that case, skip it. + # + if {![regexp { -DHAVE_USLEEP$} $opts] + && ![regexp { -DHAVE_USLEEP[ =]+} $opts]} { + append opts " -DHAVE_USLEEP=1" + } # Set the sub-directory to use. # @@ -390,10 +429,10 @@ proc run_test_suite {name testtarget config} { if {$rc} { puts " FAIL $tm" incr ::NERR - if {$errmsg!=""} {puts " $errmsg"} } else { puts " Ok $tm" } + if {$errmsg!=""} {puts " $errmsg"} } } @@ -401,6 +440,7 @@ proc run_test_suite {name testtarget config} { # the current platform, which may be Windows (via MinGW, etc). # proc configureCommand {opts} { + if {$::MSVC} return [list]; # This is not needed for MSVC. set result [list trace_cmd exec] if {$::tcl_platform(platform)=="windows"} { lappend result sh @@ -414,7 +454,14 @@ proc configureCommand {opts} { # specified targets, compiler flags, and options. # proc makeCommand { targets cflags opts } { - set result [list trace_cmd exec make clean] + set result [list trace_cmd exec] + if {$::MSVC} { + set nmakeDir [file nativename $::SRCDIR] + set nmakeFile [file join $nmakeDir Makefile.msc] + lappend result nmake /f $nmakeFile TOP=$nmakeDir clean + } else { + lappend result make clean + } foreach target $targets { lappend result $target } @@ -443,10 +490,12 @@ proc trace_cmd {args} { proc process_options {argv} { set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]] set ::QUICK 0 + set ::MSVC 0 set ::BUILDONLY 0 set ::DRYRUN 0 set ::EXEC exec set ::TRACE 0 + set ::WITHTCL {} set config {} set platform $::tcl_platform(os)-$::tcl_platform(machine) @@ -476,6 +525,10 @@ proc process_options {argv} { set config [lindex $argv $i] } + -msvc { + set ::MSVC 1 + } + -buildonly { set ::BUILDONLY 1 } @@ -494,6 +547,7 @@ proc process_options {argv} { puts " --platform [list $platform]" puts " --config [list $config]" if {$::QUICK} {puts " --quick"} + if {$::MSVC} {puts " --msvc"} if {$::BUILDONLY} {puts " --buildonly"} if {$::DRYRUN} {puts " --dryrun"} if {$::TRACE} {puts " --trace"} @@ -507,7 +561,19 @@ proc process_options {argv} { } exit } - -g - + + -g { + if {$::MSVC} { + lappend ::EXTRACONFIG -Zi + } else { + lappend ::EXTRACONFIG [lindex $argv $i] + } + } + + -with-tcl=* { + set ::WITHTCL -$x + } + -D* - -O* - -enable-* - @@ -547,6 +613,7 @@ proc process_options {argv} { puts -nonewline "Flags:" if {$::DRYRUN} {puts -nonewline " --dryrun"} if {$::BUILDONLY} {puts -nonewline " --buildonly"} + if {$::MSVC} {puts -nonewline " --msvc"} switch -- $::QUICK { 1 {puts -nonewline " --quick"} 2 {puts -nonewline " --veryquick"} @@ -570,12 +637,20 @@ proc main {argv} { set ::SQLITE_VERSION {} set STARTTIME [clock seconds] foreach {zConfig target} $::CONFIGLIST { + if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target + || "valgrindtest" in $target)} { + puts "Skipping $zConfig / $target for MSVC..." + continue + } if {$target ne "checksymbols"} { switch -- $::QUICK { 1 {set target test} 2 {set target smoketest} } - if {$::BUILDONLY} {set target testfixture} + if {$::BUILDONLY} { + set target testfixture + if {$::MSVC} {append target .exe} + } } set config_options [concat $::Configs($zConfig) $::EXTRACONFIG] @@ -586,10 +661,11 @@ proc main {argv} { # it and run veryquick.test. If it did not include the SQLITE_DEBUG option # add it and run veryquick.test. if {$target!="checksymbols" && $target!="valgrindtest" - && !$::BUILDONLY && $::QUICK<2} { + && $target!="fuzzoomtest" && !$::BUILDONLY && $::QUICK<2} { set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*] set xtarget $target regsub -all {fulltest[a-z]*} $xtarget test xtarget + regsub -all {fuzzoomtest} $xtarget fuzztest xtarget if {$debug_idx < 0} { incr NTEST append config_options " -DSQLITE_DEBUG=1" diff --git a/test/resolver01.test b/test/resolver01.test index 7d95a21..59bb3c0 100644 --- a/test/resolver01.test +++ b/test/resolver01.test @@ -11,10 +11,12 @@ # # This file tests features of the name resolver (the component that # figures out what identifiers in the SQL statement refer to) that -# were fixed by ticket [2500cdb9be] +# were fixed by ticket [2500cdb9be]. # # See also tickets [1c69be2daf] and [f617ea3125] from 2013-08-14. # +# Also a fuzzer-discovered problem on 2015-04-23. +# set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -201,6 +203,12 @@ do_execsql_test resolver01-6.3 { GROUP BY lower(name); } {1 {} 1 {}} +do_execsql_test resolver01-7.1 { + SELECT 2 AS x WHERE (SELECT x AS y WHERE 3>y); +} {2} +do_execsql_test resolver01-7.2 { + SELECT 2 AS x WHERE (SELECT x AS y WHERE 1>y); +} {} diff --git a/test/select1.test b/test/select1.test index 875c87c..4d6c07f 100644 --- a/test/select1.test +++ b/test/select1.test @@ -307,6 +307,9 @@ do_test select1-4.4 { set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg] lappend v $msg } {1 {misuse of aggregate: min()}} +do_catchsql_test select1-4.5 { + INSERT INTO test1(f1) SELECT f1 FROM test1 ORDER BY min(f1); +} {1 {misuse of aggregate: min()}} # The restriction not allowing constants in the ORDER BY clause # has been removed. See ticket #1768 @@ -1072,5 +1075,10 @@ if {[db one {PRAGMA locking_mode}]=="normal"} { do_test select1-16.1 { catchsql {SELECT 1 FROM (SELECT *)} } {1 {no tables specified}} + +# 2015-04-17: assertion fix. +do_catchsql_test select1-16.2 { + SELECT 1 FROM sqlite_master LIMIT 1,#1; +} {1 {near "#1": syntax error}} finish_test diff --git a/test/select4.test b/test/select4.test index 8fc200d..c0f88a1 100644 --- a/test/select4.test +++ b/test/select4.test @@ -105,6 +105,10 @@ ifcapable subquery { } } {0 1 2 2 3 3 3 3} } + +# EVIDENCE-OF: R-02644-22131 In a compound SELECT statement, only the +# last or right-most simple SELECT may have an ORDER BY clause. +# do_test select4-1.3 { set v [catch {execsql { SELECT DISTINCT log FROM t1 ORDER BY log @@ -114,6 +118,10 @@ do_test select4-1.3 { }} msg] lappend v $msg } {1 {ORDER BY clause should come after UNION ALL not before}} +do_catchsql_test select4-1.4 { + SELECT (VALUES(0) INTERSECT SELECT(0) UNION SELECT(0) ORDER BY 1 UNION + SELECT 0 UNION SELECT 0 ORDER BY 1); +} {1 {ORDER BY clause should come after UNION not before}} # Union operator # @@ -144,6 +152,15 @@ do_test select4-2.3 { }} msg] lappend v $msg } {1 {ORDER BY clause should come after UNION not before}} +do_test select4-2.4 { + set v [catch {execsql { + SELECT 0 ORDER BY (SELECT 0) UNION SELECT 0; + }} msg] + lappend v $msg +} {1 {ORDER BY clause should come after UNION not before}} +do_execsql_test select4-2.5 { + SELECT 123 AS x ORDER BY (SELECT x ORDER BY 1); +} {123} # Except operator # @@ -260,6 +277,16 @@ do_test select4-4.3 { }} msg] lappend v $msg } {1 {ORDER BY clause should come after INTERSECT not before}} +do_catchsql_test select4-4.4 { + SELECT 3 IN ( + SELECT 0 ORDER BY 1 + INTERSECT + SELECT 1 + INTERSECT + SELECT 2 + ORDER BY 1 + ); +} {1 {ORDER BY clause should come after INTERSECT not before}} # Various error messages while processing UNION or INTERSECT # @@ -795,6 +822,11 @@ do_test select4-11.15 { SELECT x FROM t2 } } {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} +do_test select4-11.16 { + catchsql { + INSERT INTO t2(rowid) VALUES(2) UNION SELECT 3,4 UNION SELECT 5,6 ORDER BY 1; + } +} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}} do_test select4-12.1 { sqlite3 db2 :memory: @@ -859,5 +891,23 @@ do_execsql_test select4-14.8 { do_execsql_test select4-14.9 { SELECT * FROM t14 UNION ALL VALUES(3,2,1),(2,3,1),(1,2,3),(2,1,3); } {1 2 3 4 5 6 3 2 1 2 3 1 1 2 3 2 1 3} +do_execsql_test select4-14.10 { + SELECT (VALUES(1),(2),(3),(4)) +} {1} +do_execsql_test select4-14.11 { + SELECT (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) +} {1} +do_execsql_test select4-14.12 { + VALUES(1) UNION VALUES(2); +} {1 2} +do_execsql_test select4-14.13 { + VALUES(1),(2),(3) EXCEPT VALUES(2); +} {1 3} +do_execsql_test select4-14.14 { + VALUES(1),(2),(3) EXCEPT VALUES(1),(3); +} {2} +do_execsql_test select4-14.15 { + SELECT * FROM (SELECT 123), (SELECT 456) ON likely(0 OR 1) OR 0; +} {123 456} finish_test diff --git a/test/select6.test b/test/select6.test index 64a8519..590512a 100644 --- a/test/select6.test +++ b/test/select6.test @@ -557,5 +557,61 @@ do_catchsql_test 10.8 { ) } $err +# 2015-02-09 Ticket [2f7170d73bf9abf80339187aa3677dce3dbcd5ca] +# "misuse of aggregate" error if aggregate column from FROM +# subquery is used in correlated subquery +# +do_execsql_test 11.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(w INT, x INT); + INSERT INTO t1(w,x) + VALUES(1,10),(2,20),(3,30), + (2,21),(3,31), + (3,32); + CREATE INDEX t1wx ON t1(w,x); + + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(w INT, y VARCHAR(8)); + INSERT INTO t2(w,y) VALUES(1,'one'),(2,'two'),(3,'three'),(4,'four'); + CREATE INDEX t2wy ON t2(w,y); + + SELECT cnt, xyz, (SELECT y FROM t2 WHERE w=cnt), '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY cnt, xyz; +} {1 1 one | 2 2 two | 3 3 three |} +do_execsql_test 11.2 { + SELECT cnt, xyz, lower((SELECT y FROM t2 WHERE w=cnt)), '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY cnt, xyz; +} {1 1 one | 2 2 two | 3 3 three |} +do_execsql_test 11.3 { + SELECT cnt, xyz, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + WHERE (SELECT y FROM t2 WHERE w=cnt)!='two' + ORDER BY cnt, xyz; +} {1 1 | 3 3 |} +do_execsql_test 11.4 { + SELECT cnt, xyz, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY lower((SELECT y FROM t2 WHERE w=cnt)); +} {1 1 | 3 3 | 2 2 |} +do_execsql_test 11.5 { + SELECT cnt, xyz, + CASE WHEN (SELECT y FROM t2 WHERE w=cnt)=='two' + THEN 'aaa' ELSE 'bbb' + END, '|' + FROM (SELECT count(*) AS cnt, w AS xyz FROM t1 GROUP BY 2) + ORDER BY +cnt; +} {1 1 bbb | 2 2 aaa | 3 3 bbb |} + +do_execsql_test 11.100 { + DROP TABLE t1; + DROP TABLE t2; + CREATE TABLE t1(x); + CREATE TABLE t2(y, z); + SELECT ( SELECT y FROM t2 WHERE z = cnt ) + FROM ( SELECT count(*) AS cnt FROM t1 ); +} {{}} + finish_test diff --git a/test/selectA.test b/test/selectA.test index 6e593e8..0338338 100644 --- a/test/selectA.test +++ b/test/selectA.test @@ -1375,4 +1375,64 @@ do_execsql_test 4.2.2 { } {/2 . 3 . 4 . 5 . 6 . 7 ./} +proc strip_rnd {explain} { + regexp -all {sqlite_sq_[0123456789ABCDEF]*} $explain sqlite_sq +} + +proc do_same_test {tn q1 args} { + set r2 [strip_rnd [db eval "EXPLAIN $q1"]] + set i 1 + foreach q $args { + set tst [subst -nocommands {strip_rnd [db eval "EXPLAIN $q"]}] + uplevel do_test $tn.$i [list $tst] [list $r2] + incr i + } +} + +do_execsql_test 5.0 { + CREATE TABLE t8(a, b); + CREATE TABLE t9(c, d); +} {} + +do_same_test 5.1 { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY a; +} { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t8.a; +} { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY 1; +} { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY c; +} { + SELECT a, b FROM t8 INTERSECT SELECT c, d FROM t9 ORDER BY t9.c; +} + +do_same_test 5.2 { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY a COLLATE NOCASE +} { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t8.a COLLATE NOCASE +} { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY 1 COLLATE NOCASE +} { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY c COLLATE NOCASE +} { + SELECT a, b FROM t8 UNION SELECT c, d FROM t9 ORDER BY t9.c COLLATE NOCASE +} + +do_same_test 5.3 { + SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY b, c COLLATE NOCASE +} { + SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY 2, 1 COLLATE NOCASE +} { + SELECT a, b FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, a COLLATE NOCASE +} { + SELECT a, b FROM t8 EXCEPT SELECT * FROM t9 ORDER BY t9.d, c COLLATE NOCASE +} { + SELECT * FROM t8 EXCEPT SELECT c, d FROM t9 ORDER BY d, t8.a COLLATE NOCASE +} + +do_catchsql_test 5.4 { + SELECT * FROM t8 UNION SELECT * FROM t9 ORDER BY a+b COLLATE NOCASE +} {1 {1st ORDER BY term does not match any column in the result set}} + + finish_test diff --git a/test/selectE.test b/test/selectE.test index d7592bb..1cabeff 100644 --- a/test/selectE.test +++ b/test/selectE.test @@ -92,4 +92,9 @@ do_test selectE-2.2 { } } {} +do_catchsql_test selectE-3.1 { + SELECT 1 EXCEPT SELECT 2 ORDER BY 1 COLLATE nocase EXCEPT SELECT 3; +} {1 {ORDER BY clause should come after EXCEPT not before}} + + finish_test diff --git a/test/shell1.test b/test/shell1.test index f24b00d..2fda62e 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -406,19 +406,22 @@ do_test shell1-3.11.3 { catchcmd "test.db" ".import FOO BAR BAD" } {1 {Usage: .import FILE TABLE}} -# .indices ?TABLE? Show names of all indices -# If TABLE specified, only show indices for tables +# .indexes ?TABLE? Show names of all indexes +# If TABLE specified, only show indexes for tables # matching LIKE pattern TABLE. do_test shell1-3.12.1 { - catchcmd "test.db" ".indices" + catchcmd "test.db" ".indexes" } {0 {}} do_test shell1-3.12.2 { + catchcmd "test.db" ".indexes FOO" +} {0 {}} +do_test shell1-3.12.2-legacy { catchcmd "test.db" ".indices FOO" } {0 {}} do_test shell1-3.12.3 { # too many arguments - catchcmd "test.db" ".indices FOO BAD" -} {1 {Usage: .indices ?LIKE-PATTERN?}} + catchcmd "test.db" ".indexes FOO BAD" +} {1 {Usage: .indexes ?LIKE-PATTERN?}} # .mode MODE ?TABLE? Set output mode where MODE is one of: # ascii Columns/rows delimited by 0x1F and 0x1E @@ -735,6 +738,9 @@ do_test shell1-4.1 { PRAGMA encoding=UTF16; CREATE TABLE t1(x); INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f'); + CREATE TABLE t3(x,y); + INSERT INTO t3 VALUES(1,null), (2,''), (3,1), + (4,2.25), (5,'hello'), (6,x'807f'); } catchcmd test.db {.dump} } {0 {PRAGMA foreign_keys=OFF; @@ -746,11 +752,18 @@ INSERT INTO "t1" VALUES(1); INSERT INTO "t1" VALUES(2.25); INSERT INTO "t1" VALUES('hello'); INSERT INTO "t1" VALUES(X'807F'); +CREATE TABLE t3(x,y); +INSERT INTO "t3" VALUES(1,NULL); +INSERT INTO "t3" VALUES(2,''); +INSERT INTO "t3" VALUES(3,1); +INSERT INTO "t3" VALUES(4,2.25); +INSERT INTO "t3" VALUES(5,'hello'); +INSERT INTO "t3" VALUES(6,X'807F'); COMMIT;}} # Test the output of ".mode insert" # -do_test shell1-4.2 { +do_test shell1-4.2.1 { catchcmd test.db ".mode insert t1\nselect * from t1;" } {0 {INSERT INTO t1 VALUES(NULL); INSERT INTO t1 VALUES(''); @@ -759,6 +772,39 @@ INSERT INTO t1 VALUES(2.25); INSERT INTO t1 VALUES('hello'); INSERT INTO t1 VALUES(X'807f');}} +# Test the output of ".mode insert" with headers +# +do_test shell1-4.2.2 { + catchcmd test.db ".mode insert t1\n.headers on\nselect * from t1;" +} {0 {INSERT INTO t1(x) VALUES(NULL); +INSERT INTO t1(x) VALUES(''); +INSERT INTO t1(x) VALUES(1); +INSERT INTO t1(x) VALUES(2.25); +INSERT INTO t1(x) VALUES('hello'); +INSERT INTO t1(x) VALUES(X'807f');}} + +# Test the output of ".mode insert" +# +do_test shell1-4.2.3 { + catchcmd test.db ".mode insert t3\nselect * from t3;" +} {0 {INSERT INTO t3 VALUES(1,NULL); +INSERT INTO t3 VALUES(2,''); +INSERT INTO t3 VALUES(3,1); +INSERT INTO t3 VALUES(4,2.25); +INSERT INTO t3 VALUES(5,'hello'); +INSERT INTO t3 VALUES(6,X'807f');}} + +# Test the output of ".mode insert" with headers +# +do_test shell1-4.2.4 { + catchcmd test.db ".mode insert t3\n.headers on\nselect * from t3;" +} {0 {INSERT INTO t3(x,y) VALUES(1,NULL); +INSERT INTO t3(x,y) VALUES(2,''); +INSERT INTO t3(x,y) VALUES(3,1); +INSERT INTO t3(x,y) VALUES(4,2.25); +INSERT INTO t3(x,y) VALUES(5,'hello'); +INSERT INTO t3(x,y) VALUES(6,X'807f');}} + # Test the output of ".mode tcl" # do_test shell1-4.3 { @@ -815,4 +861,61 @@ do_test shell1-4.6 { ";" "$"} 7} +# Test using arbitrary byte data with the shell via standard input/output. +# +do_test shell1-5.0 { + # + # NOTE: Skip NUL byte because it appears to be incompatible with command + # shell argument parsing. + # + for {set i 1} {$i < 256} {incr i} { + # + # NOTE: Due to how the Tcl [exec] command works (i.e. where it treats + # command channels opened for it as textual ones), the carriage + # return character (and on Windows, the end-of-file character) + # cannot be used here. + # + if {$i==0x0D || ($tcl_platform(platform)=="windows" && $i==0x1A)} { + continue + } + set hex [format %02X $i] + set char [subst \\x$hex]; set oldChar $char + set escapes [list] + if {$tcl_platform(platform)=="windows"} { + # + # NOTE: On Windows, we need to escape all the whitespace characters, + # the alarm (\a) character, and those with special meaning to + # the SQLite shell itself. + # + set escapes [list \ + \a \\a \b \\b \t \\t \n \\n \v \\v \f \\f \r \\r \ + " " "\" \"" \" \\\" ' \"'\" \\ \\\\] + } else { + # + # NOTE: On Unix, we need to escape most of the whitespace characters + # and those with special meaning to the SQLite shell itself. + # The alarm (\a), backspace (\b), and carriage-return (\r) + # characters do not appear to require escaping on Unix. For + # the alarm and backspace characters, this is probably due to + # differences in the command shell. For the carriage-return, + # it is probably due to differences in how Tcl handles command + # channel end-of-line translations. + # + set escapes [list \ + \t \\t \n \\n \v \\v \f \\f \ + " " "\" \"" \" \\\" ' \"'\" \\ \\\\] + } + set char [string map $escapes $char] + set x [catchcmdex test.db ".print $char\n"] + set code [lindex $x 0] + set res [lindex $x 1] + if {$code ne "0"} { + error "failed with error: $res" + } + if {$res ne "$oldChar\n"} { + error "failed with byte $hex mismatch" + } + } +} {} + finish_test diff --git a/test/shell4.test b/test/shell4.test index c29faf0..fcb0b2b 100644 --- a/test/shell4.test +++ b/test/shell4.test @@ -12,12 +12,12 @@ # The focus of this file is testing the CLI shell tool. # These tests are specific to the .stats command. # -# $Id: shell4.test,v 1.7 2009/07/17 16:54:48 shaneh Exp $ -# +# 2015-03-19: Added tests for .trace # Test plan: # # shell4-1.*: Basic tests specific to the "stats" command. +# shell4-2.*: Basic tests for ".trace" # set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -113,4 +113,24 @@ SELECT 1; [regexp {Autoindex Inserts} $res] } {1 1 1} +do_test shell4-2.1 { + catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace" +} {1 {Usage: .trace FILE|off}} +do_test shell4-2.2 { + catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace off\n.trace off\n" +} {0 {}} +do_test shell4-2.3 { + catchcmd ":memory:" ".trace stdout\n.trace\n.trace off\n.dump\n" +} {/^1 {PRAGMA.*Usage:.*}$/} +ifcapable trace { +do_test shell4-2.4 { + catchcmd ":memory:" ".trace stdout\nCREATE TABLE t1(x);SELECT * FROM t1;" +} {0 {CREATE TABLE t1(x); +SELECT * FROM t1;}} +do_test shell4-2.5 { + catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace stdout\nSELECT * FROM t1;" +} {0 {SELECT * FROM t1;}} +} + + finish_test diff --git a/test/shell5.test b/test/shell5.test index e22db04..b921acc 100644 --- a/test/shell5.test +++ b/test/shell5.test @@ -405,4 +405,34 @@ SELECT * FROM t5; set x } "0 \{\"test 1\"\x1F,test 2\x1Etest 3\x1Ftest 4\x1E\}" +do_test shell5-4.1 { + forcedelete shell5.csv + set fd [open shell5.csv w] + puts $fd "1,2,3" + puts $fd "4,5" + puts $fd "6,7,8" + close $fd + catchcmd test.db [string trim { +.mode csv +CREATE TABLE t6(a, b, c); +.import shell5.csv t6 + }] + db eval { SELECT * FROM t6 ORDER BY a } +} {1 2 3 4 5 {} 6 7 8} + +do_test shell5-4.2 { + forcedelete shell5.csv + set fd [open shell5.csv w] + puts $fd "1,2,3" + puts $fd "4,5" + puts $fd "6,7,8,9" + close $fd + catchcmd test.db [string trim { +.mode csv +CREATE TABLE t7(a, b, c); +.import shell5.csv t7 + }] + db eval { SELECT * FROM t7 ORDER BY a } +} {1 2 3 4 5 {} 6 7 8} + finish_test diff --git a/test/shrink.test b/test/shrink.test index e03ebee..6cc0786 100644 --- a/test/shrink.test +++ b/test/shrink.test @@ -24,6 +24,9 @@ do_test shrink-1.1 { INSERT INTO t1 VALUES(randomblob(1000000),1); } set ::baseline sqlite3_memory_used + # EVIDENCE-OF: R-58814-63508 The sqlite3_db_release_memory(D) interface + # attempts to free as much heap memory as possible from database + # connection D. sqlite3_db_release_memory db expr {$::baseline > [sqlite3_memory_used]+500000} } {1} diff --git a/test/softheap1.test b/test/softheap1.test index 522e455..07f981e 100644 --- a/test/softheap1.test +++ b/test/softheap1.test @@ -24,6 +24,14 @@ ifcapable !integrityck { return } +# EVIDENCE-OF: R-26343-45930 This pragma invokes the +# sqlite3_soft_heap_limit64() interface with the argument N, if N is +# specified and is a non-negative integer. +# +# EVIDENCE-OF: R-64451-07163 The soft_heap_limit pragma always returns +# the same integer that would be returned by the +# sqlite3_soft_heap_limit64(-1) C-language function. +# do_test softheap1-1.0 { execsql {PRAGMA soft_heap_limit} } [sqlite3_soft_heap_limit -1] diff --git a/test/sort4.test b/test/sort4.test index 7b91361..13d9a59 100644 --- a/test/sort4.test +++ b/test/sort4.test @@ -25,7 +25,20 @@ sqlite3 db test.db # Configure the sorter to use 3 background threads. -db eval {PRAGMA threads=3} +# +# EVIDENCE-OF: R-19249-32353 SQLITE_LIMIT_WORKER_THREADS The maximum +# number of auxiliary worker threads that a single prepared statement +# may start. +# +do_test sort4-init001 { + db eval {PRAGMA threads=5} + sqlite3_limit db SQLITE_LIMIT_WORKER_THREADS -1 +} {5} +do_test sort4-init002 { + sqlite3_limit db SQLITE_LIMIT_WORKER_THREADS 3 + db eval {PRAGMA threads} +} {3} + # Minimum number of seconds to run for. If the value is 0, each test # is run exactly once. Otherwise, tests are repeated until the timeout diff --git a/test/speedtest1.c b/test/speedtest1.c index 8e5b74c..93f7d14 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -12,7 +12,7 @@ static const char zHelp[] = " --explain Like --sqlonly but with added EXPLAIN keywords\n" " --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n" " --incrvacuum Enable incremenatal vacuum mode\n" - " --journalmode M Set the journal_mode to MODE\n" + " --journal M Set the journal_mode to M\n" " --key KEY Set the encryption key to KEY\n" " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" " --nosync Set PRAGMA synchronous=OFF\n" diff --git a/test/sqllimits1.test b/test/sqllimits1.test index 57fc931..39e3aed 100644 --- a/test/sqllimits1.test +++ b/test/sqllimits1.test @@ -250,6 +250,9 @@ do_test sqllimits1-4.10.1 { # Test cases sqllimits1-5.* test that the SQLITE_MAX_LENGTH limit # is enforced. # +# EVIDENCE-OF: R-61987-00541 SQLITE_LIMIT_LENGTH The maximum size of any +# string or BLOB or table row, in bytes. +# db close sqlite3 db test.db set LARGESIZE 99999 @@ -406,6 +409,9 @@ unset strvalue # Test cases sqllimits1-6.* test that the SQLITE_MAX_SQL_LENGTH limit # is enforced. # +# EVIDENCE-OF: R-09808-17554 SQLITE_LIMIT_SQL_LENGTH The maximum length +# of an SQL statement, in bytes. +# do_test sqllimits1-6.1 { sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 50000 set sql "SELECT 1 WHERE 1==1" @@ -567,6 +573,11 @@ do_test sqllimits1-7.7.4 { #-------------------------------------------------------------------- # Test cases sqllimits1-8.* test the SQLITE_MAX_COLUMN limit. # +# EVIDENCE-OF: R-43996-29471 SQLITE_LIMIT_COLUMN The maximum number of +# columns in a table definition or in the result set of a SELECT or the +# maximum number of columns in an index or in an ORDER BY or GROUP BY +# clause. +# set SQLITE_LIMIT_COLUMN 200 sqlite3_limit db SQLITE_LIMIT_COLUMN $SQLITE_LIMIT_COLUMN do_test sqllimits1-8.1 { @@ -670,6 +681,9 @@ do_test sqllimits1-8.11 { # limit is enforced. The limit refers to the number of terms in # the expression. # +# EVIDENCE-OF: R-12723-08526 SQLITE_LIMIT_EXPR_DEPTH The maximum depth +# of the parse tree on any expression. +# if {$SQLITE_MAX_EXPR_DEPTH==0} { puts -nonewline stderr "WARNING: Compile with -DSQLITE_MAX_EXPR_DEPTH to run " puts stderr "tests sqllimits1-9.X" @@ -729,6 +743,9 @@ if 0 { # Test the SQLITE_LIMIT_FUNCTION_ARG limit works. Test case names # match the pattern "sqllimits1-11.*". # +# EVIDENCE-OF: R-59001-45278 SQLITE_LIMIT_FUNCTION_ARG The maximum +# number of arguments on a function. +# for {set max 5} {$max<=$SQLITE_MAX_FUNCTION_ARG} {incr max} { do_test sqllimits1-11.$max.1 { set vals [list] @@ -762,6 +779,9 @@ for {set max 5} {$max<=$SQLITE_MAX_FUNCTION_ARG} {incr max} { #-------------------------------------------------------------------- # Test cases sqllimits1-12.*: Test the SQLITE_MAX_ATTACHED limit. # +# EVIDENCE-OF: R-41778-26203 SQLITE_LIMIT_ATTACHED The maximum number of +# attached databases. +# ifcapable attach { do_test sqllimits1-12.1 { set max $::SQLITE_MAX_ATTACHED @@ -785,6 +805,9 @@ ifcapable attach { # Test cases sqllimits1-13.*: Check that the SQLITE_MAX_VARIABLE_NUMBER # limit works. # +# EVIDENCE-OF: R-42363-29104 SQLITE_LIMIT_VARIABLE_NUMBER The maximum +# index number of any parameter in an SQL statement. +# do_test sqllimits1-13.1 { set max $::SQLITE_MAX_VARIABLE_NUMBER catchsql "SELECT ?[expr {$max+1}] FROM t1" @@ -806,6 +829,9 @@ do_test sqllimits1-13.2 { # implementation by overriding the like() scalar function bypasses # this limitation. # +# EVIDENCE-OF: R-12940-37052 SQLITE_LIMIT_LIKE_PATTERN_LENGTH The +# maximum length of the pattern argument to the LIKE or GLOB operators. +# # These tests check that the limit is not incorrectly applied to # the left-hand-side of the LIKE operator (the string being tested # against the pattern). diff --git a/test/stat.test b/test/stat.test index f0447e4..57c1b9e 100644 --- a/test/stat.test +++ b/test/stat.test @@ -166,8 +166,10 @@ sqlite3 db test.db register_dbstat_vtab db do_execsql_test stat-5.1 { PRAGMA auto_vacuum = OFF; - CREATE VIRTUAL TABLE temp.stat USING dbstat; - CREATE TABLE t1(x); + CREATE TABLE tx(y); + ATTACH ':memory:' AS aux1; + CREATE VIRTUAL TABLE temp.stat USING dbstat(aux1); + CREATE TABLE aux1.t1(x); INSERT INTO t1 VALUES(zeroblob(1513)); INSERT INTO t1 VALUES(zeroblob(1514)); SELECT name, path, pageno, pagetype, ncell, payload, unused, mx_payload @@ -178,4 +180,8 @@ do_execsql_test stat-5.1 { t1 /001+000000 4 overflow 0 1020 0 0 \ ] +do_catchsql_test stat-6.1 { + CREATE VIRTUAL TABLE temp.s2 USING dbstat(mainx); +} {1 {no such database: mainx}} + finish_test diff --git a/test/statfault.test b/test/statfault.test new file mode 100644 index 0000000..ce79e32 --- /dev/null +++ b/test/statfault.test @@ -0,0 +1,45 @@ +# 2015 April 28 +# +# 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. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl +set testprefix statfault + +ifcapable !vtab||!compound { + finish_test + return +} + +register_dbstat_vtab db +do_execsql_test statfault-1 { + CREATE TABLE t1(a, b UNIQUE); + INSERT INTO t1 VALUES(1, randomblob(500)); + INSERT INTO t1 VALUES(randomblob(500), 1); + INSERT INTO t1 VALUES(2, randomblob(250)); + INSERT INTO t1 VALUES(randomblob(250), 2); + CREATE VIRTUAL TABLE sss USING dbstat; +} {} +faultsim_save_and_close + +do_faultsim_test 1 -faults * -prep { + faultsim_restore_and_reopen + register_dbstat_vtab db + execsql { SELECT 1 FROM sqlite_master LIMIT 1 } +} -body { + execsql { SELECT count(*) FROM sss } +} -test { + faultsim_test_result {0 8} +} + + +finish_test diff --git a/test/subquery.test b/test/subquery.test index 93c3f28..06facbb 100644 --- a/test/subquery.test +++ b/test/subquery.test @@ -584,4 +584,14 @@ do_test subquery-7.11 { } {30303} } ;############# Disabled +# 2015-04-21. +# Verify that a memory leak in the table column type and collation analysis +# is plugged. +# +do_execsql_test subquery-8.1 { + CREATE TABLE t8(a TEXT, b INT); + SELECT (SELECT 0 FROM (SELECT * FROM t1)) AS x WHERE x; + SELECT (SELECT 0 FROM (SELECT * FROM (SELECT 0))) AS x WHERE x; +} {} + finish_test diff --git a/test/table.test b/test/table.test index 69f105a..faa9712 100644 --- a/test/table.test +++ b/test/table.test @@ -272,6 +272,25 @@ do_test table-5.2.1 { } } {} +do_test table-5.2.2 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE t0(a,b); + CREATE INDEX t ON t0(a); + PRAGMA writable_schema=ON; + UPDATE sqlite_master SET sql='CREATE TABLE a.b(a UNIQUE'; + BEGIN; + CREATE TABLE t1(x); + ROLLBACK; + DROP TABLE IF EXISTS t99; + } +} {} +db close +forcedelete test.db +sqlite3 db test.db + # Make sure an EXPLAIN does not really create a new table # do_test table-5.3 { diff --git a/test/tclsqlite.test b/test/tclsqlite.test index 3d9cd46..8d7fea0 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -118,7 +118,7 @@ do_test tcl-1.14 { do_test tcl-1.15 { set v [catch {db function} msg] lappend v $msg -} {1 {wrong # args: should be "db function NAME [-argcount N] SCRIPT"}} +} {1 {wrong # args: should be "db function NAME ?SWITCHES? SCRIPT"}} do_test tcl-1.16 { set v [catch {db last_insert_rowid xyz} msg] lappend v $msg diff --git a/test/tester.tcl b/test/tester.tcl index dad2266..37ca69f 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -666,6 +666,15 @@ proc do_test {name cmd expected} { flush stdout } +proc dumpbytes {s} { + set r "" + for {set i 0} {$i < [string length $s]} {incr i} { + if {$i > 0} {append r " "} + append r [format %02X [scan [string index $s $i] %c]] + } + return $r +} + proc catchcmd {db {cmd ""}} { global CLI set out [open cmds.txt w] @@ -676,6 +685,30 @@ proc catchcmd {db {cmd ""}} { list $rc $msg } +proc catchcmdex {db {cmd ""}} { + global CLI + set out [open cmds.txt w] + fconfigure $out -encoding binary -translation binary + puts -nonewline $out $cmd + close $out + set line "exec -keepnewline -- $CLI $db < cmds.txt" + set chans [list stdin stdout stderr] + foreach chan $chans { + catch { + set modes($chan) [fconfigure $chan] + fconfigure $chan -encoding binary -translation binary -buffering none + } + } + set rc [catch { eval $line } msg] + foreach chan $chans { + catch { + eval fconfigure [list $chan] $modes($chan) + } + } + # puts [dumpbytes $msg] + list $rc $msg +} + proc filepath_normalize {p} { # test cases should be written to assume "unix"-like file paths if {$::tcl_platform(platform)!="unix"} { diff --git a/test/trace2.test b/test/trace2.test index 562c70c..a3f0aeb 100644 --- a/test/trace2.test +++ b/test/trace2.test @@ -143,7 +143,7 @@ ifcapable fts3 { INSERT INTO x1(x1) VALUES('optimize'); } { "INSERT INTO x1(x1) VALUES('optimize');" - "-- SELECT DISTINCT level / (1024 * ?) FROM 'main'.'x1_segdir'" + "-- SELECT ? UNION SELECT level / (1024 * ?) FROM 'main'.'x1_segdir'" "-- SELECT idx, start_block, leaves_end_block, end_block, root FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?ORDER BY level DESC, idx ASC" "-- SELECT max(level) FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?" "-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)" diff --git a/test/trigger1.test b/test/trigger1.test index 1ebe12c..a190efd 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -712,4 +712,20 @@ do_test trigger1-16.7 { } } {1 {the INDEXED BY clause is not allowed on UPDATE or DELETE statements within triggers}} +#------------------------------------------------------------------------- +# Test that bug [34cd55d68e0e6e7c] has been fixed. +# +do_execsql_test trigger1-17.0 { + CREATE TABLE t17a(ii INT); + CREATE TABLE t17b(tt TEXT PRIMARY KEY, ss); + CREATE TRIGGER t17a_ai AFTER INSERT ON t17a BEGIN + INSERT INTO t17b(tt) VALUES(new.ii); + END; + CREATE TRIGGER t17b_ai AFTER INSERT ON t17b BEGIN + UPDATE t17b SET ss = 4; + END; + INSERT INTO t17a(ii) VALUES('1'); + PRAGMA integrity_check; +} {ok} + finish_test diff --git a/test/trigger7.test b/test/trigger7.test index 8fde200..2219624 100644 --- a/test/trigger7.test +++ b/test/trigger7.test @@ -114,6 +114,6 @@ do_test trigger7-99.1 { db close catch { sqlite3 db test.db } catchsql { DROP TRIGGER t2r5 } -} {1 {malformed database schema (t2r12) - near "nonsense": syntax error}} +} {1 {malformed database schema (t2r12)}} finish_test diff --git a/test/triggerC.test b/test/triggerC.test index 14cc0f0..3e47521 100644 --- a/test/triggerC.test +++ b/test/triggerC.test @@ -12,6 +12,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix triggerC ifcapable {!trigger} { finish_test return @@ -993,4 +994,52 @@ reset_db optimization_control db factor-constants 0 do_execsql_test triggerC-14.2 $SQL {1 2 3} +#------------------------------------------------------------------------- +# Check that table names used by trigger programs are dequoted exactly +# once. +# +do_execsql_test 15.1.1 { + PRAGMA recursive_triggers = 1; + CREATE TABLE node( + id int not null primary key, + pid int not null default 0 references node, + key varchar not null, + path varchar default '', + unique(pid, key) + ); + CREATE TRIGGER node_delete_referencing AFTER DELETE ON "node" + BEGIN + DELETE FROM "node" WHERE pid = old."id"; + END; +} +do_execsql_test 15.1.2 { + INSERT INTO node(id, pid, key) VALUES(9, 0, 'test'); + INSERT INTO node(id, pid, key) VALUES(90, 9, 'test1'); + INSERT INTO node(id, pid, key) VALUES(900, 90, 'test2'); + DELETE FROM node WHERE id=9; + SELECT * FROM node; +} + +do_execsql_test 15.2.1 { + CREATE TABLE x1 (x); + + CREATE TABLE x2 (a, b); + CREATE TABLE '"x2"'(a, b); + + INSERT INTO x2 VALUES(1, 2); + INSERT INTO x2 VALUES(3, 4); + INSERT INTO '"x2"' SELECT * FROM x2; + + CREATE TRIGGER x1ai AFTER INSERT ON x1 BEGIN + INSERT INTO """x2""" VALUES('x', 'y'); + DELETE FROM """x2""" WHERE a=1; + UPDATE """x2""" SET b = 11 WHERE a = 3; + END; + + INSERT INTO x1 VALUES('go!'); +} + +do_execsql_test 15.2.2 { SELECT * FROM x2; } {1 2 3 4} +do_execsql_test 15.2.3 { SELECT * FROM """x2"""; } {3 11 x y} + finish_test diff --git a/test/vacuum2.test b/test/vacuum2.test index b3bfab3..0350c8e 100644 --- a/test/vacuum2.test +++ b/test/vacuum2.test @@ -15,6 +15,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix vacuum2 # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). @@ -227,5 +228,24 @@ do_test vacuum2-5.4 { lappend res2 $res } {1 2 3 4 5 6 7 8 9 10 {1 {cannot VACUUM - SQL statements in progress}}} +#------------------------------------------------------------------------- +# Check that if the definition of a collation sequence is changed and +# VACUUM run, records are store in the (new) correct order following the +# VACUUM. Even if the modified collation is attached to a PK of a WITHOUT +# ROWID table. + +proc cmp {lhs rhs} { string compare $lhs $rhs } +db collate cmp cmp +do_execsql_test 6.0 { + CREATE TABLE t6(x PRIMARY KEY COLLATE cmp, y) WITHOUT ROWID; + CREATE INDEX t6y ON t6(y); + INSERT INTO t6 VALUES('i', 'one'); + INSERT INTO t6 VALUES('ii', 'one'); + INSERT INTO t6 VALUES('iii', 'one'); +} +integrity_check 6.1 +proc cmp {lhs rhs} { string compare $rhs $lhs } +do_execsql_test 6.2 VACUUM +integrity_check 6.3 finish_test diff --git a/test/vtab1.test b/test/vtab1.test index 2929b1e..c0cf3e4 100644 --- a/test/vtab1.test +++ b/test/vtab1.test @@ -1437,4 +1437,95 @@ ifcapable fts3 { } {SQLITE_OK} } + +#------------------------------------------------------------------------- +# The following tests verify that a DROP TABLE command on a virtual +# table does not cause other operations to crash. +# +# 23.1: Dropping a vtab while a SELECT is running on it. +# +# 23.2: Dropping a vtab while a SELECT that will, but has not yet, +# open a cursor on the vtab, is running. In this case the +# DROP TABLE succeeds and the SELECT hits an error. +# +# 23.3: Dropping a vtab from within a user-defined-function callback +# in the middle of an "INSERT INTO vtab SELECT ..." statement. +# +reset_db +load_static_extension db wholenumber +load_static_extension db eval +register_echo_module db + +do_test 23.1 { + execsql { CREATE VIRTUAL TABLE t1 USING wholenumber } + set res "" + db eval { SELECT value FROM t1 WHERE value<10 } { + if {$value == 5} { + set res [catchsql { DROP TABLE t1 }] + } + } + set res +} {1 {database table is locked}} + +do_test 23.2 { + execsql { + CREATE TABLE t2(value); + INSERT INTO t2 VALUES(1), (2), (3); + } + + set res2 [list [catch { + db eval { + SELECT value FROM t2 UNION ALL + SELECT value FROM t1 WHERE value<10 + } { + if {$value == 2} { set res1 [catchsql { DROP TABLE t1 }] } + } + } msg] $msg] + list $res1 $res2 +} {{0 {}} {1 {database table is locked}}} + +do_test 23.3.1 { + execsql { CREATE VIRTUAL TABLE t1e USING echo(t2) } + execsql { INSERT INTO t1e SELECT 4 } + catchsql { INSERT INTO t1e SELECT eval('DROP TABLE t1e') } +} {1 {database table is locked}} +do_execsql_test 23.3.2 { SELECT * FROM t1e } {1 2 3 4} + +#------------------------------------------------------------------------- +# At one point SQL like this: +# +# SAVEPOINT xyz; -- Opens SQL transaction +# INSERT INTO vtab -- Write to virtual table +# ROLLBACK TO xyz; +# RELEASE xyz; +# +# was not invoking the xRollbackTo() callback for the ROLLBACK TO +# operation. Which meant that virtual tables like FTS3 would incorrectly +# commit the results of the INSERT as part of the "RELEASE xyz" command. +# +# The following tests check that this has been fixed. +# +ifcapable fts3 { + do_execsql_test 24.0 { + CREATE VIRTUAL TABLE t4 USING fts3(); + SAVEPOINT a; + INSERT INTO t4 VALUES('a b c'); + ROLLBACK TO a; + RELEASE a; + SELECT * FROM t4; + } {} + + do_execsql_test 24.1 { SELECT * FROM t4 WHERE t4 MATCH 'b' } {} + do_execsql_test 24.2 { INSERT INTO t4(t4) VALUES('integrity-check') } {} + + do_execsql_test 24.3 { + SAVEPOINT a; + CREATE VIRTUAL TABLE t5 USING fts3(); + SAVEPOINT b; + ROLLBACK TO a; + SAVEPOINT c; + RELEASE a; + } +} + finish_test diff --git a/test/vtab2.test b/test/vtab2.test index 05a4834..3884ec5 100644 --- a/test/vtab2.test +++ b/test/vtab2.test @@ -10,10 +10,10 @@ #*********************************************************************** # This file implements regression tests for SQLite library. # -# $Id: vtab2.test,v 1.9 2008/10/13 10:37:50 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix vtab2 ifcapable !vtab||!schema_pragmas { finish_test @@ -133,4 +133,24 @@ do_test vtab2-4.5 { execsql { SELECT * FROM fkey } } {t1 a} +#------------------------------------------------------------------------- +# +ifcapable fts3 { + reset_db + do_execsql_test 5.1 { + PRAGMA encoding='UTF16'; + } + + do_test 5.2 { + sqlite3_exec_hex db { CREATE VIRTUAL TABLE %C8 USING fts3 } + } {0 {}} + + do_test 5.3 { + sqlite3_exec_hex db { CREATE VIRTUAL TABLE %C9 USING s } + } {/1 {malformed database schema.* already exists}/} +} + + + finish_test + diff --git a/test/vtabA.test b/test/vtabA.test index 928cc2b..eddaa70 100644 --- a/test/vtabA.test +++ b/test/vtabA.test @@ -74,28 +74,39 @@ do_test vtabA-1.6 { SELECT * FROM t1e; } } {{value a} {value c}} +do_execsql_test vtabA-1.7 { + DELETE FROM t1e; + INSERT INTO t1e SELECT 'abc','def'; +} {} +do_execsql_test vtabA-1.8 { + INSERT INTO t1e VALUES('ghi','jkl'),('mno','pqr'),('stu','vwx'); +} {} +do_execsql_test vtabA-1.9 { + SELECT a,b,c, '|' FROM t1e ORDER BY 1; +} {abc {} def | ghi {} jkl | mno {} pqr | stu {} vwx |} + # Test that the expansion of a '*' expression in the result set of # a SELECT does not include the hidden column. # -do_test vtabA-1.7 { +do_test vtabA-1.20 { execsql { INSERT INTO t1e SELECT * FROM t1e; } } {} -do_test vtabA-1.8 { +do_test vtabA-1.21 { execsql { - SELECT * FROM t1e; + SELECT * FROM t1e ORDER BY 1; } -} {{value a} {value c} {value a} {value c}} +} {abc def abc def ghi jkl ghi jkl mno pqr mno pqr stu vwx stu vwx} # Test that the declaration type of the hidden column does not include # the token "HIDDEN". # -do_test vtabA-1.9 { +do_test vtabA-1.22 { get_decltype t1e b } {VARCHAR} -do_test vtabA-1.10 { +do_test vtabA-1.23 { get_collist t1e } {a c} diff --git a/test/wal5.test b/test/wal5.test index 2d3522b..360d9c9 100644 --- a/test/wal5.test +++ b/test/wal5.test @@ -457,18 +457,18 @@ foreach {testprefix do_wal_checkpoint} { } {1 2 3 4 5 6 7 8 9 10} proc xBusyHandler {n} { return 1 } - do_test 5.$tn.14 { do_wal_checkpoint db -mode truncate } {1 4 4} - do_test 5.$tn.15 { file size test.db-wal } [wal_file_size 4 1024] + do_test 5.$tn.15 { do_wal_checkpoint db -mode truncate } {1 4 4} + do_test 5.$tn.16 { file size test.db-wal } [wal_file_size 4 1024] - do_test 5.$tn.16 { do_wal_checkpoint db -mode restart } {1 4 4} + do_test 5.$tn.17 { do_wal_checkpoint db -mode restart } {1 4 4} proc xBusyHandler {n} { sql2 { COMMIT } ; return 0 } db busy xBusyHandler - do_test 5.$tn.17 { do_wal_checkpoint db -mode restart } {0 4 4} - do_test 5.$tn.18 { file size test.db-wal } [wal_file_size 4 1024] + do_test 5.$tn.18 { do_wal_checkpoint db -mode restart } {0 4 4} + do_test 5.$tn.19 { file size test.db-wal } [wal_file_size 4 1024] - do_test 5.$tn.19 { do_wal_checkpoint db -mode truncate } {0 0 0} - do_test 5.$tn.20 { file size test.db-wal } 0 + do_test 5.$tn.20 { do_wal_checkpoint db -mode truncate } {0 0 0} + do_test 5.$tn.21 { file size test.db-wal } 0 } } diff --git a/test/walblock.test b/test/walblock.test new file mode 100644 index 0000000..23167a8 --- /dev/null +++ b/test/walblock.test @@ -0,0 +1,114 @@ +# 2015 Mar 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. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/lock_common.tcl +source $testdir/wal_common.tcl + +finish_test; return; # Feature currently not implemented. +ifcapable !wal {finish_test ; return } +if {$::tcl_platform(platform)!="unix"} { finish_test ; return } +set testprefix walblock + +catch { db close } +testvfs tvfs -fullshm 1 +foreach f [glob test.db*] { forcedelete $f } + +sqlite3 db test.db -vfs tvfs +do_execsql_test 1.1.0 { + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); + INSERT INTO t1 VALUES(5, 6); + PRAGMA journal_mode = wal; + INSERT INTO t1 VALUES(7, 8); +} {wal} + +do_test 1.1.1 { + lsort [glob test.db*] +} {test.db test.db-shm test.db-wal} + +do_test 1.1.2 { + set C [launch_testfixture] + testfixture $C { + sqlite3 db test.db + db eval { SELECT * FROM t1 } + } +} {1 2 3 4 5 6 7 8} + +do_test 1.1.3 { + set ::out [list] + testfixture $C { + db eval { SELECT * FROM t1 } + } [list set ::out] + set ::out +} {} + +do_test 1.1.4 { + vwait ::out + set ::out +} {1 2 3 4 5 6 7 8} + +# +# Test that if a read client cannot read the wal-index header because a +# write client is in the middle of updating it, the reader blocks until +# the writer finishes. +# +# 1. Open a write transaction using client [db] in this process. +# +# 2. Attempt to commit the write transaction. Intercept the xShmBarrier() +# call made by the writer between updating the two copies of the +# wal-index header. +# +# 3. Within the xShmBarrier() callback, make an asynchronous request to +# the other process to read from the database. It should block, as it +# cannot get read the wal-index header. +# +# 4. Still in xShmBarrier(), wait for 5 seconds. Check that the other +# process has not answered the request. +# +# 5: Finish committing the transaction. Then wait for 0.5 seconds more. +# Ensure that the second process has by this stage read the database +# and that the snapshot it read included the transaction committed in +# step (4). +# +do_execsql_test 1.2.1 { + BEGIN; + INSERT INTO t1 VALUES(9, 10); +} {} + +tvfs script barrier_callback +tvfs filter xShmBarrier +proc barrier_callback {method args} { + set ::out "" + testfixture $::C { db eval { SELECT * FROM t1 } } {set ::out} + + do_test "1.2.2.(blocking 10 seconds)" { + set ::continue 0 + after 10000 {set ::continue 1} + vwait ::continue + set ::out + } {} +} + +execsql COMMIT + +do_test "1.2.3.(blocking 0.5 seconds)" { + set ::continue 0 + after 500 {set ::continue 1} + vwait ::continue + set ::out +} {1 2 3 4 5 6 7 8 9 10} + + +finish_test diff --git a/test/where8.test b/test/where8.test index 139251a..a155a95 100644 --- a/test/where8.test +++ b/test/where8.test @@ -66,11 +66,11 @@ do_test where8-1.3 { do_test where8-1.4 { execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b GLOB 't*' } -} {IX X III II 0 0 9} +} {IX X III II 0 0 10} do_test where8-1.5 { execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b GLOB 'f*' } -} {IX X V IV 0 0 9} +} {IX X V IV 0 0 10} do_test where8-1.6 { execsql_status { SELECT c FROM t1 WHERE a = 1 OR b = 'three' ORDER BY rowid } diff --git a/test/whereD.test b/test/whereD.test index db99304..17fdac7 100644 --- a/test/whereD.test +++ b/test/whereD.test @@ -129,11 +129,11 @@ do_execsql_test 3.0 { do_searchcount_test 3.1 { SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR (a=2 AND b='two') -} {1 one 2 two search 2} +} {1 one 2 two search 4} do_searchcount_test 3.2 { SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR (a=2 AND b='two') -} {1 i 2 ii search 4} +} {1 i 2 ii search 6} do_searchcount_test 3.4.1 { SELECT y FROM t4 WHERE x='a' @@ -142,24 +142,24 @@ do_searchcount_test 3.4.2 { SELECT a, b FROM t3 WHERE (a=1 AND b=(SELECT y FROM t4 WHERE x='a')) OR (a=2 AND b='two') -} {1 one 2 two search 4} +} {1 one 2 two search 6} do_searchcount_test 3.4.3 { SELECT a, b FROM t3 WHERE (a=2 AND b='two') OR (a=1 AND b=(SELECT y FROM t4 WHERE x='a')) -} {2 two 1 one search 4} +} {2 two 1 one search 6} do_searchcount_test 3.4.4 { SELECT a, b FROM t3 WHERE (a=2 AND b=(SELECT y FROM t4 WHERE x='b')) OR (a=1 AND b=(SELECT y FROM t4 WHERE x='a')) -} {2 two 1 one search 6} +} {2 two 1 one search 8} do_searchcount_test 3.5.1 { SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4 -} {1 one 2 two search 2} +} {1 one 2 two search 3} do_searchcount_test 3.5.2 { SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4 -} {1 i 2 ii search 2} +} {1 i 2 ii search 3} # Ticket [d02e1406a58ea02d] (2012-10-04) # LEFT JOIN with an OR in the ON clause causes segfault diff --git a/test/whereK.test b/test/whereK.test new file mode 100644 index 0000000..13c8650 --- /dev/null +++ b/test/whereK.test @@ -0,0 +1,72 @@ +# 2015-03-16 +# +# 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 file is testing OR expressions where terms can be +# factored from either side of the OR and combined into a single new +# AND term that is beneficial to the search. Examples: +# +# (x>A OR x=A) --> ... AND (x>=A) +# (x>A OR (x=A AND y>=B) --> ... AND (x>=A) +# + + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix whereK + +do_execsql_test 1.1 { + CREATE TABLE t1(a,b,c); + WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<99) + INSERT INTO t1(a,b,c) SELECT x, x/10, x%10 FROM c; + CREATE INDEX t1bc ON t1(b,c); + SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a; +} {90 91 92 93 94 95 96 97 98 99} +do_execsql_test 1.1eqp { + EXPLAIN QUERY PLAN + SELECT a FROM t1 WHERE b>9 OR b=9 ORDER BY +a; +} {/SEARCH TABLE t1 USING INDEX t1bc/} + +do_execsql_test 1.2 { + SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a; +} {88 89 90 91 92 93 94 95 96 97 98 99} +do_execsql_test 1.2eqp { + EXPLAIN QUERY PLAN + SELECT a FROM t1 WHERE b>8 OR (b=8 AND c>7) ORDER BY +a; +} {/SEARCH TABLE t1 USING INDEX t1bc/} + +do_execsql_test 1.3 { + SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a; +} {88 89 90 91 92 93 94 95 96 97 98 99} +do_execsql_test 1.3eqp { + EXPLAIN QUERY PLAN + SELECT a FROM t1 WHERE (b=8 AND c>7) OR b>8 ORDER BY +a; +} {/SEARCH TABLE t1 USING INDEX t1bc/} + +do_execsql_test 1.4 { + SELECT a FROM t1 WHERE (b=8 AND c>7) OR 87) OR 87) OR (b>8 AND c NOT IN (4,5,6)) + ORDER BY +a; +} {88 89 90 91 92 93 97 98 99} +do_execsql_test 1.5eqp { + EXPLAIN QUERY PLAN + SELECT a FROM t1 WHERE (b=8 AND c>7) OR (b>8 AND c NOT IN (4,5,6)) + ORDER BY +a; +} {/SEARCH TABLE t1 USING INDEX t1bc/} + +finish_test diff --git a/test/win32lock.test b/test/win32lock.test index cff1ed3..d1f3d1a 100644 --- a/test/win32lock.test +++ b/test/win32lock.test @@ -64,6 +64,7 @@ while {1} { if {[info exists ::log] && $::log!=""} { do_test win32lock-1.2-$delay1-log1 { regsub {\d+} $::log # x + regsub { at line \d+} $x "" x set x } {{delayed #ms for lock/sharing conflict}} } @@ -112,6 +113,7 @@ while {1} { if {[info exists ::log] && $::log!=""} { do_test win32lock-2.2-$delay1-log1 { regsub {\d+} $::log # x + regsub { at line \d+} $x "" x set x } {{delayed #ms for lock/sharing conflict}} } diff --git a/test/with1.test b/test/with1.test index 42d2277..80892d2 100644 --- a/test/with1.test +++ b/test/with1.test @@ -827,5 +827,26 @@ WITH RECURSIVE SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1; } {2 4 8 10 14 16 20} +# 2015-03-21 +# Column wildcards on the LHS of a recursive table expression +# +do_catchsql_test 13.1 { + WITH RECURSIVE c(i) AS (SELECT * UNION ALL SELECT i+1 FROM c WHERE i<10) + SELECT i FROM c; +} {1 {no tables specified}} +do_catchsql_test 13.2 { + WITH RECURSIVE c(i) AS (SELECT 5,* UNION ALL SELECT i+1 FROM c WHERE i<10) + SELECT i FROM c; +} {1 {no tables specified}} +do_catchsql_test 13.3 { + WITH RECURSIVE c(i,j) AS (SELECT 5,* UNION ALL SELECT i+1,11 FROM c WHERE i<10) + SELECT i FROM c; +} {1 {table c has 1 values for 2 columns}} + +# 2015-04-12 +# +do_execsql_test 14.1 { + WITH x AS (SELECT * FROM t) SELECT 0 EXCEPT SELECT 0 ORDER BY 1 COLLATE binary; +} {} finish_test diff --git a/test/without_rowid6.test b/test/without_rowid6.test index e827cca..8ca78ba 100644 --- a/test/without_rowid6.test +++ b/test/without_rowid6.test @@ -37,5 +37,81 @@ do_execsql_test without_rowid6-140 { SELECT c FROM t1 ORDER BY b LIMIT 5; } {x1y x2y x3y x4y x5y} +# Column t1.b starts out as a unique index, but that index is +# subsequently converted into a PRIMARY KEY. +# +do_execsql_test without_rowid6-200 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1( + a UNIQUE, + b UNIQUE, + c UNIQUE, + PRIMARY KEY(b) + ) WITHOUT ROWID; + INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9); + SELECT a FROM t1 WHERE b>3 ORDER BY b; +} {4 1} +do_execsql_test without_rowid6-210 { + EXPLAIN QUERY PLAN + SELECT a FROM t1 WHERE b>3 ORDER BY b; +} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../} +do_execsql_test without_rowid6-220 { + PRAGMA index_list(t1); +} {/sqlite_autoindex_t1_2 1 pk/} + +do_execsql_test without_rowid6-300 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1( + a UNIQUE, + b PRIMARY KEY, + c UNIQUE, + UNIQUE(b) + ) WITHOUT ROWID; + INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9); + SELECT a FROM t1 WHERE b>3 ORDER BY b; +} {4 1} +do_execsql_test without_rowid6-310 { + EXPLAIN QUERY PLAN + SELECT a FROM t1 WHERE b>3 ORDER BY b; +} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../} +do_execsql_test without_rowid6-320 { + PRAGMA index_list(t1); +} {/sqlite_autoindex_t1_2 1 pk/} + +do_execsql_test without_rowid6-400 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1( + a UNIQUE, + b UNIQUE PRIMARY KEY, + c UNIQUE + ) WITHOUT ROWID; + INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9); + SELECT a FROM t1 WHERE b>3 ORDER BY b; +} {4 1} +do_execsql_test without_rowid6-410 { + EXPLAIN QUERY PLAN + SELECT a FROM t1 WHERE b>3 ORDER BY b; +} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../} +do_execsql_test without_rowid6-420 { + PRAGMA index_list(t1); +} {/sqlite_autoindex_t1_2 1 pk/} + +do_execsql_test without_rowid6-500 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a,b,c, + UNIQUE(b,c), + PRIMARY KEY(b,c) + ) WITHOUT ROWID; + INSERT INTO t1(a,b,c) VALUES(1,8,3),(4,5,6),(7,2,9); + SELECT a FROM t1 WHERE b>3 ORDER BY b; +} {4 1} +do_execsql_test without_rowid6-510 { + EXPLAIN QUERY PLAN + SELECT a FROM t1 WHERE b>3 ORDER BY b; +} {/SEARCH TABLE t1 USING PRIMARY KEY .b>../} +do_execsql_test without_rowid6-520 { + PRAGMA index_list(t1); +} {/sqlite_autoindex_t1_1 1 pk/} + finish_test diff --git a/test/zeroblob.test b/test/zeroblob.test index f4a1950..e70fd0b 100644 --- a/test/zeroblob.test +++ b/test/zeroblob.test @@ -255,5 +255,14 @@ do_test zeroblob-9.8 { db eval {SELECT zeroblob(2) IN (zeroblob(2))} } {1} +# Oversized zeroblob records +# +do_test zeroblob-10.1 { + db eval { + CREATE TABLE t10(a,b,c); + } + catchsql {INSERT INTO t10 VALUES(zeroblob(1e9),zeroblob(1e9),zeroblob(1e9))} +} {1 {string or blob too big}} + finish_test diff --git a/tool/build-all-msvc.bat b/tool/build-all-msvc.bat index 1fb61d4..9f5176d 100755 --- a/tool/build-all-msvc.bat +++ b/tool/build-all-msvc.bat @@ -28,6 +28,11 @@ REM In the example above, "C:\dev\sqlite\core" represents the root of the REM source tree for SQLite and "C:\Temp" represents the final destination REM directory for the generated output files. REM +REM Please note that the SQLite build process performed by the Makefile +REM associated with this batch script requires both Gawk ^(gawk.exe^) and Tcl +REM 8.5 ^(tclsh85.exe^) to be present in a directory contained in the PATH +REM environment variable unless a pre-existing amalgamation file is used. +REM REM There are several environment variables that may be set to modify the REM behavior of this batch script and its associated Makefile. The list of REM platforms to build may be overriden by using the PLATFORMS environment @@ -37,17 +42,58 @@ REM being used. The list of configurations to build may be overridden by REM setting the CONFIGURATIONS environment variable, which should contain a REM list of configurations to build ^(e.g. Debug Retail^). Neither of these REM variable values may contain any double quotes, surrounding or embedded. -REM Finally, the NCRTLIBPATH and NSDKLIBPATH environment variables may be set -REM to specify the location of the CRT and SDK, respectively, needed to compile -REM executables native to the architecture of the build machine during any -REM cross-compilation that may be necessary, depending on the platforms to be -REM built. These values in these two variables should be surrounded by double -REM quotes if they contain spaces. REM -REM Please note that the SQLite build process performed by the Makefile -REM associated with this batch script requires both Gawk ^(gawk.exe^) and Tcl -REM 8.5 ^(tclsh85.exe^) to be present in a directory contained in the PATH -REM environment variable unless a pre-existing amalgamation file is used. +REM Finally, the NCRTLIBPATH, NUCRTLIBPATH, and NSDKLIBPATH environment +REM variables may be set to specify the location of the CRT, Universal CRT, and +REM Windows SDK, respectively, that may be needed to compile executables native +REM to the architecture of the build machine during any cross-compilation that +REM may be necessary, depending on the platforms to be built. These values in +REM these three variables should be surrounded by double quotes if they contain +REM spaces. +REM +REM There are a few other environment variables that impact the build process +REM when set ^(to anything^), they are: +REM +REM NOCLEAN +REM +REM When set, the "clean" target will not be used during each build iteration. +REM However, the target binaries, if any, will still be deleted manually prior +REM to being rebuilt. Setting this environment variable is only rarely needed +REM and could cause issues in some circumstances; therefore, setting it is not +REM recommended. +REM +REM NOSYMBOLS +REM +REM When set, copying of symbol files ^(*.pdb^) created during the build will +REM be skipped and they will not appear in the final destination directory. +REM Setting this environment variable is never strictly needed and could cause +REM issues in some circumstances; therefore, setting it is not recommended. +REM +REM BUILD_ALL_SHELL +REM +REM When set, the command line shell will be built for each selected platform +REM and configuration as well. In addition, the command line shell binaries +REM will be copied, with their symbols, to the final destination directory. +REM +REM USE_WINV63_NSDKLIBPATH +REM +REM When set, modifies how the NSDKLIBPATH environment variable is built, based +REM on the WindowsSdkDir environment variable. It forces this batch script to +REM assume the Windows 8.1 SDK location should be used. +REM +REM USE_WINV100_NSDKLIBPATH +REM +REM When set, modifies how the NSDKLIBPATH environment variable is built, based +REM on the WindowsSdkDir environment variable. It causes this batch script to +REM assume the Windows 10.0 SDK location should be used. +REM +REM NMAKE_ARGS +REM +REM When set, the value is expanded and passed to the NMAKE command line, after +REM its other arguments. This is used to specify additional NMAKE options, for +REM example: +REM +REM SET NMAKE_ARGS=FOR_WINRT=1 REM SETLOCAL @@ -58,6 +104,9 @@ IF NOT DEFINED _AECHO (SET _AECHO=REM) IF NOT DEFINED _CECHO (SET _CECHO=REM) IF NOT DEFINED _VECHO (SET _VECHO=REM) +SET REDIRECT=^> +IF DEFINED __ECHO SET REDIRECT=^^^> + %_AECHO% Running %0 %* REM SET DFLAGS=/L @@ -214,8 +263,20 @@ SET TOOLPATH=%gawk.exe_PATH%;%tclsh85.exe_PATH% %_VECHO% ToolPath = '%TOOLPATH%' REM -REM NOTE: Check for MSVC 2012/2013 because the Windows SDK directory handling -REM is slightly different for those versions. +REM NOTE: Setting the Windows SDK library path is only required for MSVC +REM 2012, 2013, and 2015. +REM +CALL :fn_UnsetVariable SET_NSDKLIBPATH + +REM +REM NOTE: Setting the Universal CRT library path is only required for MSVC +REM 2015. +REM +CALL :fn_UnsetVariable SET_NUCRTLIBPATH + +REM +REM NOTE: Check for MSVC 2012, 2013, and 2015 specially because the Windows +REM SDK directory handling is slightly different for those versions. REM IF "%VisualStudioVersion%" == "11.0" ( REM @@ -233,8 +294,22 @@ IF "%VisualStudioVersion%" == "11.0" ( IF NOT DEFINED NSDKLIBPATH ( SET SET_NSDKLIBPATH=1 ) -) ELSE ( - CALL :fn_UnsetVariable SET_NSDKLIBPATH +) ELSE IF "%VisualStudioVersion%" == "14.0" ( + REM + REM NOTE: If the Windows SDK library path has already been set, do not set + REM it to something else later on. + REM + IF NOT DEFINED NSDKLIBPATH ( + SET SET_NSDKLIBPATH=1 + ) + + REM + REM NOTE: If the Universal CRT library path has already been set, do not set + REM it to something else later on. + REM + IF NOT DEFINED NUCRTLIBPATH ( + SET SET_NUCRTLIBPATH=1 + ) ) REM @@ -291,6 +366,7 @@ FOR %%P IN (%PLATFORMS%) DO ( CALL :fn_UnsetVariable LIB CALL :fn_UnsetVariable LIBPATH CALL :fn_UnsetVariable Platform + CALL :fn_UnsetVariable UniversalCRTSdkDir REM CALL :fn_UnsetVariable VCINSTALLDIR CALL :fn_UnsetVariable VSINSTALLDIR CALL :fn_UnsetVariable WindowsPhoneKitDir @@ -318,7 +394,18 @@ FOR %%P IN (%PLATFORMS%) DO ( %_AECHO% Building the %%B configuration for platform %%P with name %%D... IF /I "%%B" == "Debug" ( - SET DEBUG=2 + REM + REM NOTE: Using this level for the DEBUG environment variable should + REM disable all compiler optimizations and prevent use of the + REM NDEBUG define. Additionally, both SQLITE_ENABLE_API_ARMOR + REM and SQLITE_DEBUG defines should be enabled. + REM + SET DEBUG=3 + + REM + REM NOTE: Setting this to non-zero should enable the SQLITE_MEMDEBUG + REM define. + REM SET MEMDEBUG=1 ) ELSE ( CALL :fn_UnsetVariable DEBUG @@ -371,8 +458,8 @@ FOR %%P IN (%PLATFORMS%) DO ( ) REM - REM NOTE: When using MSVC 2012 and/or 2013, the native SDK path cannot - REM simply use the "lib" sub-directory beneath the location + REM NOTE: When using MSVC 2012, 2013, or 2015, the native SDK path + REM cannot simply be the "lib" sub-directory beneath the location REM specified in the WindowsSdkDir environment variable because REM that location does not actually contain the necessary library REM files for x86. This must be done for each iteration because @@ -391,19 +478,39 @@ FOR %%P IN (%PLATFORMS%) DO ( CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH REM - REM NOTE: The Windows 8.1 SDK has a slightly different directory - REM naming convention. + REM NOTE: The Windows 8.x and Windows 10.0 SDKs have a slightly + REM different directory naming conventions. REM - IF DEFINED USE_WINV63_NSDKLIBPATH ( + IF DEFINED USE_WINV100_NSDKLIBPATH ( + CALL :fn_AppendVariable NSDKLIBPATH \..\10\lib\10.0.10030.0\um\x86 + CALL :fn_CopyVariable UniversalCRTSdkDir PSDKLIBPATH + CALL :fn_AppendVariable PSDKLIBPATH Lib\10.0.10030.0\um\%%D + ) ELSE IF DEFINED USE_WINV63_NSDKLIBPATH ( CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86 ) ELSE IF "%VisualStudioVersion%" == "12.0" ( CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86 + ) ELSE IF "%VisualStudioVersion%" == "14.0" ( + CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86 ) ELSE ( CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86 ) ) ) + REM + REM NOTE: When using MSVC 2015, setting the Universal CRT library path + REM for x86 may be required as well. This must also be done for + REM each iteration because it relies upon the UniversalCRTSdkDir + REM environment variable being set by the batch file used to + REM setup the MSVC environment. + REM + IF DEFINED SET_NUCRTLIBPATH ( + IF DEFINED UniversalCRTSdkDir ( + CALL :fn_CopyVariable UniversalCRTSdkDir NUCRTLIBPATH + CALL :fn_AppendVariable NUCRTLIBPATH \lib\winv10.0\ucrt\x86 + ) + ) + REM REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC REM makefile to clean any stale build output from previous @@ -420,11 +527,11 @@ FOR %%P IN (%PLATFORMS%) DO ( ) ELSE ( REM REM NOTE: Even when the cleaning step has been disabled, we still - REM need to remove the build output for the files we are + REM need to remove the build output for all the files we are REM specifically wanting to build for each platform. REM - %_AECHO% Cleaning final output files only... - %__ECHO% DEL /Q *.lo sqlite3.dll sqlite3.lib sqlite3.pdb + %_AECHO% Cleaning final core library output files only... + %__ECHO% DEL /Q *.lo sqlite3.dll sqlite3.lib sqlite3.pdb 2%REDIRECT% NUL ) REM @@ -476,6 +583,64 @@ FOR %%P IN (%PLATFORMS%) DO ( GOTO errors ) ) + + REM + REM NOTE: If requested, also build the shell executable. + REM + IF DEFINED BUILD_ALL_SHELL ( + REM + REM NOTE: If necessary, make sure any previous build output for the + REM shell executable is deleted. + REM + IF DEFINED NOCLEAN ( + REM + REM NOTE: Even when the cleaning step has been disabled, we still + REM need to remove the build output for all the files we are + REM specifically wanting to build for each platform. + REM + %_AECHO% Cleaning final shell executable output files only... + %__ECHO% DEL /Q sqlite3.exe sqlite3sh.pdb 2%REDIRECT% NUL + ) + + REM + REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.exe" + REM binary. The x86 compiler will be used to compile the native + REM command line tools needed during the build process itself. + REM Also, disable looking for and/or linking to the native Tcl + REM runtime library. + REM + %__ECHO% %NMAKE_CMD% sqlite3.exe XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% + + IF ERRORLEVEL 1 ( + ECHO Failed to build %%B "sqlite3.exe" for platform %%P. + GOTO errors + ) + + REM + REM NOTE: Copy the "sqlite3.exe" file to the appropriate directory + REM for the build and platform beneath the binary directory. + REM + %__ECHO% XCOPY sqlite3.exe "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + + IF ERRORLEVEL 1 ( + ECHO Failed to copy "sqlite3.exe" to "%BINARYDIRECTORY%\%%B\%%D\". + GOTO errors + ) + + REM + REM NOTE: Copy the "sqlite3sh.pdb" file to the appropriate directory + REM for the build and platform beneath the binary directory + REM unless we are prevented from doing so. + REM + IF NOT DEFINED NOSYMBOLS ( + %__ECHO% XCOPY sqlite3sh.pdb "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS% + + IF ERRORLEVEL 1 ( + ECHO Failed to copy "sqlite3sh.pdb" to "%BINARYDIRECTORY%\%%B\%%D\". + GOTO errors + ) + ) + ) ) ) ) @@ -503,6 +668,19 @@ REM NOTE: If we get to this point, we have succeeded. REM GOTO no_errors +:fn_ShowVariable + SETLOCAL + SET __ECHO_CMD=ECHO %%%2%% + FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO ( + IF NOT "%%V" == "" ( + IF NOT "%%V" == "%%%2%%" ( + %_VECHO% %1 = '%%V' + ) + ) + ) + ENDLOCAL + GOTO :EOF + :fn_ResetErrorLevel VERIFY > NUL GOTO :EOF diff --git a/tool/fuzzershell.c b/tool/fuzzershell.c new file mode 100644 index 0000000..4eea55b --- /dev/null +++ b/tool/fuzzershell.c @@ -0,0 +1,846 @@ +/* +** 2015-04-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 is a utility program designed to aid running the SQLite library +** against an external fuzzer, such as American Fuzzy Lop (AFL) +** (http://lcamtuf.coredump.cx/afl/). Basically, this program reads +** SQL text from standard input and passes it through to SQLite for evaluation, +** just like the "sqlite3" command-line shell. Differences from the +** command-line shell: +** +** (1) The complex "dot-command" extensions are omitted. This +** prevents the fuzzer from discovering that it can run things +** like ".shell rm -rf ~" +** +** (2) The database is opened with the SQLITE_OPEN_MEMORY flag so that +** no disk I/O from the database is permitted. The ATTACH command +** with a filename still uses an in-memory database. +** +** (3) The main in-memory database can be initialized from a template +** disk database so that the fuzzer starts with a database containing +** content. +** +** (4) The eval() SQL function is added, allowing the fuzzer to do +** interesting recursive operations. +** +** (5) An error is raised if there is a memory leak. +** +** The input text can be divided into separate test cases using comments +** of the form: +** +** |****<...>****| +** +** where the "..." is arbitrary text. (Except the "|" should really be "/". +** "|" is used here to avoid compiler errors about nested comments.) +** A separate in-memory SQLite database is created to run each test case. +** This feature allows the "queue" of AFL to be captured into a single big +** file using a command like this: +** +** (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt +** +** (Once again, change the "|" to "/") Then all elements of the AFL queue +** can be run in a single go (for regression testing, for example) by typing: +** +** fuzzershell -f ~/all-queue.txt +** +** After running each chunk of SQL, the database connection is closed. The +** program aborts if the close fails or if there is any unfreed memory after +** the close. +** +** New test cases can be appended to all-queue.txt at any time. If redundant +** test cases are added, they can be eliminated by running: +** +** fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt +*/ +#include +#include +#include +#include +#include +#include "sqlite3.h" + +/* +** All global variables are gathered into the "g" singleton. +*/ +struct GlobalVars { + const char *zArgv0; /* Name of program */ + sqlite3_mem_methods sOrigMem; /* Original memory methods */ + sqlite3_mem_methods sOomMem; /* Memory methods with OOM simulator */ + int iOomCntdown; /* Memory fails on 1 to 0 transition */ + int nOomFault; /* Increments for each OOM fault */ + int bOomOnce; /* Fail just once if true */ + int bOomEnable; /* True to enable OOM simulation */ + int nOomBrkpt; /* Number of calls to oomFault() */ + char zTestName[100]; /* Name of current test */ +} g; + +/* +** Maximum number of iterations for an OOM test +*/ +#ifndef OOM_MAX +# define OOM_MAX 625 +#endif + +/* +** This routine is called when a simulated OOM occurs. It exists as a +** convenient place to set a debugger breakpoint. +*/ +static void oomFault(void){ + g.nOomBrkpt++; /* Prevent oomFault() from being optimized out */ +} + + +/* Versions of malloc() and realloc() that simulate OOM conditions */ +static void *oomMalloc(int nByte){ + if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){ + g.iOomCntdown--; + if( g.iOomCntdown==0 ){ + if( g.nOomFault==0 ) oomFault(); + g.nOomFault++; + if( !g.bOomOnce ) g.iOomCntdown = 1; + return 0; + } + } + return g.sOrigMem.xMalloc(nByte); +} +static void *oomRealloc(void *pOld, int nByte){ + if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){ + g.iOomCntdown--; + if( g.iOomCntdown==0 ){ + if( g.nOomFault==0 ) oomFault(); + g.nOomFault++; + if( !g.bOomOnce ) g.iOomCntdown = 1; + return 0; + } + } + return g.sOrigMem.xRealloc(pOld, nByte); +} + +/* +** Print an error message and abort in such a way to indicate to the +** fuzzer that this counts as a crash. +*/ +static void abendError(const char *zFormat, ...){ + va_list ap; + if( g.zTestName[0] ){ + fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName); + }else{ + fprintf(stderr, "%s: ", g.zArgv0); + } + va_start(ap, zFormat); + vfprintf(stderr, zFormat, ap); + va_end(ap); + fprintf(stderr, "\n"); + abort(); +} +/* +** Print an error message and quit, but not in a way that would look +** like a crash. +*/ +static void fatalError(const char *zFormat, ...){ + va_list ap; + if( g.zTestName[0] ){ + fprintf(stderr, "%s (%s): ", g.zArgv0, g.zTestName); + }else{ + fprintf(stderr, "%s: ", g.zArgv0); + } + va_start(ap, zFormat); + vfprintf(stderr, zFormat, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(1); +} + +/* +** Evaluate some SQL. Abort if unable. +*/ +static void sqlexec(sqlite3 *db, const char *zFormat, ...){ + va_list ap; + char *zSql; + char *zErrMsg = 0; + int rc; + va_start(ap, zFormat); + zSql = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg); + if( rc ) abendError("failed sql [%s]: %s", zSql, zErrMsg); + sqlite3_free(zSql); +} + +/* +** This callback is invoked by sqlite3_log(). +*/ +static void shellLog(void *pNotUsed, int iErrCode, const char *zMsg){ + printf("LOG: (%d) %s\n", iErrCode, zMsg); + fflush(stdout); +} +static void shellLogNoop(void *pNotUsed, int iErrCode, const char *zMsg){ + return; +} + +/* +** This callback is invoked by sqlite3_exec() to return query results. +*/ +static int execCallback(void *NotUsed, int argc, char **argv, char **colv){ + int i; + static unsigned cnt = 0; + printf("ROW #%u:\n", ++cnt); + for(i=0; inUsed+p->szSep+1 > p->nAlloc ){ + char *zNew; + p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1; + /* Using sqlite3_realloc64() would be better, but it is a recent + ** addition and will cause a segfault if loaded by an older version + ** of SQLite. */ + zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0; + if( zNew==0 ){ + sqlite3_free(p->z); + memset(p, 0, sizeof(*p)); + return 1; + } + p->z = zNew; + } + if( p->nUsed>0 ){ + memcpy(&p->z[p->nUsed], p->zSep, p->szSep); + p->nUsed += p->szSep; + } + memcpy(&p->z[p->nUsed], z, sz); + p->nUsed += sz; + } + return 0; +} + +/* +** Implementation of the eval(X) and eval(X,Y) SQL functions. +** +** Evaluate the SQL text in X. Return the results, using string +** Y as the separator. If Y is omitted, use a single space character. +*/ +static void sqlEvalFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zSql; + sqlite3 *db; + char *zErr = 0; + int rc; + struct EvalResult x; + + memset(&x, 0, sizeof(x)); + x.zSep = " "; + zSql = (const char*)sqlite3_value_text(argv[0]); + if( zSql==0 ) return; + if( argc>1 ){ + x.zSep = (const char*)sqlite3_value_text(argv[1]); + if( x.zSep==0 ) return; + } + x.szSep = (int)strlen(x.zSep); + db = sqlite3_context_db_handle(context); + rc = sqlite3_exec(db, zSql, callback, &x, &zErr); + if( rc!=SQLITE_OK ){ + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + }else if( x.zSep==0 ){ + sqlite3_result_error_nomem(context); + sqlite3_free(x.z); + }else{ + sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free); + } +} +/* End of the eval() implementation +******************************************************************************/ + +/* +** Print sketchy documentation for this utility program +*/ +static void showHelp(void){ + printf("Usage: %s [options] ?FILE...?\n", g.zArgv0); + printf( +"Read SQL text from FILE... (or from standard input if FILE... is omitted)\n" +"and then evaluate each block of SQL contained therein.\n" +"Options:\n" +" --autovacuum Enable AUTOVACUUM mode\n" +" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n" +" --help Show this help text\n" +" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" +" --oom Run each test multiple times in a simulated OOM loop\n" +" --pagesize N Set the page size to N\n" +" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n" +" -q Reduced output\n" +" --quiet Reduced output\n" +" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n" +" --unique-cases FILE Write all unique test cases to FILE\n" +" --utf16be Set text encoding to UTF-16BE\n" +" --utf16le Set text encoding to UTF-16LE\n" +" -v Increased output\n" +" --verbose Increased output\n" + ); +} + +/* +** Return the value of a hexadecimal digit. Return -1 if the input +** is not a hex digit. +*/ +static int hexDigitValue(char c){ + if( c>='0' && c<='9' ) return c - '0'; + if( c>='a' && c<='f' ) return c - 'a' + 10; + if( c>='A' && c<='F' ) return c - 'A' + 10; + return -1; +} + +/* +** Interpret zArg as an integer value, possibly with suffixes. +*/ +static int integerValue(const char *zArg){ + sqlite3_int64 v = 0; + static const struct { char *zSuffix; int iMult; } aMult[] = { + { "KiB", 1024 }, + { "MiB", 1024*1024 }, + { "GiB", 1024*1024*1024 }, + { "KB", 1000 }, + { "MB", 1000000 }, + { "GB", 1000000000 }, + { "K", 1000 }, + { "M", 1000000 }, + { "G", 1000000000 }, + }; + int i; + int isNeg = 0; + if( zArg[0]=='-' ){ + isNeg = 1; + zArg++; + }else if( zArg[0]=='+' ){ + zArg++; + } + if( zArg[0]=='0' && zArg[1]=='x' ){ + int x; + zArg += 2; + while( (x = hexDigitValue(zArg[0]))>=0 ){ + v = (v<<4) + x; + zArg++; + } + }else{ + while( isdigit(zArg[0]) ){ + v = v*10 + zArg[0] - '0'; + zArg++; + } + } + for(i=0; i0x7fffffff ) abendError("parameter too large - max 2147483648"); + return (int)(isNeg? -v : v); +} + +/* Return the current wall-clock time */ +static sqlite3_int64 timeOfDay(void){ + static sqlite3_vfs *clockVfs = 0; + sqlite3_int64 t; + if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); + if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){ + clockVfs->xCurrentTimeInt64(clockVfs, &t); + }else{ + double r; + clockVfs->xCurrentTime(clockVfs, &r); + t = (sqlite3_int64)(r*86400000.0); + } + return t; +} + +int main(int argc, char **argv){ + char *zIn = 0; /* Input text */ + int nAlloc = 0; /* Number of bytes allocated for zIn[] */ + int nIn = 0; /* Number of bytes of zIn[] used */ + size_t got; /* Bytes read from input */ + int rc = SQLITE_OK; /* Result codes from API functions */ + int i; /* Loop counter */ + int iNext; /* Next block of SQL */ + sqlite3 *db; /* Open database */ + char *zErrMsg = 0; /* Error message returned from sqlite3_exec() */ + const char *zEncoding = 0; /* --utf16be or --utf16le */ + int nHeap = 0, mnHeap = 0; /* Heap size from --heap */ + int nLook = 0, szLook = 0; /* --lookaside configuration */ + int nPCache = 0, szPCache = 0;/* --pcache configuration */ + int nScratch = 0, szScratch=0;/* --scratch configuration */ + int pageSize = 0; /* Desired page size. 0 means default */ + void *pHeap = 0; /* Allocated heap space */ + void *pLook = 0; /* Allocated lookaside space */ + void *pPCache = 0; /* Allocated storage for pcache */ + void *pScratch = 0; /* Allocated storage for scratch */ + int doAutovac = 0; /* True for --autovacuum */ + char *zSql; /* SQL to run */ + char *zToFree = 0; /* Call sqlite3_free() on this afte running zSql */ + int verboseFlag = 0; /* --verbose or -v flag */ + int quietFlag = 0; /* --quiet or -q flag */ + int nTest = 0; /* Number of test cases run */ + int multiTest = 0; /* True if there will be multiple test cases */ + int lastPct = -1; /* Previous percentage done output */ + sqlite3 *dataDb = 0; /* Database holding compacted input data */ + sqlite3_stmt *pStmt = 0; /* Statement to insert testcase into dataDb */ + const char *zDataOut = 0; /* Write compacted data to this output file */ + int nHeader = 0; /* Bytes of header comment text on input file */ + int oomFlag = 0; /* --oom */ + int oomCnt = 0; /* Counter for the OOM loop */ + char zErrBuf[200]; /* Space for the error message */ + const char *zFailCode; /* Value of the TEST_FAILURE environment var */ + const char *zPrompt; /* Initial prompt when large-file fuzzing */ + int nInFile = 0; /* Number of input files to read */ + char **azInFile = 0; /* Array of input file names */ + int jj; /* Loop counter for azInFile[] */ + sqlite3_int64 iBegin; /* Start time for the whole program */ + sqlite3_int64 iStart, iEnd; /* Start and end-times for a test case */ + + iBegin = timeOfDay(); + zFailCode = getenv("TEST_FAILURE"); + g.zArgv0 = argv[0]; + zPrompt = ""; + for(i=1; i=argc-2 ) abendError("missing arguments on %s\n", argv[i]); + nHeap = integerValue(argv[i+1]); + mnHeap = integerValue(argv[i+2]); + i += 2; + }else + if( strcmp(z,"help")==0 ){ + showHelp(); + return 0; + }else + if( strcmp(z,"lookaside")==0 ){ + if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]); + nLook = integerValue(argv[i+1]); + szLook = integerValue(argv[i+2]); + i += 2; + }else + if( strcmp(z,"oom")==0 ){ + oomFlag = 1; + }else + if( strcmp(z,"pagesize")==0 ){ + if( i>=argc-1 ) abendError("missing argument on %s", argv[i]); + pageSize = integerValue(argv[++i]); + }else + if( strcmp(z,"pcache")==0 ){ + if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]); + nPCache = integerValue(argv[i+1]); + szPCache = integerValue(argv[i+2]); + i += 2; + }else + if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){ + quietFlag = 1; + verboseFlag = 0; + }else + if( strcmp(z,"scratch")==0 ){ + if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]); + nScratch = integerValue(argv[i+1]); + szScratch = integerValue(argv[i+2]); + i += 2; + }else + if( strcmp(z, "unique-cases")==0 ){ + if( i>=argc-1 ) abendError("missing arguments on %s", argv[i]); + if( zDataOut ) abendError("only one --minimize allowed"); + zDataOut = argv[++i]; + }else + if( strcmp(z,"utf16le")==0 ){ + zEncoding = "utf16le"; + }else + if( strcmp(z,"utf16be")==0 ){ + zEncoding = "utf16be"; + }else + if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){ + quietFlag = 0; + verboseFlag = 1; + }else + { + abendError("unknown option: %s", argv[i]); + } + }else{ + addNewInFile: + nInFile++; + azInFile = realloc(azInFile, sizeof(azInFile[0])*nInFile); + if( azInFile==0 ) abendError("out of memory"); + azInFile[nInFile-1] = argv[i]; + } + } + + /* Do global SQLite initialization */ + sqlite3_config(SQLITE_CONFIG_LOG, verboseFlag ? shellLog : shellLogNoop, 0); + if( nHeap>0 ){ + pHeap = malloc( nHeap ); + if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap); + rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap); + if( rc ) abendError("heap configuration failed: %d\n", rc); + } + if( oomFlag ){ + sqlite3_config(SQLITE_CONFIG_GETMALLOC, &g.sOrigMem); + g.sOomMem = g.sOrigMem; + g.sOomMem.xMalloc = oomMalloc; + g.sOomMem.xRealloc = oomRealloc; + sqlite3_config(SQLITE_CONFIG_MALLOC, &g.sOomMem); + } + if( nLook>0 ){ + sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0); + if( szLook>0 ){ + pLook = malloc( nLook*szLook ); + if( pLook==0 ) fatalError("out of memory"); + } + } + if( nScratch>0 && szScratch>0 ){ + pScratch = malloc( nScratch*(sqlite3_int64)szScratch ); + if( pScratch==0 ) fatalError("cannot allocate %lld-byte scratch", + nScratch*(sqlite3_int64)szScratch); + rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch); + if( rc ) abendError("scratch configuration failed: %d\n", rc); + } + if( nPCache>0 && szPCache>0 ){ + pPCache = malloc( nPCache*(sqlite3_int64)szPCache ); + if( pPCache==0 ) fatalError("cannot allocate %lld-byte pcache", + nPCache*(sqlite3_int64)szPCache); + rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache); + if( rc ) abendError("pcache configuration failed: %d", rc); + } + + /* If the --unique-cases option was supplied, open the database that will + ** be used to gather unique test cases. + */ + if( zDataOut ){ + rc = sqlite3_open(":memory:", &dataDb); + if( rc ) abendError("cannot open :memory: database"); + rc = sqlite3_exec(dataDb, + "CREATE TABLE testcase(sql BLOB PRIMARY KEY, tm) WITHOUT ROWID;",0,0,0); + if( rc ) abendError("%s", sqlite3_errmsg(dataDb)); + rc = sqlite3_prepare_v2(dataDb, + "INSERT OR IGNORE INTO testcase(sql,tm)VALUES(?1,?2)", + -1, &pStmt, 0); + if( rc ) abendError("%s", sqlite3_errmsg(dataDb)); + } + + /* Initialize the input buffer used to hold SQL text */ + if( nInFile==0 ) nInFile = 1; + nAlloc = 1000; + zIn = malloc(nAlloc); + if( zIn==0 ) fatalError("out of memory"); + + /* Loop over all input files */ + for(jj=0; jj****/"); + if( z ){ + z += 6; + sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*s", + (int)(z-&zIn[i]) - 12, &zIn[i+6]); + if( verboseFlag ){ + printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]); + fflush(stdout); + } + i += (int)(z-&zIn[i]); + multiTest = 1; + } + } + for(iNext=i; iNext1 ){ + printf("%s\n", zPrompt); + } + fflush(stdout); + + /* Run the next test case. Run it multiple times in --oom mode + */ + if( oomFlag ){ + oomCnt = g.iOomCntdown = 1; + g.nOomFault = 0; + g.bOomOnce = 1; + if( verboseFlag ){ + printf("Once.%d\n", oomCnt); + fflush(stdout); + } + }else{ + oomCnt = 0; + } + do{ + rc = sqlite3_open_v2( + "main.db", &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, + 0); + if( rc!=SQLITE_OK ){ + abendError("Unable to open the in-memory database"); + } + if( pLook ){ + rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook); + if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc); + } + #ifndef SQLITE_OMIT_TRACE + sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0); + #endif + sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0); + sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0); + sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000); + if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding); + if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize); + if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL"); + iStart = timeOfDay(); + g.bOomEnable = 1; + if( verboseFlag ){ + zErrMsg = 0; + rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg); + if( zErrMsg ){ + sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg); + zErrMsg = 0; + } + }else { + rc = sqlite3_exec(db, zSql, execNoop, 0, 0); + } + g.bOomEnable = 0; + iEnd = timeOfDay(); + rc = sqlite3_close(db); + if( rc ){ + abendError("sqlite3_close() failed with rc=%d", rc); + } + if( !zDataOut && sqlite3_memory_used()>0 ){ + abendError("memory in use after close: %lld bytes",sqlite3_memory_used()); + } + if( oomFlag ){ + /* Limit the number of iterations of the OOM loop to OOM_MAX. If the + ** first pass (single failure) exceeds 2/3rds of OOM_MAX this skip the + ** second pass (continuous failure after first) completely. */ + if( g.nOomFault==0 || oomCnt>OOM_MAX ){ + if( g.bOomOnce && oomCnt<=(OOM_MAX*2/3) ){ + oomCnt = g.iOomCntdown = 1; + g.bOomOnce = 0; + }else{ + oomCnt = 0; + } + }else{ + g.iOomCntdown = ++oomCnt; + g.nOomFault = 0; + } + if( oomCnt ){ + if( verboseFlag ){ + printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt); + fflush(stdout); + } + nTest++; + } + } + }while( oomCnt>0 ); + + /* Store unique test cases in the in the dataDb database if the + ** --unique-cases flag is present + */ + if( zDataOut ){ + sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC); + sqlite3_bind_int64(pStmt, 2, iEnd - iStart); + rc = sqlite3_step(pStmt); + if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb)); + sqlite3_reset(pStmt); + } + + /* Free the SQL from the current test case + */ + if( zToFree ){ + sqlite3_free(zToFree); + zToFree = 0; + } + zIn[iNext] = cSaved; + + /* Show test-case results in --verbose mode + */ + if( verboseFlag ){ + printf("RESULT-CODE: %d\n", rc); + if( zErrMsg ){ + printf("ERROR-MSG: [%s]\n", zErrBuf); + } + fflush(stdout); + } + + /* Simulate an error if the TEST_FAILURE environment variable is "5". + ** This is used to verify that automated test script really do spot + ** errors that occur in this test program. + */ + if( zFailCode ){ + if( zFailCode[0]=='5' && zFailCode[1]==0 ){ + abendError("simulated failure"); + }else if( zFailCode[0]!=0 ){ + /* If TEST_FAILURE is something other than 5, just exit the test + ** early */ + printf("\nExit early due to TEST_FAILURE being set"); + break; + } + } + } + if( !verboseFlag && multiTest && !quietFlag && !oomFlag ) printf("\n"); + } + + /* Report total number of tests run + */ + if( nTest>1 && !quietFlag ){ + sqlite3_int64 iElapse = timeOfDay() - iBegin; + printf("%s: 0 errors out of %d tests in %d.%03d seconds\nSQLite %s %s\n", + g.zArgv0, nTest, (int)(iElapse/1000), (int)(iElapse%1000), + sqlite3_libversion(), sqlite3_sourceid()); + } + + /* Write the unique test cases if the --unique-cases flag was used + */ + if( zDataOut ){ + int n = 0; + FILE *out = fopen(zDataOut, "wb"); + if( out==0 ) abendError("cannot open %s for writing", zDataOut); + if( nHeader>0 ) fwrite(zIn, nHeader, 1, out); + sqlite3_finalize(pStmt); + rc = sqlite3_prepare_v2(dataDb, "SELECT sql, tm FROM testcase ORDER BY tm, sql", + -1, &pStmt, 0); + if( rc ) abendError("%s", sqlite3_errmsg(dataDb)); + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + fprintf(out,"/****<%d:%dms>****/", ++n, sqlite3_column_int(pStmt,1)); + fwrite(sqlite3_column_blob(pStmt,0),sqlite3_column_bytes(pStmt,0),1,out); + } + fclose(out); + sqlite3_finalize(pStmt); + sqlite3_close(dataDb); + } + + /* Clean up and exit. + */ + free(azInFile); + free(zIn); + free(pHeap); + free(pLook); + free(pScratch); + free(pPCache); + return 0; +} diff --git a/tool/lemon.c b/tool/lemon.c index 4ada425..89d992c 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -1114,7 +1114,6 @@ void FindActions(struct lemon *lemp) /* Resolve conflicts */ for(i=0; instate; i++){ struct action *ap, *nap; - struct state *stp; stp = lemp->sorted[i]; /* assert( stp->ap ); */ stp->ap = Action_sort(stp->ap); @@ -1731,7 +1730,7 @@ static char *msort( char *ep; char *set[LISTSIZE]; int i; - offset = (unsigned long)next - (unsigned long)list; + offset = (unsigned long)((char*)next - (char*)list); for(i=0; iinclude,&lineno); if( mhflag ){ - char *name = file_makename(lemp, ".h"); - fprintf(out,"#include \"%s\"\n", name); lineno++; - free(name); + char *incName = file_makename(lemp, ".h"); + fprintf(out,"#include \"%s\"\n", incName); lineno++; + free(incName); } tplt_xfer(lemp->name,in,out,&lineno); @@ -3791,7 +3790,6 @@ void ReportTable( } name = lemp->name ? lemp->name : "Parse"; if( lemp->arg && lemp->arg[0] ){ - int i; i = lemonStrlen(lemp->arg); while( i>=1 && isspace(lemp->arg[i-1]) ) i--; while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; @@ -4479,18 +4477,18 @@ int Strsafe_insert(const char *data) } if( x1a->count>=x1a->size ){ /* Need to make the hash table bigger */ - int i,size; + int i,arrSize; struct s_x1 array; - array.size = size = x1a->size*2; + array.size = arrSize = x1a->size*2; array.count = x1a->count; - array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*)); + array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ - array.ht = (x1node**)&(array.tbl[size]); - for(i=0; icount; i++){ x1node *oldnp, *newnp; oldnp = &(x1a->tbl[i]); - h = strhash(oldnp->data) & (size-1); + h = strhash(oldnp->data) & (arrSize-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; @@ -4646,18 +4644,18 @@ int Symbol_insert(struct symbol *data, const char *key) } if( x2a->count>=x2a->size ){ /* Need to make the hash table bigger */ - int i,size; + int i,arrSize; struct s_x2 array; - array.size = size = x2a->size*2; + array.size = arrSize = x2a->size*2; array.count = x2a->count; - array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*)); + array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ - array.ht = (x2node**)&(array.tbl[size]); - for(i=0; icount; i++){ x2node *oldnp, *newnp; oldnp = &(x2a->tbl[i]); - h = strhash(oldnp->key) & (size-1); + h = strhash(oldnp->key) & (arrSize-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; @@ -4722,12 +4720,12 @@ int Symbol_count() struct symbol **Symbol_arrayof() { struct symbol **array; - int i,size; + int i,arrSize; if( x2a==0 ) return 0; - size = x2a->count; - array = (struct symbol **)calloc(size, sizeof(struct symbol *)); + arrSize = x2a->count; + array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *)); if( array ){ - for(i=0; itbl[i].data; + for(i=0; itbl[i].data; } return array; } @@ -4843,18 +4841,18 @@ int State_insert(struct state *data, struct config *key) } if( x3a->count>=x3a->size ){ /* Need to make the hash table bigger */ - int i,size; + int i,arrSize; struct s_x3 array; - array.size = size = x3a->size*2; + array.size = arrSize = x3a->size*2; array.count = x3a->count; - array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*)); + array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ - array.ht = (x3node**)&(array.tbl[size]); - for(i=0; icount; i++){ x3node *oldnp, *newnp; oldnp = &(x3a->tbl[i]); - h = statehash(oldnp->key) & (size-1); + h = statehash(oldnp->key) & (arrSize-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; @@ -4901,12 +4899,12 @@ struct state *State_find(struct config *key) struct state **State_arrayof() { struct state **array; - int i,size; + int i,arrSize; if( x3a==0 ) return 0; - size = x3a->count; - array = (struct state **)calloc(size, sizeof(struct state *)); + arrSize = x3a->count; + array = (struct state **)calloc(arrSize, sizeof(struct state *)); if( array ){ - for(i=0; itbl[i].data; + for(i=0; itbl[i].data; } return array; } @@ -4983,18 +4981,18 @@ int Configtable_insert(struct config *data) } if( x4a->count>=x4a->size ){ /* Need to make the hash table bigger */ - int i,size; + int i,arrSize; struct s_x4 array; - array.size = size = x4a->size*2; + array.size = arrSize = x4a->size*2; array.count = x4a->count; - array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*)); + array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*)); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ - array.ht = (x4node**)&(array.tbl[size]); - for(i=0; icount; i++){ x4node *oldnp, *newnp; oldnp = &(x4a->tbl[i]); - h = confighash(oldnp->data) & (size-1); + h = confighash(oldnp->data) & (arrSize-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index 21503d1..964946e 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -4,10 +4,10 @@ # # To add new pragmas, first add the name and other relevant attributes # of the pragma to the "pragma_def" object below. Then run this script -# to generate the C-code for the lookup table and copy/paste the output -# of this script into the appropriate spot in the pragma.c source file. +# to generate the ../src/pragma.h header file that contains macros and +# the lookup table needed for pragma name lookup in the pragma.c module. # Then add the extra "case PragTyp_XXXXX:" and subsequent code for the -# new pragma. +# new pragma in ../src/pragma.c. # set pragma_def { @@ -205,6 +205,14 @@ set pragma_def { IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) NAME: index_info + TYPE: INDEX_INFO + ARG: 0 + FLAG: NeedSchema + IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + + NAME: index_xinfo + TYPE: INDEX_INFO + ARG: 1 FLAG: NeedSchema IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) @@ -308,7 +316,20 @@ set pragma_def { NAME: threads } -fconfigure stdout -translation lf + +# Open the output file +# +set destfile "[file dir [file dir [file normal $argv0]]]/src/pragma.h" +puts "Overwriting $destfile with new pragma table..." +set fd [open $destfile wb] +puts $fd {/* DO NOT EDIT! +** This file is automatically generated by the script at +** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit +** that script and rerun it. +*/} + +# Parse the PRAGMA table above. +# set name {} set type {} set if {} @@ -362,7 +383,7 @@ foreach name $allnames { set if [lindex $allbyname($name) 2] if {[regexp SQLITE_DEBUG $if] || [regexp SQLITE_HAS_CODEC $if]} continue set seentype($type) 1 - puts [format {#define %-35s %4d} PragTyp_$type $pnum] + puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum] incr pnum } foreach name $allnames { @@ -371,14 +392,14 @@ foreach name $allnames { set if [lindex $allbyname($name) 2] if {[regexp SQLITE_DEBUG $if]} continue set seentype($type) 1 - puts [format {#define %-35s %4d} PragTyp_$type $pnum] + puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum] incr pnum } foreach name $allnames { set type [lindex $allbyname($name) 0] if {[info exists seentype($type)]} continue set seentype($type) 1 - puts [format {#define %-35s %4d} PragTyp_$type $pnum] + puts $fd [format {#define %-35s %4d} PragTyp_$type $pnum] incr pnum } @@ -386,18 +407,18 @@ foreach name $allnames { # set fv 1 foreach f [lsort [array names allflags]] { - puts [format {#define PragFlag_%-20s 0x%02x} $f $fv] + puts $fd [format {#define PragFlag_%-20s 0x%02x} $f $fv] set fv [expr {$fv*2}] } # Generate the lookup table # -puts "static const struct sPragmaNames \173" -puts " const char *const zName; /* Name of pragma */" -puts " u8 ePragTyp; /* PragTyp_XXX value */" -puts " u8 mPragFlag; /* Zero or more PragFlag_XXX values */" -puts " u32 iArg; /* Extra argument */" -puts "\175 aPragmaNames\[\] = \173" +puts $fd "static const struct sPragmaNames \173" +puts $fd " const char *const zName; /* Name of pragma */" +puts $fd " u8 ePragTyp; /* PragTyp_XXX value */" +puts $fd " u8 mPragFlag; /* Zero or more PragFlag_XXX values */" +puts $fd " u32 iArg; /* Extra argument */" +puts $fd "\175 aPragmaNames\[\] = \173" set current_if {} set spacer [format { %26s } {}] @@ -406,13 +427,13 @@ foreach name $allnames { if {$if!=$current_if} { if {$current_if!=""} { foreach this_if $current_if { - puts "#endif" + puts $fd "#endif" } } set current_if $if if {$current_if!=""} { foreach this_if $current_if { - puts "#if $this_if" + puts $fd "#if $this_if" } } } @@ -422,17 +443,17 @@ foreach name $allnames { } else { set flagx PragFlag_[join $flag {|PragFlag_}] } - puts " \173 /* zName: */ \"$name\"," - puts " /* ePragTyp: */ PragTyp_$type," - puts " /* ePragFlag: */ $flagx," - puts " /* iArg: */ $arg \175," + puts $fd " \173 /* zName: */ \"$name\"," + puts $fd " /* ePragTyp: */ PragTyp_$type," + puts $fd " /* ePragFlag: */ $flagx," + puts $fd " /* iArg: */ $arg \175," } if {$current_if!=""} { foreach this_if $current_if { - puts "#endif" + puts $fd "#endif" } } -puts "\175;" +puts $fd "\175;" # count the number of pragmas, for information purposes # @@ -444,4 +465,4 @@ foreach name $allnames { if {[regexp {^defined} $if] || [regexp {[^!]defined} $if]} continue incr dfltcnt } -puts "/* Number of pragmas: $dfltcnt on by default, $allcnt total. */" +puts $fd "/* Number of pragmas: $dfltcnt on by default, $allcnt total. */" diff --git a/tool/mksqlite3c-noext.tcl b/tool/mksqlite3c-noext.tcl index 2752226..0e1d0fc 100644 --- a/tool/mksqlite3c-noext.tcl +++ b/tool/mksqlite3c-noext.tcl @@ -17,13 +17,13 @@ # After the "tsrc" directory has been created and populated, run # this script: # -# tclsh mksqlite3c.tcl +# tclsh mksqlite3c-noext.tcl # # The amalgamated SQLite code will be written into sqlite3.c # # Begin by reading the "sqlite3.h" header file. Extract the version number -# from in this file. The versioon number is needed to generate the header +# from in this file. The version number is needed to generate the header # comment of the amalgamation. # if {[lsearch $argv --nostatic]>=0} { @@ -80,9 +80,6 @@ if {$addstatic} { puts $out \ {#ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static -#endif -#ifndef SQLITE_API -# define SQLITE_API #endif} } @@ -106,6 +103,7 @@ foreach hdr { pager.h parse.h pcache.h + pragma.h sqlite3ext.h sqlite3.h sqliteicu.h @@ -113,12 +111,31 @@ foreach hdr { sqliteLimit.h vdbe.h vdbeInt.h + vxworks.h wal.h + whereInt.h } { set available_hdr($hdr) 1 } set available_hdr(sqliteInt.h) 0 +# These headers should be copied into the amalgamation without modifying any +# of their function declarations or definitions. +set varonly_hdr(sqlite3.h) 1 + +# These are the functions that accept a variable number of arguments. They +# always need to use the "cdecl" calling convention even when another calling +# convention (e.g. "stcall") is being used for the rest of the library. +set cdecllist { + sqlite3_config + sqlite3_db_config + sqlite3_log + sqlite3_mprintf + sqlite3_snprintf + sqlite3_test_control + sqlite3_vtab_config +} + # 78 stars used for comment formatting. set s78 \ {*****************************************************************************} @@ -135,21 +152,21 @@ proc section_comment {text} { # Read the source file named $filename and write it into the # sqlite3.c output file. If any #include statements are seen, -# process them approprately. +# process them appropriately. # proc copy_file {filename} { - global seen_hdr available_hdr out addstatic linemacros + global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros set ln 0 set tail [file tail $filename] section_comment "Begin file $tail" if {$linemacros} {puts $out "#line 1 \"$filename\""} set in [open $filename r] set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)} - set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(} + set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)} if {[file extension $filename]==".h"} { set declpattern " *$declpattern" } - set declpattern ^$declpattern + set declpattern ^$declpattern\$ while {![eof $in]} { set line [gets $in] incr ln @@ -165,42 +182,67 @@ proc copy_file {filename} { if {$linemacros} {puts $out "#line [expr {$ln+1}] \"$filename\""} } } elseif {![info exists seen_hdr($hdr)]} { - set seen_hdr($hdr) 1 + if {![regexp {/\*\s+amalgamator:\s+dontcache\s+\*/} $line]} { + set seen_hdr($hdr) 1 + } + puts $out $line + } elseif {[regexp {/\*\s+amalgamator:\s+keep\s+\*/} $line]} { + # This include file must be kept because there was a "keep" + # directive inside of a line comment. puts $out $line } else { - puts $out "/* $line */" + # Comment out the entire line, replacing any nested comment + # begin/end markers with the harmless substring "**". + puts $out "/* [string map [list /* ** */ **] $line] */" } } elseif {[regexp {^#ifdef __cplusplus} $line]} { puts $out "#if 0" } elseif {!$linemacros && [regexp {^#line} $line]} { # Skip #line directives. } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} { - regsub {^SQLITE_API } $line {} line - if {[regexp $declpattern $line all funcname]} { + # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before + # functions if this header file does not need it. + if {![info exists varonly_hdr($tail)] + && [regexp $declpattern $line all rettype funcname rest]} { + regsub {^SQLITE_API } $line {} line # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions. # so that linkage can be modified at compile-time. if {[regexp {^sqlite3_} $funcname]} { - puts $out "SQLITE_API $line" + set line SQLITE_API + append line " " [string trim $rettype] + if {[string index $rettype end] ne "*"} { + append line " " + } + if {[lsearch -exact $cdecllist $funcname] >= 0} { + append line SQLITE_CDECL + } else { + append line SQLITE_STDCALL + } + append line " " $funcname $rest + puts $out $line } else { puts $out "SQLITE_PRIVATE $line" } } elseif {[regexp $varpattern $line all varname]} { - # Add the SQLITE_PRIVATE before variable declarations or - # definitions for internal use - if {![regexp {^sqlite3_} $varname]} { - regsub {^extern } $line {} line - puts $out "SQLITE_PRIVATE $line" - } else { - if {[regexp {const char sqlite3_version\[\];} $line]} { - set line {const char sqlite3_version[] = SQLITE_VERSION;} + # Add the SQLITE_PRIVATE before variable declarations or + # definitions for internal use + regsub {^SQLITE_API } $line {} line + if {![regexp {^sqlite3_} $varname]} { + regsub {^extern } $line {} line + puts $out "SQLITE_PRIVATE $line" + } else { + if {[regexp {const char sqlite3_version\[\];} $line]} { + set line {const char sqlite3_version[] = SQLITE_VERSION;} + } + regsub {^SQLITE_EXTERN } $line {} line + puts $out "SQLITE_API $line" } - regsub {^SQLITE_EXTERN } $line {} line - puts $out "SQLITE_API $line" - } } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} { + regsub {^SQLITE_API } $line {} line regsub {^SQLITE_EXTERN } $line {} line - puts $out "SQLITE_PRIVATE $line" + puts $out $line } elseif {[regexp {^void \(\*sqlite3Os} $line]} { + regsub {^SQLITE_API } $line {} line puts $out "SQLITE_PRIVATE $line" } else { puts $out $line diff --git a/tool/mksqlite3c.tcl b/tool/mksqlite3c.tcl index 1d597a5..0c2f3e7 100644 --- a/tool/mksqlite3c.tcl +++ b/tool/mksqlite3c.tcl @@ -17,7 +17,7 @@ # After the "tsrc" directory has been created and populated, run # this script: # -# tclsh mksqlite3c.tcl +# tclsh mksqlite3c.tcl --srcdir $SRC # # The amalgamated SQLite code will be written into sqlite3.c # @@ -26,15 +26,17 @@ # from in this file. The version number is needed to generate the header # comment of the amalgamation. # -if {[lsearch $argv --nostatic]>=0} { - set addstatic 0 -} else { - set addstatic 1 -} -if {[lsearch $argv --linemacros]>=0} { - set linemacros 1 -} else { - set linemacros 0 +set addstatic 1 +set linemacros 0 +for {set i 0} {$i<[llength $argv]} {incr i} { + set x [lindex $argv $i] + if {[regexp {^-+nostatic$} $x]} { + set addstatic 0 + } elseif {[regexp {^-+linemacros} $x]} { + set linemacros 1 + } else { + error "unknown command-line option: $x" + } } set in [open tsrc/sqlite3.h] set cnt 0 @@ -80,9 +82,6 @@ if {$addstatic} { puts $out \ {#ifndef SQLITE_PRIVATE # define SQLITE_PRIVATE static -#endif -#ifndef SQLITE_API -# define SQLITE_API #endif} } @@ -110,6 +109,7 @@ foreach hdr { pager.h parse.h pcache.h + pragma.h rtree.h sqlite3ext.h sqlite3.h @@ -118,6 +118,7 @@ foreach hdr { sqliteLimit.h vdbe.h vdbeInt.h + vxworks.h wal.h whereInt.h } { @@ -125,6 +126,23 @@ foreach hdr { } set available_hdr(sqliteInt.h) 0 +# These headers should be copied into the amalgamation without modifying any +# of their function declarations or definitions. +set varonly_hdr(sqlite3.h) 1 + +# These are the functions that accept a variable number of arguments. They +# always need to use the "cdecl" calling convention even when another calling +# convention (e.g. "stcall") is being used for the rest of the library. +set cdecllist { + sqlite3_config + sqlite3_db_config + sqlite3_log + sqlite3_mprintf + sqlite3_snprintf + sqlite3_test_control + sqlite3_vtab_config +} + # 78 stars used for comment formatting. set s78 \ {*****************************************************************************} @@ -144,18 +162,18 @@ proc section_comment {text} { # process them appropriately. # proc copy_file {filename} { - global seen_hdr available_hdr out addstatic linemacros + global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros set ln 0 set tail [file tail $filename] section_comment "Begin file $tail" if {$linemacros} {puts $out "#line 1 \"$filename\""} set in [open $filename r] set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+(sqlite3[_a-zA-Z0-9]+)(\[|;| =)} - set declpattern {[a-zA-Z][a-zA-Z_0-9 ]+ \**(sqlite3[_a-zA-Z0-9]+)\(} + set declpattern {([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3[_a-zA-Z0-9]+)(\(.*)} if {[file extension $filename]==".h"} { set declpattern " *$declpattern" } - set declpattern ^$declpattern + set declpattern ^$declpattern\$ while {![eof $in]} { set line [gets $in] incr ln @@ -189,32 +207,49 @@ proc copy_file {filename} { } elseif {!$linemacros && [regexp {^#line} $line]} { # Skip #line directives. } elseif {$addstatic && ![regexp {^(static|typedef)} $line]} { - regsub {^SQLITE_API } $line {} line - if {[regexp $declpattern $line all funcname]} { + # Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before + # functions if this header file does not need it. + if {![info exists varonly_hdr($tail)] + && [regexp $declpattern $line all rettype funcname rest]} { + regsub {^SQLITE_API } $line {} line # Add the SQLITE_PRIVATE or SQLITE_API keyword before functions. # so that linkage can be modified at compile-time. if {[regexp {^sqlite3_} $funcname]} { - puts $out "SQLITE_API $line" + set line SQLITE_API + append line " " [string trim $rettype] + if {[string index $rettype end] ne "*"} { + append line " " + } + if {[lsearch -exact $cdecllist $funcname] >= 0} { + append line SQLITE_CDECL + } else { + append line SQLITE_STDCALL + } + append line " " $funcname $rest + puts $out $line } else { puts $out "SQLITE_PRIVATE $line" } } elseif {[regexp $varpattern $line all varname]} { - # Add the SQLITE_PRIVATE before variable declarations or - # definitions for internal use - if {![regexp {^sqlite3_} $varname]} { - regsub {^extern } $line {} line - puts $out "SQLITE_PRIVATE $line" - } else { - if {[regexp {const char sqlite3_version\[\];} $line]} { - set line {const char sqlite3_version[] = SQLITE_VERSION;} + # Add the SQLITE_PRIVATE before variable declarations or + # definitions for internal use + regsub {^SQLITE_API } $line {} line + if {![regexp {^sqlite3_} $varname]} { + regsub {^extern } $line {} line + puts $out "SQLITE_PRIVATE $line" + } else { + if {[regexp {const char sqlite3_version\[\];} $line]} { + set line {const char sqlite3_version[] = SQLITE_VERSION;} + } + regsub {^SQLITE_EXTERN } $line {} line + puts $out "SQLITE_API $line" } - regsub {^SQLITE_EXTERN } $line {} line - puts $out "SQLITE_API $line" - } } elseif {[regexp {^(SQLITE_EXTERN )?void \(\*sqlite3IoTrace\)} $line]} { + regsub {^SQLITE_API } $line {} line regsub {^SQLITE_EXTERN } $line {} line puts $out $line } elseif {[regexp {^void \(\*sqlite3Os} $line]} { + regsub {^SQLITE_API } $line {} line puts $out "SQLITE_PRIVATE $line" } else { puts $out $line @@ -333,6 +368,7 @@ foreach file { rtree.c icu.c fts3_icu.c + dbstat.c } { copy_file tsrc/$file } diff --git a/tool/mksqlite3h.tcl b/tool/mksqlite3h.tcl index a89b9f9..cabce1f 100644 --- a/tool/mksqlite3h.tcl +++ b/tool/mksqlite3h.tcl @@ -63,7 +63,7 @@ close $in # Set up patterns for recognizing API declarations. # set varpattern {^[a-zA-Z][a-zA-Z_0-9 *]+sqlite3_[_a-zA-Z0-9]+(\[|;| =)} -set declpattern {^ *[a-zA-Z][a-zA-Z_0-9 ]+ \**sqlite3_[_a-zA-Z0-9]+\(} +set declpattern {^ *([a-zA-Z][a-zA-Z_0-9 ]+ \**)(sqlite3_[_a-zA-Z0-9]+)(\(.*)$} # Force the output to use unix line endings, even on Windows. fconfigure stdout -translation lf @@ -73,6 +73,19 @@ set filelist [subst { $TOP/ext/rtree/sqlite3rtree.h }] +# These are the functions that accept a variable number of arguments. They +# always need to use the "cdecl" calling convention even when another calling +# convention (e.g. "stcall") is being used for the rest of the library. +set cdecllist { + sqlite3_config + sqlite3_db_config + sqlite3_log + sqlite3_mprintf + sqlite3_snprintf + sqlite3_test_control + sqlite3_vtab_config +} + # Process the source files. # foreach file $filelist { @@ -89,21 +102,23 @@ foreach file $filelist { regsub -- --VERS-- $line $zVersion line regsub -- --VERSION-NUMBER-- $line $nVersion line regsub -- --SOURCE-ID-- $line "$zDate $zUuid" line - - if {[regexp {define SQLITE_EXTERN extern} $line]} { - puts $line - puts [gets $in] - puts "" - puts "#ifndef SQLITE_API" - puts "# define SQLITE_API" - puts "#endif" - set line "" - } - - if {([regexp $varpattern $line] && ![regexp {^ *typedef} $line]) - || ([regexp $declpattern $line]) - } { + + if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} { set line "SQLITE_API $line" + } else { + if {[regexp $declpattern $line all rettype funcname rest]} { + set line SQLITE_API + append line " " [string trim $rettype] + if {[string index $rettype end] ne "*"} { + append line " " + } + if {[lsearch -exact $cdecllist $funcname] >= 0} { + append line SQLITE_CDECL + } else { + append line SQLITE_STDCALL + } + append line " " $funcname $rest + } } puts $line } diff --git a/tool/mkvsix.tcl b/tool/mkvsix.tcl index 208ce2b..15ae2b0 100644 --- a/tool/mkvsix.tcl +++ b/tool/mkvsix.tcl @@ -174,6 +174,9 @@ proc writeFile { fileName data } { return "" } +# +# TODO: Modify this procedure when a new version of Visual Studio is released. +# proc getMinVsVersionXmlChunk { vsVersion } { switch -exact $vsVersion { 2012 { @@ -184,17 +187,26 @@ proc getMinVsVersionXmlChunk { vsVersion } { return [appendArgs \ "\r\n " {MinVSVersion="12.0"}] } + 2015 { + return [appendArgs \ + "\r\n " {MinVSVersion="14.0"}] + } default { return "" } } } +# +# TODO: Modify this procedure when a new version of Visual Studio is released. +# proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } { # - # NOTE: Only Visual Studio 2013 supports this SDK manifest attribute. + # NOTE: Only Visual Studio 2013 and later support this attribute within the + # SDK manifest. # - if {![string equal $vsVersion 2013]} then { + if {![string equal $vsVersion 2013] && \ + ![string equal $vsVersion 2015]} then { return "" } @@ -221,6 +233,9 @@ proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } { } } +# +# TODO: Modify this procedure when a new version of Visual Studio is released. +# proc getExtraFileListXmlChunk { packageFlavor vsVersion } { # # NOTE: Windows Phone 8.0 does not require any extra attributes in its VSIX @@ -245,6 +260,14 @@ proc getExtraFileListXmlChunk { packageFlavor vsVersion } { "\r\n " AppliesTo=\" $appliesTo \" \ "\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}] } + 2015 { + # + # TODO: Is the ".AppLocal" suffix always needed here? + # + return [appendArgs \ + "\r\n " AppliesTo=\" $appliesTo \" \ + "\r\n " {DependsOn="Microsoft.VCLibs.AppLocal, version=14.0"}] + } default { return "" } @@ -354,10 +377,11 @@ if {[string length $vsVersion] == 0} then { fail "invalid Visual Studio version" } -if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013]} then { +if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013] && \ + ![string equal $vsVersion 2015]} then { fail [appendArgs \ "unsupported Visual Studio version, must be one of: " \ - [list 2012 2013]] + [list 2012 2013 2015]] } set shortNames(WinRT,2012) SQLite.WinRT @@ -368,6 +392,7 @@ set shortNames(WP80,2013) SQLite.WP80.2013 set shortNames(WP81,2013) SQLite.WP81 set shortNames(Win32,2012) SQLite.Win32 set shortNames(Win32,2013) SQLite.Win32.2013 +set shortNames(UAP,2015) SQLite.UAP.2015 set displayNames(WinRT,2012) "SQLite for Windows Runtime" set displayNames(WinRT,2013) "SQLite for Windows Runtime" @@ -377,6 +402,7 @@ set displayNames(WP80,2013) "SQLite for Windows Phone" set displayNames(WP81,2013) "SQLite for Windows Phone 8.1" set displayNames(Win32,2012) "SQLite for Windows" set displayNames(Win32,2013) "SQLite for Windows" +set displayNames(UAP,2015) "SQLite for Universal App Platform" if {[string equal $packageFlavor WinRT]} then { set shortName $shortNames($packageFlavor,$vsVersion) @@ -432,6 +458,22 @@ if {[string equal $packageFlavor WinRT]} then { set extraSdkPath "\\..\\$targetPlatformIdentifier" set extraFileListAttributes \ [getExtraFileListXmlChunk $packageFlavor $vsVersion] +} elseif {[string equal $packageFlavor UAP]} then { + if {$vsVersion ne "2015"} then { + fail [appendArgs \ + "unsupported combination, package flavor " $packageFlavor \ + " is only supported with Visual Studio 2015"] + } + set shortName $shortNames($packageFlavor,$vsVersion) + set displayName $displayNames($packageFlavor,$vsVersion) + set targetPlatformIdentifier UAP + set targetPlatformVersion v0.8.0.0 + set minVsVersion [getMinVsVersionXmlChunk $vsVersion] + set maxPlatformVersion \ + [getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion] + set extraSdkPath "\\..\\$targetPlatformIdentifier" + set extraFileListAttributes \ + [getExtraFileListXmlChunk $packageFlavor $vsVersion] } elseif {[string equal $packageFlavor Win32]} then { set shortName $shortNames($packageFlavor,$vsVersion) set displayName $displayNames($packageFlavor,$vsVersion) @@ -446,7 +488,7 @@ if {[string equal $packageFlavor WinRT]} then { } else { fail [appendArgs \ "unsupported package flavor, must be one of: " \ - [list WinRT WinRT81 WP80 WP81 Win32]] + [list WinRT WinRT81 WP80 WP81 UAP Win32]] } ############################################################################### diff --git a/tool/showdb.c b/tool/showdb.c index 82b8c9f..c90f410 100644 --- a/tool/showdb.c +++ b/tool/showdb.c @@ -64,11 +64,13 @@ static void out_of_memory(void){ */ static unsigned char *getContent(int ofst, int nByte){ unsigned char *aData; + int got; aData = malloc(nByte+32); if( aData==0 ) out_of_memory(); memset(aData, 0, nByte+32); lseek(db, ofst, SEEK_SET); - if( read(db, aData, nByte)0 && got +#include +#include +#include +#include + +/* This utility only looks for locks in the first 2 billion bytes */ +#define MX_LCK 2147483647 + +/* +** Print all locks on the inode of "fd" that occur in between +** lwr and upr, inclusive. +*/ +static int showLocksInRange(int fd, off_t lwr, off_t upr){ + int cnt = 0; + struct flock x; + + x.l_type = F_WRLCK; + x.l_whence = SEEK_SET; + x.l_start = lwr; + x.l_len = upr-lwr; + fcntl(fd, F_GETLK, &x); + if( x.l_type==F_UNLCK ) return 0; + printf("start: %-12d len: %-5d pid: %-5d type: %s\n", + (int)x.l_start, (int)x.l_len, + x.l_pid, x.l_type==F_WRLCK ? "WRLCK" : "RDLCK"); + cnt++; + if( x.l_start>lwr ){ + cnt += showLocksInRange(fd, lwr, x.l_start-1); + } + if( x.l_start+x.l_len0 } foreach {name tblname} [concat sqlite_master sqlite_master [db eval $sql]] { set is_index [expr {$name!=$tblname}] + set idx_btree [expr {$is_index || [is_without_rowid $name]}] db eval { SELECT sum(ncell) AS nentry, - sum(isleaf(pagetype, $is_index) * ncell) AS leaf_entries, + sum(isleaf(pagetype, $idx_btree) * ncell) AS leaf_entries, sum(payload) AS payload, - sum(isoverflow(pagetype, $is_index) * payload) AS ovfl_payload, + sum(isoverflow(pagetype, $idx_btree) * payload) AS ovfl_payload, sum(path LIKE '%+000000') AS ovfl_cnt, max(mx_payload) AS mx_payload, - sum(isinternal(pagetype, $is_index)) AS int_pages, - sum(isleaf(pagetype, $is_index)) AS leaf_pages, - sum(isoverflow(pagetype, $is_index)) AS ovfl_pages, - sum(isinternal(pagetype, $is_index) * unused) AS int_unused, - sum(isleaf(pagetype, $is_index) * unused) AS leaf_unused, - sum(isoverflow(pagetype, $is_index) * unused) AS ovfl_unused, + sum(isinternal(pagetype, $idx_btree)) AS int_pages, + sum(isleaf(pagetype, $idx_btree)) AS leaf_pages, + sum(isoverflow(pagetype, $idx_btree)) AS ovfl_pages, + sum(isinternal(pagetype, $idx_btree) * unused) AS int_unused, + sum(isleaf(pagetype, $idx_btree) * unused) AS leaf_unused, + sum(isoverflow(pagetype, $idx_btree) * unused) AS ovfl_unused, sum(pgsize) AS compressed_size FROM temp.dbstat WHERE name = $name } break diff --git a/tool/sqldiff.c b/tool/sqldiff.c new file mode 100644 index 0000000..0b3f02c --- /dev/null +++ b/tool/sqldiff.c @@ -0,0 +1,1242 @@ +/* +** 2015-04-06 +** +** 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 is a utility program that computes the differences in content +** between two SQLite databases. +** +** To compile, simply link against SQLite. +** +** See the showHelp() routine below for a brief description of how to +** run the utility. +*/ +#include +#include +#include +#include +#include +#include "sqlite3.h" + +/* +** All global variables are gathered into the "g" singleton. +*/ +struct GlobalVars { + const char *zArgv0; /* Name of program */ + int bSchemaOnly; /* Only show schema differences */ + int bSchemaPK; /* Use the schema-defined PK, not the true PK */ + unsigned fDebug; /* Debug flags */ + sqlite3 *db; /* The database connection */ +} g; + +/* +** Allowed values for g.fDebug +*/ +#define DEBUG_COLUMN_NAMES 0x000001 +#define DEBUG_DIFF_SQL 0x000002 + +/* +** Dynamic string object +*/ +typedef struct Str Str; +struct Str { + char *z; /* Text of the string */ + int nAlloc; /* Bytes allocated in z[] */ + int nUsed; /* Bytes actually used in z[] */ +}; + +/* +** Initialize a Str object +*/ +static void strInit(Str *p){ + p->z = 0; + p->nAlloc = 0; + p->nUsed = 0; +} + +/* +** Print an error resulting from faulting command-line arguments and +** abort the program. +*/ +static void cmdlineError(const char *zFormat, ...){ + va_list ap; + fprintf(stderr, "%s: ", g.zArgv0); + va_start(ap, zFormat); + vfprintf(stderr, zFormat, ap); + va_end(ap); + fprintf(stderr, "\n\"%s --help\" for more help\n", g.zArgv0); + exit(1); +} + +/* +** Print an error message for an error that occurs at runtime, then +** abort the program. +*/ +static void runtimeError(const char *zFormat, ...){ + va_list ap; + fprintf(stderr, "%s: ", g.zArgv0); + va_start(ap, zFormat); + vfprintf(stderr, zFormat, ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(1); +} + +/* +** Free all memory held by a Str object +*/ +static void strFree(Str *p){ + sqlite3_free(p->z); + strInit(p); +} + +/* +** Add formatted text to the end of a Str object +*/ +static void strPrintf(Str *p, const char *zFormat, ...){ + int nNew; + for(;;){ + if( p->z ){ + va_list ap; + va_start(ap, zFormat); + sqlite3_vsnprintf(p->nAlloc-p->nUsed, p->z+p->nUsed, zFormat, ap); + va_end(ap); + nNew = (int)strlen(p->z + p->nUsed); + }else{ + nNew = p->nAlloc; + } + if( p->nUsed+nNew < p->nAlloc-1 ){ + p->nUsed += nNew; + break; + } + p->nAlloc = p->nAlloc*2 + 1000; + p->z = sqlite3_realloc(p->z, p->nAlloc); + if( p->z==0 ) runtimeError("out of memory"); + } +} + + + +/* Safely quote an SQL identifier. Use the minimum amount of transformation +** necessary to allow the string to be used with %s. +** +** Space to hold the returned string is obtained from sqlite3_malloc(). The +** caller is responsible for ensuring this space is freed when no longer +** needed. +*/ +static char *safeId(const char *zId){ + /* All SQLite keywords, in alphabetical order */ + static const char *azKeywords[] = { + "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", + "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", + "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", + "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", + "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", + "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", + "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", + "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", + "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", + "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", + "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", + "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", + "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", + "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", + "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", + "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", + "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", + "WITH", "WITHOUT", + }; + int lwr, upr, mid, c, i, x; + for(i=x=0; (c = zId[i])!=0; i++){ + if( !isalpha(c) && c!='_' ){ + if( i>0 && isdigit(c) ){ + x++; + }else{ + return sqlite3_mprintf("\"%w\"", zId); + } + } + } + if( x ) return sqlite3_mprintf("%s", zId); + lwr = 0; + upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; + while( lwr<=upr ){ + mid = (lwr+upr)/2; + c = sqlite3_stricmp(azKeywords[mid], zId); + if( c==0 ) return sqlite3_mprintf("\"%w\"", zId); + if( c<0 ){ + lwr = mid+1; + }else{ + upr = mid-1; + } + } + return sqlite3_mprintf("%s", zId); +} + +/* +** Prepare a new SQL statement. Print an error and abort if anything +** goes wrong. +*/ +static sqlite3_stmt *db_vprepare(const char *zFormat, va_list ap){ + char *zSql; + int rc; + sqlite3_stmt *pStmt; + + zSql = sqlite3_vmprintf(zFormat, ap); + if( zSql==0 ) runtimeError("out of memory"); + rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, 0); + if( rc ){ + runtimeError("SQL statement error: %s\n\"%s\"", sqlite3_errmsg(g.db), + zSql); + } + sqlite3_free(zSql); + return pStmt; +} +static sqlite3_stmt *db_prepare(const char *zFormat, ...){ + va_list ap; + sqlite3_stmt *pStmt; + va_start(ap, zFormat); + pStmt = db_vprepare(zFormat, ap); + va_end(ap); + return pStmt; +} + +/* +** Free a list of strings +*/ +static void namelistFree(char **az){ + if( az ){ + int i; + for(i=0; az[i]; i++) sqlite3_free(az[i]); + sqlite3_free(az); + } +} + +/* +** Return a list of column names for the table zDb.zTab. Space to +** hold the list is obtained from sqlite3_malloc() and should released +** using namelistFree() when no longer needed. +** +** Primary key columns are listed first, followed by data columns. +** The number of columns in the primary key is returned in *pnPkey. +** +** Normally, the "primary key" in the previous sentence is the true +** primary key - the rowid or INTEGER PRIMARY KEY for ordinary tables +** or the declared PRIMARY KEY for WITHOUT ROWID tables. However, if +** the g.bSchemaPK flag is set, then the schema-defined PRIMARY KEY is +** used in all cases. In that case, entries that have NULL values in +** any of their primary key fields will be excluded from the analysis. +** +** If the primary key for a table is the rowid but rowid is inaccessible, +** then this routine returns a NULL pointer. +** +** Examples: +** CREATE TABLE t1(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(c)); +** *pnPKey = 1; +** az = { "rowid", "a", "b", "c", 0 } // Normal case +** az = { "c", "a", "b", 0 } // g.bSchemaPK==1 +** +** CREATE TABLE t2(a INT UNIQUE, b INTEGER, c TEXT, PRIMARY KEY(b)); +** *pnPKey = 1; +** az = { "b", "a", "c", 0 } +** +** CREATE TABLE t3(x,y,z,PRIMARY KEY(y,z)); +** *pnPKey = 1 // Normal case +** az = { "rowid", "x", "y", "z", 0 } // Normal case +** *pnPKey = 2 // g.bSchemaPK==1 +** az = { "y", "x", "z", 0 } // g.bSchemaPK==1 +** +** CREATE TABLE t4(x,y,z,PRIMARY KEY(y,z)) WITHOUT ROWID; +** *pnPKey = 2 +** az = { "y", "z", "x", 0 } +** +** CREATE TABLE t5(rowid,_rowid_,oid); +** az = 0 // The rowid is not accessible +*/ +static char **columnNames(const char *zDb, const char *zTab, int *pnPKey){ + char **az = 0; /* List of column names to be returned */ + int naz = 0; /* Number of entries in az[] */ + sqlite3_stmt *pStmt; /* SQL statement being run */ + char *zPkIdxName = 0; /* Name of the PRIMARY KEY index */ + int truePk = 0; /* PRAGMA table_info indentifies the PK to use */ + int nPK = 0; /* Number of PRIMARY KEY columns */ + int i, j; /* Loop counters */ + + if( g.bSchemaPK==0 ){ + /* Normal case: Figure out what the true primary key is for the table. + ** * For WITHOUT ROWID tables, the true primary key is the same as + ** the schema PRIMARY KEY, which is guaranteed to be present. + ** * For rowid tables with an INTEGER PRIMARY KEY, the true primary + ** key is the INTEGER PRIMARY KEY. + ** * For all other rowid tables, the rowid is the true primary key. + */ + pStmt = db_prepare("PRAGMA %s.index_list=%Q", zDb, zTab); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,3),"pk")==0 ){ + zPkIdxName = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + break; + } + } + sqlite3_finalize(pStmt); + if( zPkIdxName ){ + int nKey = 0; + int nCol = 0; + truePk = 0; + pStmt = db_prepare("PRAGMA %s.index_xinfo=%Q", zDb, zPkIdxName); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nCol++; + if( sqlite3_column_int(pStmt,5) ){ nKey++; continue; } + if( sqlite3_column_int(pStmt,1)>=0 ) truePk = 1; + } + if( nCol==nKey ) truePk = 1; + if( truePk ){ + nPK = nKey; + }else{ + nPK = 1; + } + sqlite3_finalize(pStmt); + sqlite3_free(zPkIdxName); + }else{ + truePk = 1; + nPK = 1; + } + pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab); + }else{ + /* The g.bSchemaPK==1 case: Use whatever primary key is declared + ** in the schema. The "rowid" will still be used as the primary key + ** if the table definition does not contain a PRIMARY KEY. + */ + nPK = 0; + pStmt = db_prepare("PRAGMA %s.table_info=%Q", zDb, zTab); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_int(pStmt,5)>0 ) nPK++; + } + sqlite3_reset(pStmt); + if( nPK==0 ) nPK = 1; + truePk = 1; + } + *pnPKey = nPK; + naz = nPK; + az = sqlite3_malloc( sizeof(char*)*(nPK+1) ); + if( az==0 ) runtimeError("out of memory"); + memset(az, 0, sizeof(char*)*(nPK+1)); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + int iPKey; + if( truePk && (iPKey = sqlite3_column_int(pStmt,5))>0 ){ + az[iPKey-1] = safeId((char*)sqlite3_column_text(pStmt,1)); + }else{ + az = sqlite3_realloc(az, sizeof(char*)*(naz+2) ); + if( az==0 ) runtimeError("out of memory"); + az[naz++] = safeId((char*)sqlite3_column_text(pStmt,1)); + } + } + sqlite3_finalize(pStmt); + if( az ) az[naz] = 0; + if( az[0]==0 ){ + const char *azRowid[] = { "rowid", "_rowid_", "oid" }; + for(i=0; i=naz ){ + az[0] = sqlite3_mprintf("%s", azRowid[i]); + break; + } + } + if( az[0]==0 ){ + for(i=1; inPk2 ){ + zSep = "SELECT "; + for(i=0; i>= 8; + for(i=7; i>=0; i--){ + p[i] = (unsigned char)((v & 0x7f) | 0x80); + v >>= 7; + } + fwrite(p, 8, 1, out); + }else{ + n = 9; + do{ + p[n--] = (unsigned char)((v & 0x7f) | 0x80); + v >>= 7; + }while( v!=0 ); + p[9] &= 0x7f; + fwrite(p+n+1, 9-n, 1, out); + } +} + +/* +** Write an SQLite value onto out. +*/ +static void putValue(FILE *out, sqlite3_value *pVal){ + int iDType = sqlite3_value_type(pVal); + sqlite3_int64 iX; + double rX; + sqlite3_uint64 uX; + int j; + + putc(iDType, out); + switch( iDType ){ + case SQLITE_INTEGER: + iX = sqlite3_value_int64(pVal); + memcpy(&uX, &iX, 8); + for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); + break; + case SQLITE_FLOAT: + rX = sqlite3_value_double(pVal); + memcpy(&uX, &rX, 8); + for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); + break; + case SQLITE_TEXT: + iX = sqlite3_value_bytes(pVal); + putsVarint(out, (sqlite3_uint64)iX); + fwrite(sqlite3_value_text(pVal),1,(size_t)iX,out); + break; + case SQLITE_BLOB: + iX = sqlite3_value_bytes(pVal); + putsVarint(out, (sqlite3_uint64)iX); + fwrite(sqlite3_value_blob(pVal),1,(size_t)iX,out); + break; + case SQLITE_NULL: + break; + } +} + +/* +** Generate a CHANGESET for all differences from main.zTab to aux.zTab. +*/ +static void changeset_one_table(const char *zTab, FILE *out){ + sqlite3_stmt *pStmt; /* SQL statment */ + char *zId = safeId(zTab); /* Escaped name of the table */ + char **azCol = 0; /* List of escaped column names */ + int nCol = 0; /* Number of columns */ + int *aiFlg = 0; /* 0 if column is not part of PK */ + int *aiPk = 0; /* Column numbers for each PK column */ + int nPk = 0; /* Number of PRIMARY KEY columns */ + Str sql; /* SQL for the diff query */ + int i, k; /* Loop counters */ + const char *zSep; /* List separator */ + + pStmt = db_prepare( + "SELECT A.sql=B.sql FROM main.sqlite_master A, aux.sqlite_master B" + " WHERE A.name=%Q AND B.name=%Q", zTab, zTab + ); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_int(pStmt,0)==0 ){ + runtimeError("schema changes for table %s", safeId(zTab)); + } + }else{ + runtimeError("table %s missing from one or both databases", safeId(zTab)); + } + sqlite3_finalize(pStmt); + pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab); + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + nCol++; + azCol = sqlite3_realloc(azCol, sizeof(char*)*nCol); + if( azCol==0 ) runtimeError("out of memory"); + aiFlg = sqlite3_realloc(aiFlg, sizeof(int)*nCol); + if( aiFlg==0 ) runtimeError("out of memory"); + azCol[nCol-1] = safeId((const char*)sqlite3_column_text(pStmt,1)); + aiFlg[nCol-1] = i = sqlite3_column_int(pStmt,5); + if( i>0 ){ + if( i>nPk ){ + nPk = i; + aiPk = sqlite3_realloc(aiPk, sizeof(int)*nPk); + if( aiPk==0 ) runtimeError("out of memory"); + } + aiPk[i-1] = nCol-1; + } + } + sqlite3_finalize(pStmt); + if( nPk==0 ) goto end_changeset_one_table; + strInit(&sql); + if( nCol>nPk ){ + strPrintf(&sql, "SELECT %d", SQLITE_UPDATE); + for(i=0; i0 ) sqlite3_free(azCol[--nCol]); + sqlite3_free(azCol); + sqlite3_free(aiPk); + sqlite3_free(zId); +} + +/* +** Print sketchy documentation for this utility program +*/ +static void showHelp(void){ + printf("Usage: %s [options] DB1 DB2\n", g.zArgv0); + printf( +"Output SQL text that would transform DB1 into DB2.\n" +"Options:\n" +" --changeset FILE Write a CHANGESET into FILE\n" +" -L|--lib LIBRARY Load an SQLite extension library\n" +" --primarykey Use schema-defined PRIMARY KEYs\n" +" --schema Show only differences in the schema\n" +" --summary Show only a summary of the differences\n" +" --table TAB Show only differences in table TAB\n" + ); +} + +int main(int argc, char **argv){ + const char *zDb1 = 0; + const char *zDb2 = 0; + int i; + int rc; + char *zErrMsg = 0; + char *zSql; + sqlite3_stmt *pStmt; + char *zTab = 0; + FILE *out = stdout; + void (*xDiff)(const char*,FILE*) = diff_one_table; + int nExt = 0; + char **azExt = 0; + + g.zArgv0 = argv[0]; + for(i=1; i Date: Mon, 13 Jul 2015 09:53:10 -0500 Subject: [PATCH 13/36] Bump cipher version to 3.3.1 --- src/crypto.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto.h b/src/crypto.h index a614ede..b048b49 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -45,9 +45,9 @@ #ifndef CIPHER_VERSION #ifdef SQLCIPHER_FIPS -#define CIPHER_VERSION "3.3.0 FIPS" +#define CIPHER_VERSION "3.3.1 FIPS" #else -#define CIPHER_VERSION "3.3.0" +#define CIPHER_VERSION "3.3.1" #endif #endif From 951d2ed667a8ec4a06766f65a183b4949b3b8d11 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Mon, 13 Jul 2015 10:23:35 -0500 Subject: [PATCH 14/36] Add release notes for 3.3.1 --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c67f1fc..a53cc76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file. ## [Unreleased][unreleased] +## [3.3.1] - 2015-07-13 +### Changed +- Merge upstream SQLite 3.8.10.2 +- Fixed segfault when provided an invalid cipher name +- Check for codec context when performing `PRAGMA cipher_store_pass` +- Remove extraneous null check in `PRAGMA cipher_migrate` + ## [3.3.0] - 2015-03-25 ### Added - Added FIPS API calls within the OpenSSL crypto provider @@ -49,7 +56,8 @@ All notable changes to this project will be documented in this file. ### Security - Change KDF iteration length from 4,000 to 64,000 -[unreleased]: https://github.com/sqlcipher/sqlcipher/compare/v3.3.0...prerelease +[unreleased]: https://github.com/sqlcipher/sqlcipher/compare/v3.3.1...prerelease +[3.3.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.3.0...v3.3.1 [3.3.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.2.0...v3.3.0 [3.2.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.1.0...v3.2.0 [3.1.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.0.1...v3.1.0 From 6737dca1bc7ff766a61838a670b4cf8da9dd8652 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Mon, 13 Jul 2015 10:35:55 -0500 Subject: [PATCH 15/36] Fix link for 3.3.1 release --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a53cc76..2f35868 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,7 +57,7 @@ All notable changes to this project will be documented in this file. - Change KDF iteration length from 4,000 to 64,000 [unreleased]: https://github.com/sqlcipher/sqlcipher/compare/v3.3.1...prerelease -[3.3.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.3.0...v3.3.1 +[3.3.1]: https://github.com/sqlcipher/sqlcipher/compare/v3.3.0...v3.3.1 [3.3.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.2.0...v3.3.0 [3.2.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.1.0...v3.2.0 [3.1.0]: https://github.com/sqlcipher/sqlcipher/compare/v3.0.1...v3.1.0 From b69e1d36beb85d1f32014ec324518f87c664750d Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Mon, 13 Jul 2015 11:54:42 -0500 Subject: [PATCH 16/36] Rebuild configure to work properly with libtool --- configure | 4098 ++++++++++++++++++----------------------------------- 1 file changed, 1400 insertions(+), 2698 deletions(-) diff --git a/configure b/configure index 4ae63c9..82a361c 100755 --- a/configure +++ b/configure @@ -196,14 +196,6 @@ test -x / || exit 1" as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 - - test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( - ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' - ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO - ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO - PATH=/empty FPATH=/empty; export PATH FPATH - test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ - || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes @@ -561,8 +553,155 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} +case X$lt_ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +ECHO=${lt_ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then + # Yippee, $ECHO works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<_LT_EOF +$* +_LT_EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test -z "$lt_ECHO"; then + if test "X${echo_test_string+set}" != Xset; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if { echo_test_string=`eval $cmd`; } 2>/dev/null && + { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null + then + break + fi + done + fi + + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : + else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$ECHO" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + ECHO='print -r' + elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + ECHO='printf %s\n' + if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && + echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + ECHO="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + ECHO="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + ECHO=echo + fi + fi + fi + fi + fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +lt_ECHO=$ECHO +if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + test -n "$DJDIR" || exec 7<&0 &1 @@ -665,23 +804,20 @@ VERSION program_prefix TCLLIBDIR TCLSH_CMD +AWK INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM CPP -LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL -MANIFEST_TOOL -AWK +lt_ECHO RANLIB STRIP -ac_ct_AR AR -DLLTOOL OBJDUMP LN_S NM @@ -753,9 +889,7 @@ enable_shared enable_static with_pic enable_fast_install -with_aix_soname with_gnu_ld -with_sysroot enable_libtool_lock enable_largefile enable_threadsafe @@ -781,7 +915,6 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -LT_SYS_LIBRARY_PATH CPP TCLLIBDIR' @@ -1421,14 +1554,9 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + --with-pic try to use only PIC/non-PIC objects [default=use both] - --with-aix-soname=aix|svr4|both - shared library versioning (aka "SONAME") variant to - provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-sysroot[=DIR] Search for dependent libraries within DIR (or the - compiler's sysroot if not specified). --with-crypto-lib Specify which crypto library to use --with-tcl=DIR directory containing tcl configuration (tclConfig.sh) @@ -1443,8 +1571,6 @@ Some influential environment variables: LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory - LT_SYS_LIBRARY_PATH - User-defined run-time library search path. CPP C preprocessor TCLLIBDIR Where to install tcl plugin @@ -2293,6 +2419,31 @@ fi ######### # Programs needed # +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.2.6' +macro_revision='1.3012' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then @@ -2322,31 +2473,6 @@ ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -case `pwd` in - *\ * | *\ *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 -$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; -esac - - - -macro_version='2.4.6' -macro_revision='2.4.6' - - - - - - - - - - - - - -ltmain=$ac_aux_dir/ltmain.sh - # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 @@ -2418,75 +2544,6 @@ IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac -# Backslashify metacharacters that are still active within -# double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO -ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 -$as_echo_n "checking how to print strings... " >&6; } -# Test print first, because it will be a builtin if present. -if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ - test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='print -r --' -elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then - ECHO='printf %s\n' -else - # Use this function as a fallback that always works. - func_fallback_echo () - { - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' - } - ECHO='func_fallback_echo' -fi - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "" -} - -case $ECHO in - printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 -$as_echo "printf" >&6; } ;; - print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 -$as_echo "print -r" >&6; } ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 -$as_echo "cat" >&6; } ;; -esac - - - - - - - - - - - - - - ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3577,19 +3634,19 @@ test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld -if test yes = "$GCC"; then +if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) - # gcc leaves a trailing carriage return, which upsets mingw + # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -3603,7 +3660,7 @@ $as_echo_n "checking for ld used by $CC... " >&6; } while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD=$ac_prog + test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. @@ -3614,7 +3671,7 @@ $as_echo_n "checking for ld used by $CC... " >&6; } with_gnu_ld=unknown ;; esac -elif test yes = "$with_gnu_ld"; then +elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else @@ -3625,32 +3682,32 @@ if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD=$ac_dir/$ac_prog + lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } @@ -3693,38 +3750,33 @@ if ${lt_cv_path_NM+:} false; then : else if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM=$NM + lt_cv_path_NM="$NM" else - lt_nm_to_check=${ac_tool_prefix}nm + lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. - tmp_nm=$ac_dir/$lt_tmp_nm - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty - case $build_os in - mingw*) lt_bad_file=conftest.nm/nofile ;; - *) lt_bad_file=/dev/null ;; - esac - case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in - *$lt_bad_file* | *'Invalid file or object type'*) + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break 2 + break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break 2 + break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -3735,22 +3787,19 @@ else esac fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } -if test no != "$lt_cv_path_NM"; then - NM=$lt_cv_path_NM +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$DUMPBIN"; then : - # Let the user override the test. - else - if test -n "$ac_tool_prefix"; then - for ac_prog in dumpbin "link -dump" + if test -n "$ac_tool_prefix"; then + for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -3794,7 +3843,7 @@ fi fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN - for ac_prog in dumpbin "link -dump" + for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -3849,18 +3898,9 @@ esac fi fi - case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in - *COFF*) - DUMPBIN="$DUMPBIN -symbols -headers" - ;; - *) - DUMPBIN=: - ;; - esac - fi - if test : != "$DUMPBIN"; then - NM=$DUMPBIN + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm @@ -3877,13 +3917,13 @@ if ${lt_cv_nm_interface+:} false; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval echo "\"\$as_me:3920: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:3923: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:$LINENO: output\"" >&5) + (eval echo "\"\$as_me:3926: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -3911,7 +3951,7 @@ if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 - teststring=ABCD + teststring="ABCD" case $build_os in msdosdjgpp*) @@ -3940,18 +3980,13 @@ else lt_cv_sys_max_cmd_len=8192; ;; - mint*) - # On MiNT this can take a long time and run out of memory. - lt_cv_sys_max_cmd_len=8192; - ;; - amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; - bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -3970,11 +4005,6 @@ else lt_cv_sys_max_cmd_len=196608 ;; - os2*) - # The test takes a long time on OS/2. - lt_cv_sys_max_cmd_len=8192 - ;; - osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not @@ -4001,23 +4031,22 @@ else ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len" && \ - test undefined != "$lt_cv_sys_max_cmd_len"; then + if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8; do + for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test X`env echo "$teststring$teststring" 2>/dev/null` \ - = "X$teststring$teststring"; } >/dev/null 2>&1 && - test 17 != "$i" # 1/2 MB should be enough + while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ + = "XX$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -4035,7 +4064,7 @@ else fi -if test -n "$lt_cv_sys_max_cmd_len"; then +if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else @@ -4053,6 +4082,30 @@ max_cmd_len=$lt_cv_sys_max_cmd_len : ${MV="mv -f"} : ${RM="rm -f"} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else @@ -4084,80 +4137,6 @@ esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 -$as_echo_n "checking how to convert $build file names to $host format... " >&6; } -if ${lt_cv_to_host_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 - ;; - esac - ;; - *-*-cygwin* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin - ;; - *-*-cygwin* ) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; - * ) # otherwise, assume *nix - lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin - ;; - esac - ;; - * ) # unhandled hosts (and "normal" native builds) - lt_cv_to_host_file_cmd=func_convert_file_noop - ;; -esac - -fi - -to_host_file_cmd=$lt_cv_to_host_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 -$as_echo "$lt_cv_to_host_file_cmd" >&6; } - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 -$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } -if ${lt_cv_to_tool_file_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - #assume ordinary cross tools, or native build. -lt_cv_to_tool_file_cmd=func_convert_file_noop -case $host in - *-*-mingw* ) - case $build in - *-*-mingw* ) # actually msys - lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 - ;; - esac - ;; -esac - -fi - -to_tool_file_cmd=$lt_cv_to_tool_file_cmd -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 -$as_echo "$lt_cv_to_tool_file_cmd" >&6; } - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : @@ -4174,14 +4153,9 @@ case $reload_flag in esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - if test yes != "$GCC"; then - reload_cmds=false - fi - ;; darwin*) - if test yes = "$GCC"; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi @@ -4309,13 +4283,13 @@ lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# 'unknown' -- same as none, but documents that we really don't know. +# `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# that responds to the $file_magic_cmd with a given extended regex. -# If you have 'file' or equivalent on your system and you're not sure -# whether 'pass_all' will *always* work, you probably want this one. +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) @@ -4346,13 +4320,12 @@ mingw* | pw32*) lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else - # Keep this pattern in sync with the one in func_win32_libid. - lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; -cegcc*) +cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' @@ -4378,7 +4351,7 @@ freebsd* | dragonfly*) fi ;; -haiku*) +gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -4390,11 +4363,11 @@ hpux10.20* | hpux11*) lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac @@ -4415,8 +4388,8 @@ irix5* | irix6* | nonstopux*) lt_cv_deplibs_check_method=pass_all ;; -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) +# This must be Linux ELF. +linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; @@ -4438,8 +4411,8 @@ newos6*) lt_cv_deplibs_check_method=pass_all ;; -openbsd* | bitrig*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' @@ -4492,29 +4465,11 @@ sysv4 | sysv4.3*) tpf*) lt_cv_deplibs_check_method=pass_all ;; -os2*) - lt_cv_deplibs_check_method=pass_all - ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } - -file_magic_glob= -want_nocaseglob=no -if test "$build" = "$host"; then - case $host_os in - mingw* | pw32*) - if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then - want_nocaseglob=yes - else - file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` - fi - ;; - esac -fi - file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown @@ -4528,165 +4483,11 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown - - - - - - - - - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. -set dummy ${ac_tool_prefix}dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_DLLTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DLLTOOL"; then - ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DLLTOOL=$ac_cv_prog_DLLTOOL -if test -n "$DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 -$as_echo "$DLLTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_DLLTOOL"; then - ac_ct_DLLTOOL=$DLLTOOL - # Extract the first word of "dlltool", so it can be a program name with args. -set dummy dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DLLTOOL"; then - ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_DLLTOOL="dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL -if test -n "$ac_ct_DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 -$as_echo "$ac_ct_DLLTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_DLLTOOL" = x; then - DLLTOOL="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DLLTOOL=$ac_ct_DLLTOOL - fi -else - DLLTOOL="$ac_cv_prog_DLLTOOL" -fi - -test -z "$DLLTOOL" && DLLTOOL=dlltool - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 -$as_echo_n "checking how to associate runtime and link libraries... " >&6; } -if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_sharedlib_from_linklib_cmd='unknown' - -case $host_os in -cygwin* | mingw* | pw32* | cegcc*) - # two different shell functions defined in ltmain.sh; - # decide which one to use based on capabilities of $DLLTOOL - case `$DLLTOOL --help 2>&1` in - *--identify-strict*) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib - ;; - *) - lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback - ;; - esac - ;; -*) - # fallback: assume linklib IS sharedlib - lt_cv_sharedlib_from_linklib_cmd=$ECHO - ;; -esac - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 -$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } -sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd -test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO - - - - - - - - -if test -n "$ac_tool_prefix"; then - for ac_prog in ar - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : @@ -4702,7 +4503,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -4722,15 +4523,11 @@ $as_echo "no" >&6; } fi - test -n "$AR" && break - done fi -if test -z "$AR"; then +if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR - for ac_prog in ar -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : @@ -4746,7 +4543,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_AR="$ac_prog" + ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -4765,10 +4562,6 @@ else $as_echo "no" >&6; } fi - - test -n "$ac_ct_AR" && break -done - if test "x$ac_ct_AR" = x; then AR="false" else @@ -4780,72 +4573,16 @@ ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi -fi - -: ${AR=ar} -: ${AR_FLAGS=cru} - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 -$as_echo_n "checking for archiver @FILE support... " >&6; } -if ${lt_cv_ar_at_file+:} false; then : - $as_echo_n "(cached) " >&6 else - lt_cv_ar_at_file=no - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - echo conftest.$ac_objext > conftest.lst - lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 - (eval $lt_ar_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if test 0 -eq "$ac_status"; then - # Ensure the archiver fails upon bogus file names. - rm -f conftest.$ac_objext libconftest.a - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 - (eval $lt_ar_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if test 0 -ne "$ac_status"; then - lt_cv_ar_at_file=@ - fi - fi - rm -f conftest.* libconftest.a - + AR="$ac_cv_prog_AR" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 -$as_echo "$lt_cv_ar_at_file" >&6; } +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru + + + -if test no = "$lt_cv_ar_at_file"; then - archiver_list_spec= -else - archiver_list_spec=$lt_cv_ar_at_file -fi @@ -5058,84 +4795,30 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in - bitrig* | openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" -fi - -case $host_os in - darwin*) - lock_old_archive_extraction=yes ;; - *) - lock_old_archive_extraction=no ;; -esac - - - - - - - - - - - - - - - - - - - - - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi - test -n "$AWK" && break -done + + + + + + + + + + + + + @@ -5190,7 +4873,7 @@ cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; @@ -5223,44 +4906,14 @@ case `$NM -V 2>&1` in symcode='[ABCDGIRSTW]' ;; esac -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Gets list of data symbols to import. - lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" - # Adjust the below global symbol transforms to fixup imported variables. - lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" - lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" - lt_c_name_lib_hook="\ - -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ - -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" -else - # Disable hooks by default. - lt_cv_sys_global_symbol_to_import= - lt_cdecl_hook= - lt_c_name_hook= - lt_c_name_lib_hook= -fi - # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n"\ -$lt_cdecl_hook\ -" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ -$lt_c_name_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" - -# Transform an extracted symbol line into symbol name with lib prefix and -# symbol address. -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ -$lt_c_name_lib_hook\ -" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ -" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ -" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -5278,29 +4931,24 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function, - # D for any global variable and I for any imported variable. + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ -" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ -" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ -" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ -" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ -" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no @@ -5326,8 +4974,8 @@ _LT_EOF test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 - (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then @@ -5342,18 +4990,6 @@ _LT_EOF if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE -/* DATA imports from DLLs on WIN32 can't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined __osf__ -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - #ifdef __cplusplus extern "C" { #endif @@ -5365,7 +5001,7 @@ _LT_EOF cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ -LT_DLSYM_CONST struct { +const struct { const char *name; void *address; } @@ -5373,7 +5009,7 @@ lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -5391,19 +5027,19 @@ static const void *lt_preloaded_setup() { _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext - lt_globsym_save_LIBS=$LIBS - lt_globsym_save_CFLAGS=$CFLAGS - LIBS=conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest$ac_exeext; then + test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi - LIBS=$lt_globsym_save_LIBS - CFLAGS=$lt_globsym_save_CFLAGS + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi @@ -5420,7 +5056,7 @@ _LT_EOF rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test yes = "$pipe_works"; then + if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= @@ -5440,12 +5076,6 @@ else $as_echo "ok" >&6; } fi -# Response file support. -if test "$lt_cv_nm_interface" = "MS dumpbin"; then - nm_file_list_spec='@' -elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then - nm_file_list_spec='@' -fi @@ -5467,152 +5097,19 @@ fi - - - - - - - - - - - - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 -$as_echo_n "checking for sysroot... " >&6; } - -# Check whether --with-sysroot was given. -if test "${with_sysroot+set}" = set; then : - withval=$with_sysroot; -else - with_sysroot=no -fi - - -lt_sysroot= -case $with_sysroot in #( - yes) - if test yes = "$GCC"; then - lt_sysroot=`$CC --print-sysroot 2>/dev/null` - fi - ;; #( - /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` - ;; #( - no|'') - ;; #( - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 -$as_echo "$with_sysroot" >&6; } - as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 - ;; -esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 -$as_echo "${lt_sysroot:-no}" >&6; } - - - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 -$as_echo_n "checking for a working dd... " >&6; } -if ${ac_cv_path_lt_DD+:} false; then : - $as_echo_n "(cached) " >&6 -else - printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -: ${lt_DD:=$DD} -if test -z "$lt_DD"; then - ac_path_lt_DD_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in dd; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_lt_DD" || continue -if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: -fi - $ac_path_lt_DD_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_lt_DD"; then - : - fi -else - ac_cv_path_lt_DD=$lt_DD -fi - -rm -f conftest.i conftest2.i conftest.out -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 -$as_echo "$ac_cv_path_lt_DD" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 -$as_echo_n "checking how to truncate binary pipes... " >&6; } -if ${lt_cv_truncate_bin+:} false; then : - $as_echo_n "(cached) " >&6 -else - printf 0123456789abcdef0123456789abcdef >conftest.i -cat conftest.i conftest.i >conftest2.i -lt_cv_truncate_bin= -if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then - cmp -s conftest.i conftest.out \ - && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" -fi -rm -f conftest.i conftest2.i conftest.out -test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 -$as_echo "$lt_cv_truncate_bin" >&6; } - - - - - - - -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in $*""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi -test no = "$enable_libtool_lock" || enable_libtool_lock=yes +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out what ABI is being produced by ac_compile, and set mode - # options accordingly. + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -5621,25 +5118,24 @@ ia64-*-hpux*) test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE=32 + HPUX_IA64_MODE="32" ;; *ELF-64*) - HPUX_IA64_MODE=64 + HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '#line '$LINENO' "configure"' > conftest.$ac_ext + # Find out which ABI we are using. + echo '#line 5132 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - if test yes = "$lt_cv_prog_gnu_ld"; then + if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" @@ -5668,50 +5164,9 @@ ia64-*-hpux*) rm -rf conftest* ;; -mips64*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. - echo '#line '$LINENO' "configure"' > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - emul=elf - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - emul="${emul}32" - ;; - *64-bit*) - emul="${emul}64" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *MSB*) - emul="${emul}btsmip" - ;; - *LSB*) - emul="${emul}ltsmip" - ;; - esac - case `/usr/bin/file conftest.$ac_objext` in - *N32*) - emul="${emul}n32" - ;; - esac - LD="${LD-ld} -m $emul" - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. Note that the listed cases only cover the - # situations where additional linker options are needed (such as when - # doing 32-bit compilation for a host where ld defaults to 64-bit, or - # vice versa); the common cases where no linker options are needed do - # not appear in the list. + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -5725,19 +5180,9 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - case `/usr/bin/file conftest.o` in - *x86-64*) - LD="${LD-ld} -m elf32_x86_64" - ;; - *) - LD="${LD-ld} -m elf_i386" - ;; - esac + LD="${LD-ld} -m elf_i386" ;; - powerpc64le-*linux*) - LD="${LD-ld} -m elf32lppclinux" - ;; - powerpc64-*linux*) + ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -5756,10 +5201,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - powerpcle-*linux*) - LD="${LD-ld} -m elf64lppc" - ;; - powerpc-*linux*) + ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -5777,7 +5219,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS=$CFLAGS + SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } @@ -5817,14 +5259,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } - if test yes != "$lt_cv_cc_needs_belf"; then + if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS=$SAVE_CFLAGS + CFLAGS="$SAVE_CFLAGS" fi ;; -*-*solaris*) - # Find out what ABI is being produced by ac_compile, and set linker - # options accordingly. +sparc*-*solaris*) + # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -5834,20 +5275,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in - yes*) - case $host in - i?86-*-solaris*|x86_64-*-solaris*) - LD="${LD-ld} -m elf_x86_64" - ;; - sparc*-*-solaris*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - # GNU ld 2.21 introduced _sol2 emulations. Use them if available. - if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD=${LD-ld}_sol2 - fi - ;; + yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" @@ -5861,124 +5289,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } ;; esac -need_locks=$enable_libtool_lock - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. -set dummy ${ac_tool_prefix}mt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$MANIFEST_TOOL"; then - ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL -if test -n "$MANIFEST_TOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 -$as_echo "$MANIFEST_TOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_MANIFEST_TOOL"; then - ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL - # Extract the first word of "mt", so it can be a program name with args. -set dummy mt; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_MANIFEST_TOOL"; then - ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL -if test -n "$ac_ct_MANIFEST_TOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 -$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_MANIFEST_TOOL" = x; then - MANIFEST_TOOL=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL - fi -else - MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" -fi - -test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 -$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } -if ${lt_cv_path_mainfest_tool+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_path_mainfest_tool=no - echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 - $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out - cat conftest.err >&5 - if $GREP 'Manifest Tool' conftest.out > /dev/null; then - lt_cv_path_mainfest_tool=yes - fi - rm -f conftest* -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 -$as_echo "$lt_cv_path_mainfest_tool" >&6; } -if test yes != "$lt_cv_path_mainfest_tool"; then - MANIFEST_TOOL=: -fi - - - - +need_locks="$enable_libtool_lock" case $host_os in @@ -6475,7 +5786,7 @@ if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no - if test -z "$LT_MULTI_MODULE"; then + if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -6487,13 +5798,7 @@ else $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? - # If there is a non-empty error log, and "single_module" - # appears in it, assume the flag caused a linker warning - if test -s conftest.err && $GREP single_module conftest.err; then - cat conftest.err >&5 - # Otherwise, if the output was created with a 0 exit code from - # the compiler, it worked. - elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 @@ -6504,7 +5809,6 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : @@ -6532,74 +5836,39 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 -$as_echo_n "checking for -force_load linker flag... " >&6; } -if ${lt_cv_ld_force_load+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_ld_force_load=no - cat > conftest.c << _LT_EOF -int forced_loaded() { return 2;} -_LT_EOF - echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 - $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 - echo "$AR cru libconftest.a conftest.o" >&5 - $AR cru libconftest.a conftest.o 2>&5 - echo "$RANLIB libconftest.a" >&5 - $RANLIB libconftest.a 2>&5 - cat > conftest.c << _LT_EOF -int main() { return 0;} -_LT_EOF - echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 - $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err - _lt_result=$? - if test -s conftest.err && $GREP force_load conftest.err; then - cat conftest.err >&5 - elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then - lt_cv_ld_force_load=yes - else - cat conftest.err >&5 - fi - rm -f conftest.err libconftest.a conftest conftest.c - rm -rf conftest.dSYM - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 -$as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; - 10.[012][,.]*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test yes = "$lt_cv_apple_cc_single_mod"; then + if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi - if test yes = "$lt_cv_ld_exported_symbols_list"; then - _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi - if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -6607,41 +5876,6 @@ $as_echo "$lt_cv_ld_force_load" >&6; } ;; esac -# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x$2 in - x) - ;; - *:) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" - ;; - x:*) - eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" - ;; - *) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" - ;; - esac -} - ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -6924,8 +6158,6 @@ done - - # Set options @@ -6945,14 +6177,14 @@ if test "${enable_shared+set}" = set; then : *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" ;; esac else @@ -6976,14 +6208,14 @@ if test "${enable_static+set}" = set; then : *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" ;; esac else @@ -7001,27 +6233,14 @@ fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : - withval=$with_pic; lt_p=${PACKAGE-default} - case $withval in - yes|no) pic_mode=$withval ;; - *) - pic_mode=default - # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, - for lt_pkg in $withval; do - IFS=$lt_save_ifs - if test "X$lt_pkg" = "X$lt_p"; then - pic_mode=yes - fi - done - IFS=$lt_save_ifs - ;; - esac + withval=$with_pic; pic_mode="$withval" else pic_mode=default fi +test -z "$pic_mode" && pic_mode=default + @@ -7037,14 +6256,14 @@ if test "${enable_fast_install+set}" = set; then : *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS=$lt_save_ifs + IFS="$lt_save_ifs" ;; esac else @@ -7058,63 +6277,11 @@ fi - shared_archive_member_spec= -case $host,$enable_shared in -power*-*-aix[5-9]*,yes) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 -$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } - -# Check whether --with-aix-soname was given. -if test "${with_aix_soname+set}" = set; then : - withval=$with_aix_soname; case $withval in - aix|svr4|both) - ;; - *) - as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 - ;; - esac - lt_cv_with_aix_soname=$with_aix_soname -else - if ${lt_cv_with_aix_soname+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_with_aix_soname=aix -fi - - with_aix_soname=$lt_cv_with_aix_soname -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 -$as_echo "$with_aix_soname" >&6; } - if test aix != "$with_aix_soname"; then - # For the AIX way of multilib, we name the shared archive member - # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', - # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. - # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, - # the AIX toolchain works better with OBJECT_MODE set (default 32). - if test 64 = "${OBJECT_MODE-32}"; then - shared_archive_member_spec=shr_64 - else - shared_archive_member_spec=shr - fi - fi - ;; -*) - with_aix_soname=aix - ;; -esac - - - - - - - # This can be used to rebuild libtool when needed -LIBTOOL_DEPS=$ltmain +LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -7137,11 +6304,6 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool' - - - - - @@ -7163,7 +6325,7 @@ test -z "$LN_S" && LN_S="ln -s" -if test -n "${ZSH_VERSION+set}"; then +if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi @@ -7197,30 +6359,60 @@ _ACEOF + + + + + + + + + + + + + case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test set != "${COLLECT_NAMES+set}"; then + if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + # Global variables: ofile=libtool can_build_shared=yes -# All known linkers require a '.a' archive for static linking (except MSVC, +# All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a -with_gnu_ld=$lt_cv_prog_gnu_ld +with_gnu_ld="$lt_cv_prog_gnu_ld" -old_CC=$CC -old_CFLAGS=$CFLAGS +old_CC="$CC" +old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -7229,8 +6421,15 @@ test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o -func_cc_basename $compiler -cc_basename=$func_cc_basename_result +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it @@ -7245,22 +6444,22 @@ if ${lt_cv_path_MAGIC_CMD+:} false; then : else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/${ac_tool_prefix}file"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -7283,13 +6482,13 @@ _LT_EOF break fi done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi -MAGIC_CMD=$lt_cv_path_MAGIC_CMD +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -7311,22 +6510,22 @@ if ${lt_cv_path_MAGIC_CMD+:} false; then : else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD=$MAGIC_CMD - lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS=$lt_save_ifs + IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/file"; then - lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD=$lt_cv_path_MAGIC_CMD + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -7349,13 +6548,13 @@ _LT_EOF break fi done - IFS=$lt_save_ifs - MAGIC_CMD=$lt_save_MAGIC_CMD + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi -MAGIC_CMD=$lt_cv_path_MAGIC_CMD +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -7376,7 +6575,7 @@ esac # Use C for the default configuration in the libtool script -lt_save_CC=$CC +lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -7434,13 +6633,8 @@ if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= -if test yes = "$GCC"; then - case $cc_basename in - nvcc*) - lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; - *) - lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; - esac +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } @@ -7450,7 +6644,7 @@ else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -7460,15 +6654,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6657: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 + echo "$as_me:6661: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes @@ -7480,7 +6674,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } -if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : @@ -7497,19 +6691,20 @@ fi lt_prog_compiler_pic= lt_prog_compiler_static= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } - if test yes = "$GCC"; then + if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi - lt_prog_compiler_pic='-fPIC' ;; amigaos*) @@ -7520,8 +6715,8 @@ lt_prog_compiler_static= ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the '-m68020' flag to GCC prevents building anything better, - # like '-m68040'. + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -7537,11 +6732,6 @@ lt_prog_compiler_static= # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' - case $host_os in - os2*) - lt_prog_compiler_static='$wl-static' - ;; - esac ;; darwin* | rhapsody*) @@ -7550,12 +6740,6 @@ lt_prog_compiler_static= lt_prog_compiler_pic='-fno-common' ;; - haiku*) - # PIC is the default for Haiku. - # The "-static" flag exists, but is broken. - lt_prog_compiler_static= - ;; - hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag @@ -7598,21 +6782,12 @@ lt_prog_compiler_static= lt_prog_compiler_pic='-fPIC' ;; esac - - case $cc_basename in - nvcc*) # Cuda Compiler Driver 2.2 - lt_prog_compiler_wl='-Xlinker ' - if test -n "$lt_prog_compiler_pic"; then - lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" - fi - ;; - esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else @@ -7620,29 +6795,10 @@ lt_prog_compiler_static= fi ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - lt_prog_compiler_pic='-fno-common' - case $cc_basename in - nagfor*) - # NAG Fortran compiler - lt_prog_compiler_wl='-Wl,-Wl,,' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - esac - ;; - mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' - case $host_os in - os2*) - lt_prog_compiler_static='$wl-static' - ;; - esac ;; hpux9* | hpux10* | hpux11*) @@ -7658,7 +6814,7 @@ lt_prog_compiler_static= ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='$wl-a ${wl}archive' + lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -7667,9 +6823,9 @@ lt_prog_compiler_static= lt_prog_compiler_static='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + linux* | k*bsd*-gnu) case $cc_basename in - # old Intel for x86_64, which still supported -KPIC. + # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' @@ -7688,19 +6844,7 @@ lt_prog_compiler_static= lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; - nagfor*) - # NAG Fortran compiler - lt_prog_compiler_wl='-Wl,-Wl,,' - lt_prog_compiler_pic='-PIC' - lt_prog_compiler_static='-Bstatic' - ;; - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' @@ -7712,40 +6856,25 @@ lt_prog_compiler_static= # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; - xl* | bgxl* | bgf* | mpixl*) - # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + xl*) + # IBM XL C 8.0/Fortran 10.1 on PPC lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in - *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='' - ;; - *Sun\ F* | *Sun*Fortran*) - lt_prog_compiler_pic='-KPIC' - lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='-Qoption ld ' - ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; - *Intel*\ [CF]*Compiler*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; - *Portland\ Group*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fpic' + *Sun\ F*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' ;; esac ;; @@ -7777,7 +6906,7 @@ lt_prog_compiler_static= lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in - f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + f77* | f90* | f95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; @@ -7797,7 +6926,7 @@ lt_prog_compiler_static= ;; sysv4*MP*) - if test -d /usr/nec; then + if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi @@ -7826,7 +6955,7 @@ lt_prog_compiler_static= fi case $host_os in - # For platforms that do not support PIC, -DPIC is meaningless: + # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; @@ -7834,17 +6963,13 @@ case $host_os in lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 +$as_echo "$lt_prog_compiler_pic" >&6; } + + + + -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } -if ${lt_cv_prog_compiler_pic+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler_pic=$lt_prog_compiler_pic -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 -$as_echo "$lt_cv_prog_compiler_pic" >&6; } -lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. @@ -7858,7 +6983,7 @@ else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -7868,15 +6993,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6996: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 + echo "$as_me:7000: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes @@ -7888,7 +7013,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } -if test yes = "$lt_cv_prog_compiler_pic_works"; then +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; @@ -7905,11 +7030,6 @@ fi - - - - - # # Check to make sure the static flag actually works. # @@ -7920,7 +7040,7 @@ if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no - save_LDFLAGS=$LDFLAGS + save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -7929,7 +7049,7 @@ else if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes @@ -7939,13 +7059,13 @@ else fi fi $RM -r conftest* - LDFLAGS=$save_LDFLAGS + LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } -if test yes = "$lt_cv_prog_compiler_static_works"; then +if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= @@ -7978,16 +7098,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7101: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 + echo "$as_me:7105: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes @@ -8033,16 +7153,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7156: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 + echo "$as_me:7160: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes @@ -8065,8 +7185,8 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; } -hard_links=nottested -if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } @@ -8078,9 +7198,9 @@ $as_echo_n "checking if we can lock with hard links... " >&6; } ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } - if test no = "$hard_links"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else @@ -8108,6 +7228,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported @@ -8123,9 +7244,9 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ' (' and ')$', so one must not match beginning or - # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', - # as well as any symbol that contains 'd'. + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -8140,7 +7261,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. - if test yes != "$GCC"; then + if test "$GCC" != yes; then with_gnu_ld=no fi ;; @@ -8148,57 +7269,30 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; - openbsd* | bitrig*) + openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes - - # On some targets, GNU ld is compatible enough with the native linker - # that we're better off using the native interface for both. - lt_use_gnu_ld_interface=no - if test yes = "$with_gnu_ld"; then - case $host_os in - aix*) - # The AIX port of GNU ld has always aspired to compatibility - # with the native linker. However, as the warning in the GNU ld - # block says, versions before 2.19.5* couldn't really create working - # shared libraries, regardless of the interface used. - case `$LD -v 2>&1` in - *\ \(GNU\ Binutils\)\ 2.19.5*) ;; - *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; - *\ \(GNU\ Binutils\)\ [3-9]*) ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - ;; - *) - lt_use_gnu_ld_interface=yes - ;; - esac - fi - - if test yes = "$lt_use_gnu_ld_interface"; then + if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='$wl' + wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - export_dynamic_flag_spec='$wl--export-dynamic' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no - case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in - *GNU\ gold*) supports_anon_versioning=yes ;; + case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... @@ -8210,16 +7304,15 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken - if test ia64 != "$host_cpu"; then + if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: the GNU linker, at least up to release 2.19, is reported +*** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to install binutils -*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. -*** You will then need to restart the configuration process. +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. _LT_EOF fi @@ -8229,7 +7322,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -8245,7 +7338,7 @@ _LT_EOF allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi @@ -8255,97 +7348,61 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' - export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' - exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file, use it as - # is; otherwise, prepend EXPORTS... - archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; - haiku*) - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - link_all_deplibs=yes - ;; - - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - allow_undefined_flag=unsupported - shrext_cmds=.dll - archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - enable_shared_with_static_runtimes=yes - ;; - interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='$wl-rpath,$libdir' - export_dynamic_flag_spec='$wl-E' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + gnu* | linux* | tpf* | k*bsd*-gnu) tmp_diet=no - if test linux-dietlibc = "$host_os"; then + if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test no = "$tmp_diet" + && test "$tmp_diet" = no then - tmp_addflag=' $pic_flag' + tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; - pgf77* | pgf90* | pgf95* | pgfortran*) - # Portland Group f77 and f90 compilers - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -8356,47 +7413,39 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; - nagfor*) # NAGFOR 5.3 - tmp_sharedflag='-Wl,-shared' ;; - xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; - nvcc*) # Cuda Compiler Driver 2.2 - whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' - compiler_needs_object=yes - ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test yes = "$supports_anon_versioning"; then + if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in - tcc*) - export_dynamic_flag_spec='-rdynamic' - ;; - xlf* | bgf* | bgxlf* | mpixlf*) + xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' - if test yes = "$supports_anon_versioning"; then + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -8410,8 +7459,8 @@ _LT_EOF archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -8429,8 +7478,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -8442,7 +7491,7 @@ _LT_EOF ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -8457,9 +7506,9 @@ _LT_EOF # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -8476,15 +7525,15 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac - if test no = "$ld_shlibs"; then + if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= @@ -8500,7 +7549,7 @@ _LT_EOF # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes - if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported @@ -8508,57 +7557,32 @@ _LT_EOF ;; aix[4-9]*) - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag= + no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to GNU nm, but means don't demangle to AIX nm. - # Without the "-l" option, or with the "-B" option, AIX nm treats - # weak defined symbols like other global defined symbols, whereas - # GNU nm marks them as "W". - # While the 'weak' keyword is ignored in the Export File, we need - # it in the Import File for the 'aix-soname' feature, so we have - # to replace the "-B" option with "-P" for AIX nm. + # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # have runtime linking enabled, and use it for executables. - # For shared libraries, we enable/disable runtime linking - # depending on the kind of the shared library created - - # when "with_aix_soname,aix_use_runtimelinking" is: - # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables - # "aix,yes" lib.so shared, rtl:yes, for executables - # lib.a static archive - # "both,no" lib.so.V(shr.o) shared, rtl:yes - # lib.a(lib.so.V) shared, rtl:no, for executables - # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a(lib.so.V) shared, rtl:no - # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables - # lib.a static archive + # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do - if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done - if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then - # With aix-soname=svr4, we create the lib.so.V shared archives only, - # so we don't have lib.a shared libs to link our executables. - # We have to force runtime linking in this case. - aix_use_runtimelinking=yes - LDFLAGS="$LDFLAGS -Wl,-brtl" - fi ;; esac @@ -8577,21 +7601,13 @@ _LT_EOF hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes - file_list_spec='$wl-f,' - case $with_aix_soname,$aix_use_runtimelinking in - aix,*) ;; # traditional, no import file - svr4,* | *,yes) # use import file - # The Import File defines what to hardcode. - hardcode_direct=no - hardcode_direct_absolute=no - ;; - esac + file_list_spec='${wl}-f,' - if test yes = "$GCC"; then + if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`$CC -print-prog-name=collect2` + collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -8610,48 +7626,35 @@ _LT_EOF ;; esac shared_flag='-shared' - if test yes = "$aix_use_runtimelinking"; then - shared_flag="$shared_flag "'$wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' fi - # Need to ensure runtime linking is disabled for the traditional - # shared library, or the linker may eventually find shared libraries - # /with/ Import File - we do not want to mix them. - shared_flag_aix='-shared' - shared_flag_svr4='-shared $wl-G' else # not using gcc - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test yes = "$aix_use_runtimelinking"; then - shared_flag='$wl-G' + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' else - shared_flag='$wl-bM:SRE' + shared_flag='${wl}-bM:SRE' fi - shared_flag_aix='$wl-bM:SRE' - shared_flag_svr4='$wl-G' fi fi - export_dynamic_flag_spec='$wl-bexpall' + export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes - if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. - if test set = "${lt_cv_aix_libpath+set}"; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath_+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -8664,47 +7667,34 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=/usr/lib:/lib - fi +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi -fi - - aix_libpath=$lt_cv_aix_libpath_ -fi - - hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else - if test ia64 = "$host_cpu"; then - hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. - if test set = "${lt_cv_aix_libpath+set}"; then - aix_libpath=$lt_cv_aix_libpath -else - if ${lt_cv_aix_libpath_+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -8717,57 +7707,33 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : - lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\([^ ]*\) *$/\1/ - p - } - }' - lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - # Check for a 64-bit object if we didn't find anything. - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` - fi +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test -z "$lt_cv_aix_libpath_"; then - lt_cv_aix_libpath_=/usr/lib:/lib - fi +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi -fi - - aix_libpath=$lt_cv_aix_libpath_ -fi - - hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - no_undefined_flag=' $wl-bernotok' - allow_undefined_flag=' $wl-berok' - if test yes = "$with_gnu_ld"; then - # We only use this code for GNU lds that support --whole-archive. - whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' - else - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' - fi + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes - archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' - # -brtl affects multiple linker settings, -berok does not and is overridden later - compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' - if test svr4 != "$with_aix_soname"; then - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' - fi - if test aix != "$with_aix_soname"; then - archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' - else - # used by -dlpreopen to get the symbols - archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' - fi - archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -8776,7 +7742,7 @@ fi case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -8796,65 +7762,20 @@ fi # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. - case $cc_basename in - cl*) - # Native MSVC - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - always_export_symbols=yes - file_list_spec='@' - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' - archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then - cp "$export_symbols" "$output_objdir/$soname.def"; - echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; - else - $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; - fi~ - $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ - linknames=' - # The linker will not automatically build a static lib if we build a DLL. - # _LT_TAGVAR(old_archive_from_new_cmds, )='true' - enable_shared_with_static_runtimes=yes - exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' - # Don't use ranlib - old_postinstall_cmds='chmod 644 $oldlib' - postlink_cmds='lt_outputfile="@OUTPUT@"~ - lt_tool_outputfile="@TOOL_OUTPUT@"~ - case $lt_outputfile in - *.exe|*.EXE) ;; - *) - lt_outputfile=$lt_outputfile.exe - lt_tool_outputfile=$lt_tool_outputfile.exe - ;; - esac~ - if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then - $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; - $RM "$lt_outputfile.manifest"; - fi' - ;; - *) - # Assume MSVC wrapper - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=.dll - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' - enable_shared_with_static_runtimes=yes - ;; - esac + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) @@ -8864,24 +7785,19 @@ fi hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - if test yes = "$lt_cv_ld_force_load"; then - whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' - - else - whole_archive_flag_spec='' - fi + whole_archive_flag_spec='' link_all_deplibs=yes - allow_undefined_flag=$_lt_dar_allow_undefined + allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in - ifort*|nagfor*) _lt_dar_can_shared=yes ;; + ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test yes = "$_lt_dar_can_shared"; then - output_verbose_link_cmd=func_echo_all - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=echo + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no @@ -8895,6 +7811,10 @@ fi hardcode_shlibpath_var=no ;; + freebsd1*) + ld_shlibs=no + ;; + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little @@ -8907,7 +7827,7 @@ fi ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2.*) + freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes @@ -8916,40 +7836,41 @@ fi # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) - if test yes = "$GCC"; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi - hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes - export_dynamic_flag_spec='$wl-E' + export_dynamic_flag_spec='${wl}-E' ;; hpux10*) - if test yes,no = "$GCC,$with_gnu_ld"; then - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test no = "$with_gnu_ld"; then - hardcode_libdir_flag_spec='$wl+b $wl$libdir' + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='$wl-E' + export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes @@ -8957,72 +7878,33 @@ fi ;; hpux11*) - if test yes,no = "$GCC,$with_gnu_ld"; then + if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) - archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - - # Older versions of the 11.00 compiler do not understand -b yet - # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 -$as_echo_n "checking if $CC understands -b... " >&6; } -if ${lt_cv_prog_compiler__b+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_prog_compiler__b=no - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -b" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - lt_cv_prog_compiler__b=yes - fi - else - lt_cv_prog_compiler__b=yes - fi - fi - $RM -r conftest* - LDFLAGS=$save_LDFLAGS - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 -$as_echo "$lt_cv_prog_compiler__b" >&6; } - -if test yes = "$lt_cv_prog_compiler__b"; then - archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' -else - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' -fi - + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi - if test no = "$with_gnu_ld"; then - hardcode_libdir_flag_spec='$wl+b $wl$libdir' + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in @@ -9033,7 +7915,7 @@ fi *) hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='$wl-E' + export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -9044,58 +7926,35 @@ fi ;; irix5* | irix6* | nonstopux*) - if test yes = "$GCC"; then - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. - # This should be the same for all languages, so no per-tag cache variable. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 -$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } -if ${lt_cv_irix_exported_symbol+:} false; then : - $as_echo_n "(cached) " >&6 -else - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -int foo (void) { return 0; } +int foo(void) {} _ACEOF if ac_fn_c_try_link "$LINENO"; then : - lt_cv_irix_exported_symbol=yes -else - lt_cv_irix_exported_symbol=no + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 -$as_echo "$lt_cv_irix_exported_symbol" >&6; } - if test yes = "$lt_cv_irix_exported_symbol"; then - archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' - fi + LDFLAGS="$save_LDFLAGS" else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; - linux*) - case $cc_basename in - tcc*) - # Fabrice Bellard et al's Tiny C Compiler - ld_shlibs=yes - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -9110,7 +7969,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; @@ -9118,19 +7977,27 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } *nto* | *qnx*) ;; - openbsd* | bitrig*) + openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='$wl-rpath,$libdir' - export_dynamic_flag_spec='$wl-E' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' else - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='$wl-rpath,$libdir' + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac fi else ld_shlibs=no @@ -9141,53 +8008,33 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported - shrext_cmds=.dll - archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ - $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ - $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ - $ECHO EXPORTS >> $output_objdir/$libname.def~ - prefix_cmds="$SED"~ - if test EXPORTS = "`$SED 1q $export_symbols`"; then - prefix_cmds="$prefix_cmds -e 1d"; - fi~ - prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ - cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ - $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ - emximp -o $lib $output_objdir/$libname.def' - old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' - enable_shared_with_static_runtimes=yes + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) - if test yes = "$GCC"; then - allow_undefined_flag=' $wl-expect_unresolved $wl\*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test yes = "$GCC"; then - allow_undefined_flag=' $wl-expect_unresolved $wl\*' - archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' - hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -9198,24 +8045,24 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } solaris*) no_undefined_flag=' -z defs' - if test yes = "$GCC"; then - wlarc='$wl' - archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='$wl' - archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -9225,11 +8072,11 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands '-z linker_flag'. GCC discards it without '$wl', + # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test yes = "$GCC"; then - whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi @@ -9239,10 +8086,10 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; sunos4*) - if test sequent = "$host_vendor"; then + if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -9291,43 +8138,43 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='$wl-z,text' + no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' - if test yes = "$GCC"; then - archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We CANNOT use -z defs as we might desire, because we do not + # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - no_undefined_flag='$wl-z,text' - allow_undefined_flag='$wl-z,nodefs' + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes - export_dynamic_flag_spec='$wl-Bexport' + export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' - if test yes = "$GCC"; then - archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -9342,10 +8189,10 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } ;; esac - if test sni = "$host_vendor"; then + if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='$wl-Blargedynsym' + export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi @@ -9353,7 +8200,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } -test no = "$ld_shlibs" && can_build_shared=no +test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld @@ -9379,7 +8226,7 @@ x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes - if test yes,yes = "$GCC,$enable_shared"; then + if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -9390,50 +8237,44 @@ x|xyes) # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } -if ${lt_cv_archive_cmds_need_lc+:} false; then : - $as_echo_n "(cached) " >&6 -else - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - then - lt_cv_archive_cmds_need_lc=no - else - lt_cv_archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 -$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } - archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 +$as_echo "$archive_cmds_need_lc" >&6; } ;; esac fi @@ -9585,6 +8426,11 @@ esac + + + + + @@ -9594,58 +8440,44 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } -if test yes = "$GCC"; then +if test "$GCC" = yes; then case $host_os in - darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; - *) lt_awk_arg='/^libraries:/' ;; + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; esac - case $host_os in - mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; - *) lt_sed_strip_eq='s|=/|/|g' ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` - case $lt_search_path_spec in - *\;*) + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` - ;; - *) - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` - ;; - esac + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary... + # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= - lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - # ...but if some path component already ends with the multilib dir we assume - # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). - case "$lt_multi_os_dir; $lt_search_path_spec " in - "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) - lt_multi_os_dir= - ;; - esac + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" - elif test -n "$lt_multi_os_dir"; then + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done - lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' -BEGIN {RS = " "; FS = "/|\n";} { - lt_foo = ""; - lt_count = 0; + lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo = "/" $lt_i lt_foo; + lt_foo="/" $lt_i lt_foo; } else { lt_count--; } @@ -9655,20 +8487,14 @@ BEGIN {RS = " "; FS = "/|\n";} { if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` - # AWK program above erroneously prepends '/' to C:/dos/paths - # for these hosts. - case $host_os in - mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ - $SED 's|/\([A-Za-z]:\)|\1|g'` ;; - esac - sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` + sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=.so +shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -9685,108 +8511,56 @@ hardcode_into_libs=no # flags to be left without arguments need_version=unknown - - case $host_os in aix3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='$libname$release$shared_ext$major' + soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) - version_type=linux # correct to gnu/linux during the next big refactor + version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test ia64 = "$host_cpu"; then + if test "$host_cpu" = ia64; then # AIX 5 supports IA64 - library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line '#! .'. This would cause the generated library to - # depend on '.', always an invalid library. This was fixed in + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # Using Import Files as archive members, it is possible to support - # filename-based versioning of shared library archives on AIX. While - # this would work for both with and without runtime linking, it will - # prevent static linking of such archives. So we do filename-based - # shared library versioning with .so extension only, which is used - # when both runtime linking and shared linking is enabled. - # Unfortunately, runtime linking may impact performance, so we do - # not want this to be the default eventually. Also, we use the - # versioned .so libs for executables only if there is the -brtl - # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. - # To allow for filename-based versioning support, we need to create - # libNAME.so.V as an archive file, containing: - # *) an Import File, referring to the versioned filename of the - # archive as well as the shared archive member, telling the - # bitwidth (32 or 64) of that shared object, and providing the - # list of exported symbols of that shared object, eventually - # decorated with the 'weak' keyword - # *) the shared object with the F_LOADONLY flag set, to really avoid - # it being seen by the linker. - # At run time we better use the real file rather than another symlink, - # but for link time we create the symlink libNAME.so -> libNAME.so.V - - case $with_aix_soname,$aix_use_runtimelinking in - # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - aix,yes) # traditional libtool - dynamic_linker='AIX unversionable lib.so' + if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - ;; - aix,no) # traditional AIX only - dynamic_linker='AIX lib.a(lib.so.V)' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - ;; - svr4,*) # full svr4 only - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,yes) # both, prefer svr4 - dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" - library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' - # unpreferred sharedlib libNAME.a needs extra handling - postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' - postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' - # We do not specify a path in Import Files, so LIBPATH fires. - shlibpath_overrides_runpath=yes - ;; - *,no) # both, prefer aix - dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" - library_names_spec='$libname$release.a $libname.a' - soname_spec='$libname$release$shared_ext$major' - # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling - postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' - postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' - ;; - esac + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi shlibpath_var=LIBPATH fi ;; @@ -9796,27 +8570,27 @@ amigaos*) powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='$libname$shared_ext' + library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) - version_type=linux # correct to gnu/linux during the next big refactor + version_type=linux need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -9828,17 +8602,16 @@ bsdi[45]*) cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=.dll + shrext_cmds=".dll" need_version=no need_lib_prefix=no - case $GCC,$cc_basename in - yes,*) - # gcc + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -9854,84 +8627,37 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac - dynamic_linker='Win32 ld.exe' - ;; - - *,cl*) - # Native MSVC - libname_spec='$name' - soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' - library_names_spec='$libname.dll.lib' - - case $build_os in - mingw*) - sys_lib_search_path_spec= - lt_save_ifs=$IFS - IFS=';' - for lt_path in $LIB - do - IFS=$lt_save_ifs - # Let DOS variable expansion print the short 8.3 style file name. - lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` - sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" - done - IFS=$lt_save_ifs - # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` - ;; - cygwin*) - # Convert to unix form, then to dos form, then back to unix form - # but this time dos style (no spaces!) so that the unix form looks - # like /cygdrive/c/PROGRA~1:/cygdr... - sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` - sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` - sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - ;; - *) - sys_lib_search_path_spec=$LIB - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # FIXME: find the short name or the path components, as spaces are - # common. (e.g. "Program Files" -> "PROGRA~1") - ;; - esac - - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - dynamic_linker='Win32 link.exe' ;; *) - # Assume MSVC wrapper - library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' - dynamic_linker='Win32 ld.exe' + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac + dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; @@ -9941,8 +8667,8 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' - soname_spec='$libname$release$major$shared_ext' + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -9952,14 +8678,18 @@ darwin* | rhapsody*) ;; dgux*) - version_type=linux # correct to gnu/linux during the next big refactor + version_type=linux need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; +freebsd1*) + dynamic_linker=no + ;; + freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -9967,26 +8697,38 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[23].*) objformat=aout ;; + freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi - version_type=freebsd-$objformat + # Handle Gentoo/FreeBSD as it was Linux + case $host_vendor in + gentoo) + version_type=linux ;; + *) + version_type=freebsd-$objformat ;; + esac + case $version_type in freebsd-elf*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; + linux) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + need_lib_prefix=no + need_version=no + ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2.*) + freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) @@ -10005,16 +8747,13 @@ freebsd* | dragonfly*) esac ;; -haiku*) - version_type=linux # correct to gnu/linux during the next big refactor +gnu*) + version_type=linux need_lib_prefix=no need_version=no - dynamic_linker="$host_os runtime_loader" - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - shlibpath_var=LIBRARY_PATH - shlibpath_overrides_runpath=no - sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; @@ -10031,15 +8770,14 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' - if test 32 = "$HPUX_IA64_MODE"; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -10047,8 +8785,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -10057,22 +8795,20 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' ;; esac - # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' - # or fails outright, so override atomically: - install_override_mode=555 ;; interix[3-9]*) - version_type=linux # correct to gnu/linux during the next big refactor + version_type=linux need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -10083,16 +8819,16 @@ irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test yes = "$lt_cv_prog_gnu_ld"; then - version_type=linux # correct to gnu/linux during the next big refactor + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -10111,8 +8847,8 @@ irix5* | irix6* | nonstopux*) esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" - sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; @@ -10121,47 +8857,22 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; -linux*android*) - version_type=none # Android doesn't support versioned libraries. +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext' - soname_spec='$libname$release$shared_ext' - finish_cmds= - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - dynamic_linker='Android linker' - # Don't embed -rpath directories since the linker doesn't support them. - hardcode_libdir_flag_spec='-L$libdir' - ;; - -# This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no - # Some binutils ld are patched to set DT_RUNPATH - if ${lt_cv_shlibpath_overrides_runpath+:} false; then : - $as_echo_n "(cached) " >&6 -else - lt_cv_shlibpath_overrides_runpath=no - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -10174,31 +8885,22 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - lt_cv_shlibpath_overrides_runpath=yes + shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - -fi - - shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes - # Ideally, we could use ldconfig to report *all* directores which are - # searched for libraries, however this is still not possible. Aside from not - # being certain /sbin/ldconfig is available, command - # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, - # even though it is searched at run-time. Try to do the best guess by - # appending ld.so.conf contents (and includes) to the search path. + # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi @@ -10216,12 +8918,12 @@ netbsd*) need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -10230,8 +8932,8 @@ netbsd*) ;; newsos6) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -10240,68 +8942,58 @@ newsos6) version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd* | bitrig*) +openbsd*) version_type=sunos - sys_lib_dlsearch_path_spec=/usr/lib + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then - need_version=no - else - need_version=yes - fi - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi ;; os2*) libname_spec='$name' - version_type=windows - shrext_cmds=.dll - need_version=no + shrext_cmds=".dll" need_lib_prefix=no - # OS/2 can only load a DLL with a base name of 8 characters or less. - soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; - v=$($ECHO $release$versuffix | tr -d .-); - n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); - $ECHO $n$v`$shared_ext' - library_names_spec='${libname}_dll.$libext' + library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' - shlibpath_var=BEGINLIBPATH - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - postinstall_cmds='base_file=`basename \$file`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' + shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='$libname$release$shared_ext$major' - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) @@ -10309,11 +9001,11 @@ rdos*) ;; solaris*) - version_type=linux # correct to gnu/linux during the next big refactor + version_type=linux need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -10323,20 +9015,20 @@ solaris*) sunos4*) version_type=sunos - library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -10357,24 +9049,24 @@ sysv4 | sysv4.3*) ;; sysv4*MP*) - if test -d /usr/nec; then - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' - soname_spec='$libname$shared_ext.$major' + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=sco + version_type=freebsd-elf need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test yes = "$with_gnu_ld"; then + if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -10389,19 +9081,19 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux # correct to gnu/linux during the next big refactor + version_type=linux need_lib_prefix=no need_version=no - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) - version_type=linux # correct to gnu/linux during the next big refactor - library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' - soname_spec='$libname$release$shared_ext$major' + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -10411,40 +9103,20 @@ uts4*) esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } -test no = "$dynamic_linker" && can_build_shared=no +test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test yes = "$GCC"; then +if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then - sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi - -if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then - sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi -# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... -configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec - -# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code -func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" - -# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool -configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH - - - - - - - - - - - @@ -10536,15 +9208,15 @@ $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || - test yes = "$hardcode_automatic"; then + test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. - if test no != "$hardcode_direct" && + if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && - test no != "$hardcode_minus_L"; then + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else @@ -10559,12 +9231,12 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } -if test relink = "$hardcode_action" || - test yes = "$inherit_rpath"; then +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no -elif test yes = "$shlibpath_overrides_runpath" || - test no = "$enable_shared"; then +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi @@ -10574,7 +9246,7 @@ fi - if test yes != "$enable_dlopen"; then + if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -10584,23 +9256,23 @@ else case $host_os in beos*) - lt_cv_dlopen=load_add_on + lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen=LoadLibrary + lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen=dlopen + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : @@ -10638,10 +9310,10 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else - lt_cv_dlopen=dyld + lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes @@ -10649,18 +9321,10 @@ fi ;; - tpf*) - # Don't try to run any link tests for TPF. We know it's impossible - # because TPF is a cross-compiler, and we know how we open DSOs. - lt_cv_dlopen=dlopen - lt_cv_dlopen_libs= - lt_cv_dlopen_self=no - ;; - *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : - lt_cv_dlopen=shl_load + lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } @@ -10699,11 +9363,11 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : - lt_cv_dlopen=dlopen + lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } @@ -10742,7 +9406,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } @@ -10781,7 +9445,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : - lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } @@ -10820,7 +9484,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : - lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi @@ -10841,21 +9505,21 @@ fi ;; esac - if test no = "$lt_cv_dlopen"; then - enable_dlopen=no - else + if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes + else + enable_dlopen=no fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS=$CPPFLAGS - test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS=$LDFLAGS + save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS=$LIBS + save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 @@ -10863,13 +9527,13 @@ $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else - if test yes = "$cross_compiling"; then : + if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line $LINENO "configure" +#line 9536 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10910,13 +9574,7 @@ else # endif #endif -/* When -fvisibility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } +void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -10925,11 +9583,7 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else @@ -10942,7 +9596,7 @@ _LT_EOF (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -10962,20 +9616,20 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } - if test yes = "$lt_cv_dlopen_self"; then + if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else - if test yes = "$cross_compiling"; then : + if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line $LINENO "configure" +#line 9632 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11016,13 +9670,7 @@ else # endif #endif -/* When -fvisibility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif - -int fnord () { return 42; } +void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -11031,11 +9679,7 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else - { - if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - else puts (dlerror ()); - } + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else @@ -11048,7 +9692,7 @@ _LT_EOF (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -11069,9 +9713,9 @@ fi $as_echo "$lt_cv_dlopen_self_static" >&6; } fi - CPPFLAGS=$save_CPPFLAGS - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" ;; esac @@ -11115,7 +9759,7 @@ else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) - if test -n "$STRIP"; then + if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 @@ -11143,7 +9787,7 @@ fi - # Report what library types will actually be built + # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 @@ -11151,13 +9795,13 @@ $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } - test no = "$can_build_shared" && enable_shared=no + test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test yes = "$enable_shared" && enable_static=no + test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -11165,12 +9809,8 @@ $as_echo_n "checking whether to build shared libraries... " >&6; } ;; aix[4-9]*) - if test ia64 != "$host_cpu"; then - case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in - yes,aix,yes) ;; # shared object as lib.so file only - yes,svr4,*) ;; # shared object as lib.so archive member only - yes,*) enable_static=no ;; # shared object in lib.a archive as well - esac + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no fi ;; esac @@ -11180,7 +9820,7 @@ $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. - test yes = "$enable_shared" || enable_static=yes + test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } @@ -11194,9 +9834,7 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -CC=$lt_save_CC - - +CC="$lt_save_CC" @@ -13508,159 +12146,131 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' -macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' -macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' -enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' -enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' -pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' -enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' -shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' -SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' -ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' -PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' -host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' -host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' -host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' -build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' -build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' -build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' -SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' -Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' -GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' -EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' -FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' -LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' -NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' -LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' -max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' -ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' -exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' -lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' -lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' -lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' -lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' -lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' -reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' -reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' -OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' -deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' -file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' -file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' -want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' -DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' -sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' -AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' -AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' -archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' -STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' -RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' -old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' -old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' -old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' -lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' -CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' -CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' -compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' -GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' -lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' -nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' -lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' -lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' -objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' -MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' -lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' -need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' -MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' -DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' -NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' -LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' -OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' -OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' -libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' -shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' -extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' -archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' -export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' -whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' -compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' -old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' -archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' -archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' -module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' -module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' -with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' -allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' -no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' -hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' -hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' -hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' -hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' -hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' -hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' -inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' -link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' -always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' -export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' -exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' -include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' -prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' -postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' -file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' -variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' -need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' -need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' -version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' -runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' -shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' -shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' -libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' -library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' -soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' -install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' -postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' -postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' -finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' -finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' -hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' -sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' -configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' -configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' -hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' -enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' -enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' -enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' -old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' -striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' +macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' +enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' +pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' +host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' +host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' +host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' +build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' +build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' +build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' +SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' +Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' +GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' +EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' +FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' +LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' +NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' +LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' +ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' +exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' +lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' +reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' +AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' +STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' +RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' +compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' +GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' +SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' +ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' +need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' +LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' +libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' +fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' +need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' +version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' +runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' +libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' +soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' +finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' +old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' +striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - # Quote evaled strings. -for var in SHELL \ -ECHO \ -PATH_SEPARATOR \ -SED \ +for var in SED \ GREP \ EGREP \ FGREP \ @@ -13673,13 +12283,8 @@ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ -file_magic_glob \ -want_nocaseglob \ -DLLTOOL \ -sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ -archiver_list_spec \ STRIP \ RANLIB \ CC \ @@ -13687,19 +12292,16 @@ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ -lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ -lt_cv_nm_interface \ -nm_file_list_spec \ -lt_cv_truncate_bin \ +SHELL \ +ECHO \ lt_prog_compiler_no_builtin_flag \ -lt_prog_compiler_pic \ lt_prog_compiler_wl \ +lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ -MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ @@ -13713,7 +12315,9 @@ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ +fix_srcfile_path \ exclude_expsyms \ include_expsyms \ file_list_spec \ @@ -13721,13 +12325,12 @@ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ -install_override_mode \ finish_eval \ old_striplib \ striplib; do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -13749,16 +12352,14 @@ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ -postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ -configure_time_dlsearch_path \ -configure_time_lt_sys_library_path; do - case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -13766,17 +12367,26 @@ configure_time_lt_sys_library_path; do esac done -ac_aux_dir='$ac_aux_dir' +# Fix-up fallback echo if it was mangled by the above quoting rules. +case \$lt_ECHO in +*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` + ;; +esac -# See if we are running on zsh, and set the options that allow our +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}"; then +if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' @@ -14352,53 +12962,54 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} case $ac_file$ac_mode in "libtool":C) - # See if we are running on zsh, and set the options that allow our + # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}"; then + if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi - cfgfile=${ofile}T + cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL -# Generated automatically by $as_me ($PACKAGE) $VERSION + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. - -# Provide generalized library-building support services. -# Written by Gordon Matzigkeit, 1996 - -# Copyright (C) 2014 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of of the License, or -# (at your option) any later version. # -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program or library that is built -# using GNU Libtool, you may include this file under the same -# distribution terms that you use for the rest of that program. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 # -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. -available_tags='' - -# Configured defaults for sys_lib_dlsearch_path munging. -: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} +available_tags="" # ### BEGIN LIBTOOL CONFIG @@ -14418,18 +13029,6 @@ pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install -# Shared archive member basename,for filename based shared library versioning on AIX. -shared_archive_member_spec=$shared_archive_member_spec - -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# An echo program that protects backslashes. -ECHO=$lt_ECHO - -# The PATH separator for the build system. -PATH_SEPARATOR=$lt_PATH_SEPARATOR - # The host system. host_alias=$host_alias host=$host @@ -14479,11 +13078,9 @@ SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP -# convert \$build file names to \$host format. -to_host_file_cmd=$lt_cv_to_host_file_cmd - -# convert \$build files to toolchain format. -to_tool_file_cmd=$lt_cv_to_tool_file_cmd +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds # An object symbol dumper. OBJDUMP=$lt_OBJDUMP @@ -14491,30 +13088,13 @@ OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method -# Command to use when deplibs_check_method = "file_magic". +# Command to use when deplibs_check_method == "file_magic". file_magic_cmd=$lt_file_magic_cmd -# How to find potential files when deplibs_check_method = "file_magic". -file_magic_glob=$lt_file_magic_glob - -# Find potential files using nocaseglob when deplibs_check_method = "file_magic". -want_nocaseglob=$lt_want_nocaseglob - -# DLL creation program. -DLLTOOL=$lt_DLLTOOL - -# Command to associate shared and link libraries. -sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd - # The archiver. AR=$lt_AR - -# Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS -# How to feed a file listing to the archiver. -archiver_list_spec=$lt_archiver_list_spec - # A symbol stripping program. STRIP=$lt_STRIP @@ -14523,9 +13103,6 @@ RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds -# Whether to use a lock for old archive extraction. -lock_old_archive_extraction=$lock_old_archive_extraction - # A C compiler. LTCC=$lt_CC @@ -14538,39 +13115,27 @@ global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl -# Transform the output of nm into a list of symbols to manually relocate. -global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import - # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix -# The name lister interface. -nm_interface=$lt_lt_cv_nm_interface - -# Specify filename containing input files for \$NM. -nm_file_list_spec=$lt_nm_file_list_spec - -# The root where to search for dependent libraries,and where our libraries should be installed. -lt_sysroot=$lt_sysroot - -# Command to truncate a binary pipe. -lt_truncate_bin=$lt_lt_cv_truncate_bin - # The name of the directory that contains temporary libtool files. objdir=$objdir +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that does not interpret backslashes. +ECHO=$lt_ECHO + # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks -# Manifest tool. -MANIFEST_TOOL=$lt_MANIFEST_TOOL - # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL @@ -14627,9 +13192,6 @@ library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec -# Permission mode override for installation of shared libraries. -install_override_mode=$lt_install_override_mode - # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds @@ -14649,11 +13211,8 @@ hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec -# Detected run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path - -# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. -configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen @@ -14672,10 +13231,6 @@ striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds @@ -14688,12 +13243,12 @@ with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag -# Additional compiler flags for building library objects. -pic_flag=$lt_lt_prog_compiler_pic - # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static @@ -14743,16 +13298,20 @@ no_undefined_flag=$lt_no_undefined_flag # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct -# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute @@ -14776,6 +13335,9 @@ inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols @@ -14791,9 +13353,6 @@ include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds -# Commands necessary for finishing linking programs. -postlink_cmds=$lt_postlink_cmds - # Specify filename containing input files. file_list_spec=$lt_file_list_spec @@ -14802,65 +13361,6 @@ hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG -_LT_EOF - - cat <<'_LT_EOF' >> "$cfgfile" - -# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE - -# func_munge_path_list VARIABLE PATH -# ----------------------------------- -# VARIABLE is name of variable containing _space_ separated list of -# directories to be munged by the contents of PATH, which is string -# having a format: -# "DIR[:DIR]:" -# string "DIR[ DIR]" will be prepended to VARIABLE -# ":DIR[:DIR]" -# string "DIR[ DIR]" will be appended to VARIABLE -# "DIRP[:DIRP]::[DIRA:]DIRA" -# string "DIRP[ DIRP]" will be prepended to VARIABLE and string -# "DIRA[ DIRA]" will be appended to VARIABLE -# "DIR[:DIR]" -# VARIABLE will be replaced by "DIR[ DIR]" -func_munge_path_list () -{ - case x$2 in - x) - ;; - *:) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" - ;; - x:*) - eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" - ;; - *::*) - eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" - eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" - ;; - *) - eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" - ;; - esac -} - - -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -func_cc_basename () -{ - for cc_temp in $*""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac - done - func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` -} - - -# ### END FUNCTIONS SHARED WITH CONFIGURE - _LT_EOF case $host_os in @@ -14869,7 +13369,7 @@ _LT_EOF # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test set != "${COLLECT_NAMES+set}"; then +if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -14878,17 +13378,219 @@ _LT_EOF esac -ltmain=$ac_aux_dir/ltmain.sh +ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) + sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) - mv -f "$cfgfile" "$ofile" || + case $xsi_shell in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $* )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + +_LT_EOF + ;; + *) # Bourne compatible functions. + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` +} + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "X${3}" \ + | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + esac +} + +# sed scripts: +my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' +my_sed_long_arg='1s/^-[^=]*=//' + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` +} + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "$@"` +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` +} + +_LT_EOF +esac + +case $lt_shell_append in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1+=\$2" +} +_LT_EOF + ;; + *) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1=\$$1\$2" +} + +_LT_EOF + ;; + esac + + + sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" From d1e1e72fb05ceb787f69fdabf10e30a4a125bb2e Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Mon, 13 Jul 2015 11:58:18 -0500 Subject: [PATCH 17/36] Adjust cipher_version test for 3.3.1 release --- test/crypto.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/crypto.test b/test/crypto.test index 84f8d57..0caf7aa 100644 --- a/test/crypto.test +++ b/test/crypto.test @@ -1541,7 +1541,7 @@ do_test verify-pragma-cipher-version { execsql { PRAGMA cipher_version; } -} {3.3.0} +} {3.3.1} db close file delete -force test.db From 8554c8577fc9632355c14dd8b9c8d68f0c813533 Mon Sep 17 00:00:00 2001 From: Christian Noon Date: Tue, 17 Nov 2015 20:50:22 -0800 Subject: [PATCH 18/36] Created a new SQLCipher framework target for iOS 8.0+. --- macosx/Info.plist | 26 ++ macosx/SQLCipher.h | 5 + sqlcipher.xcodeproj/project.pbxproj | 244 +++++++++++++++++- .../xcschemes/SQLCipher iOS.xcscheme | 80 ++++++ 4 files changed, 347 insertions(+), 8 deletions(-) create mode 100644 macosx/Info.plist create mode 100644 macosx/SQLCipher.h create mode 100644 sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher iOS.xcscheme diff --git a/macosx/Info.plist b/macosx/Info.plist new file mode 100644 index 0000000..dd6cc70 --- /dev/null +++ b/macosx/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.3.1 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/macosx/SQLCipher.h b/macosx/SQLCipher.h new file mode 100644 index 0000000..d43dd88 --- /dev/null +++ b/macosx/SQLCipher.h @@ -0,0 +1,5 @@ + +@import Foundation; + +FOUNDATION_EXPORT double SQLCipherVersionNumber; +FOUNDATION_EXPORT const unsigned char SQLCipherVersionString[]; diff --git a/sqlcipher.xcodeproj/project.pbxproj b/sqlcipher.xcodeproj/project.pbxproj index a3459bc..cd79669 100644 --- a/sqlcipher.xcodeproj/project.pbxproj +++ b/sqlcipher.xcodeproj/project.pbxproj @@ -21,7 +21,8 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 28B46E6317CD07A700672510 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28B46E6217CD07A600672510 /* Security.framework */; }; + 4C0041A61BFC3A5000ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041A51BFC3A5000ED2AD5 /* Security.framework */; }; + 4C0041AB1BFC3A7E00ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9069D0A30FCE1A4D0042E34C /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; /* End PBXBuildFile section */ @@ -33,20 +34,37 @@ remoteGlobalIDString = 9069D08B0FCE185A0042E34C; remoteInfo = amalgamation; }; + 4C0041A11BFC392D00ED2AD5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9069D08B0FCE185A0042E34C; + remoteInfo = amalgamation; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 28B46E6217CD07A600672510 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 4C0041981BFC382400ED2AD5 /* SQLCipher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLCipher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C0041A51BFC3A5000ED2AD5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 4C0041A81BFC3A7E00ED2AD5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = macosx/Info.plist; sourceTree = ""; }; + 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLCipher.h; path = macosx/SQLCipher.h; sourceTree = ""; }; 9069D0A20FCE1A4D0042E34C /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite3.c; sourceTree = ""; }; D2AAC046055464E500DB518D /* libsqlcipher.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsqlcipher.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 4C0041941BFC382400ED2AD5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D289987405E68DCB004EDB86 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 28B46E6317CD07A700672510 /* Security.framework in Frameworks */, + 4C0041A61BFC3A5000ED2AD5 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -56,9 +74,9 @@ 08FB7794FE84155DC02AAC07 /* sqlcipher */ = { isa = PBXGroup; children = ( - 28B46E6217CD07A600672510 /* Security.framework */, 08FB7795FE84155DC02AAC07 /* Source */, - C6A0FF2B0290797F04C91782 /* Documentation */, + 4C0041A41BFC3A3800ED2AD5 /* Supporting Files */, + 4C0041A71BFC3A5400ED2AD5 /* Frameworks */, 1AB674ADFE9D54B511CA2CBB /* Products */, ); name = sqlcipher; @@ -76,20 +94,39 @@ isa = PBXGroup; children = ( D2AAC046055464E500DB518D /* libsqlcipher.a */, + 4C0041981BFC382400ED2AD5 /* SQLCipher.framework */, ); name = Products; sourceTree = ""; }; - C6A0FF2B0290797F04C91782 /* Documentation */ = { + 4C0041A41BFC3A3800ED2AD5 /* Supporting Files */ = { isa = PBXGroup; children = ( + 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */, + 4C0041A81BFC3A7E00ED2AD5 /* Info.plist */, ); - name = Documentation; + name = "Supporting Files"; + sourceTree = ""; + }; + 4C0041A71BFC3A5400ED2AD5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4C0041A51BFC3A5000ED2AD5 /* Security.framework */, + ); + name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 4C0041951BFC382400ED2AD5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C0041AB1BFC3A7E00ED2AD5 /* SQLCipher.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D2AAC043055464E500DB518D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -100,6 +137,25 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 4C0041971BFC382400ED2AD5 /* SQLCipher iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C00419D1BFC382500ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher iOS" */; + buildPhases = ( + 4C0041931BFC382400ED2AD5 /* Sources */, + 4C0041941BFC382400ED2AD5 /* Frameworks */, + 4C0041951BFC382400ED2AD5 /* Headers */, + 4C0041961BFC382400ED2AD5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4C0041A21BFC392D00ED2AD5 /* PBXTargetDependency */, + ); + name = "SQLCipher iOS"; + productName = SQLCipher; + productReference = 4C0041981BFC382400ED2AD5 /* SQLCipher.framework */; + productType = "com.apple.product-type.framework"; + }; D2AAC045055464E500DB518D /* sqlcipher */ = { isa = PBXNativeTarget; buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "sqlcipher" */; @@ -124,7 +180,12 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0450; + LastUpgradeCheck = 0710; + TargetAttributes = { + 4C0041971BFC382400ED2AD5 = { + CreatedOnToolsVersion = 7.1; + }; + }; }; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "sqlcipher" */; compatibilityVersion = "Xcode 3.2"; @@ -140,12 +201,23 @@ projectDirPath = ""; projectRoot = ""; targets = ( + 4C0041971BFC382400ED2AD5 /* SQLCipher iOS */, D2AAC045055464E500DB518D /* sqlcipher */, 9069D08B0FCE185A0042E34C /* amalgamation */, ); }; /* End PBXProject section */ +/* Begin PBXResourcesBuildPhase section */ + 4C0041961BFC382400ED2AD5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + /* Begin PBXShellScriptBuildPhase section */ 9069D08A0FCE185A0042E34C /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -164,6 +236,13 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 4C0041931BFC382400ED2AD5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D2AAC044055464E500DB518D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -180,6 +259,11 @@ target = 9069D08B0FCE185A0042E34C /* amalgamation */; targetProxy = 289BE0E7180C4930003E52DA /* PBXContainerItemProxy */; }; + 4C0041A21BFC392D00ED2AD5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9069D08B0FCE185A0042E34C /* amalgamation */; + targetProxy = 4C0041A11BFC392D00ED2AD5 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -258,6 +342,7 @@ x86_64, i386, ); + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -299,6 +384,141 @@ }; name = Release; }; + 4C00419E1BFC382500ED2AD5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; + BITCODE_GENERATION_MODE = marker; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = macosx/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_CFLAGS = ( + "-DSQLITE_HAS_CODEC", + "-DSQLITE_TEMP_STORE=2", + "-DSQLITE_THREADSAFE", + "-DSQLCIPHER_CRYPTO_CC", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; + PRODUCT_NAME = SQLCipher; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALID_ARCHS = "arm64 armv7 armv7s"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Debug; + }; + 4C00419F1BFC382500ED2AD5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; + BITCODE_GENERATION_MODE = bitcode; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = macosx/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = ( + "-DSQLITE_HAS_CODEC", + "-DSQLITE_TEMP_STORE=2", + "-DSQLITE_THREADSAFE", + "-DSQLCIPHER_CRYPTO_CC", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; + PRODUCT_NAME = SQLCipher; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + TARGETED_DEVICE_FAMILY = "1,2"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + VALID_ARCHS = "arm64 armv7 armv7s"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; 9069D08C0FCE185A0042E34C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -346,6 +566,14 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 4C00419D1BFC382500ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C00419E1BFC382500ED2AD5 /* Debug */, + 4C00419F1BFC382500ED2AD5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; 9069D0900FCE18970042E34C /* Build configuration list for PBXAggregateTarget "amalgamation" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher iOS.xcscheme b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher iOS.xcscheme new file mode 100644 index 0000000..a988b2b --- /dev/null +++ b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher iOS.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a2d461cd6d6693402d48d20d47a8e9d206ce7eb0 Mon Sep 17 00:00:00 2001 From: Christian Noon Date: Tue, 17 Nov 2015 20:57:18 -0800 Subject: [PATCH 19/36] Added a new OSX framework target for OS X 10.9+. --- sqlcipher.xcodeproj/project.pbxproj | 229 +++++++++++++++++- .../xcschemes/SQLCipher OSX.xcscheme | 80 ++++++ 2 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher OSX.xcscheme diff --git a/sqlcipher.xcodeproj/project.pbxproj b/sqlcipher.xcodeproj/project.pbxproj index cd79669..6d8dbdc 100644 --- a/sqlcipher.xcodeproj/project.pbxproj +++ b/sqlcipher.xcodeproj/project.pbxproj @@ -23,6 +23,9 @@ /* Begin PBXBuildFile section */ 4C0041A61BFC3A5000ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041A51BFC3A5000ED2AD5 /* Security.framework */; }; 4C0041AB1BFC3A7E00ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041B41BFC3B2200ED2AD5 /* SQLCipher OSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041B31BFC3B2200ED2AD5 /* SQLCipher OSX.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041BC1BFC3C7500ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041BB1BFC3C7500ED2AD5 /* Security.framework */; }; + 4C0041BD1BFC3C8300ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9069D0A30FCE1A4D0042E34C /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; /* End PBXBuildFile section */ @@ -41,6 +44,13 @@ remoteGlobalIDString = 9069D08B0FCE185A0042E34C; remoteInfo = amalgamation; }; + 4C0041B91BFC3C6E00ED2AD5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9069D08B0FCE185A0042E34C; + remoteInfo = amalgamation; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -48,6 +58,10 @@ 4C0041A51BFC3A5000ED2AD5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 4C0041A81BFC3A7E00ED2AD5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = macosx/Info.plist; sourceTree = ""; }; 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLCipher.h; path = macosx/SQLCipher.h; sourceTree = ""; }; + 4C0041B11BFC3B2200ED2AD5 /* SQLCipher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLCipher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C0041B31BFC3B2200ED2AD5 /* SQLCipher OSX.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SQLCipher OSX.h"; sourceTree = ""; }; + 4C0041B51BFC3B2200ED2AD5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 4C0041BB1BFC3C7500ED2AD5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; 9069D0A20FCE1A4D0042E34C /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite3.c; sourceTree = ""; }; D2AAC046055464E500DB518D /* libsqlcipher.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsqlcipher.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -60,6 +74,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041AD1BFC3B2200ED2AD5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C0041BC1BFC3C7500ED2AD5 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D289987405E68DCB004EDB86 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -76,6 +98,7 @@ children = ( 08FB7795FE84155DC02AAC07 /* Source */, 4C0041A41BFC3A3800ED2AD5 /* Supporting Files */, + 4C0041B21BFC3B2200ED2AD5 /* SQLCipher OSX */, 4C0041A71BFC3A5400ED2AD5 /* Frameworks */, 1AB674ADFE9D54B511CA2CBB /* Products */, ); @@ -95,6 +118,7 @@ children = ( D2AAC046055464E500DB518D /* libsqlcipher.a */, 4C0041981BFC382400ED2AD5 /* SQLCipher.framework */, + 4C0041B11BFC3B2200ED2AD5 /* SQLCipher.framework */, ); name = Products; sourceTree = ""; @@ -111,11 +135,21 @@ 4C0041A71BFC3A5400ED2AD5 /* Frameworks */ = { isa = PBXGroup; children = ( + 4C0041BB1BFC3C7500ED2AD5 /* Security.framework */, 4C0041A51BFC3A5000ED2AD5 /* Security.framework */, ); name = Frameworks; sourceTree = ""; }; + 4C0041B21BFC3B2200ED2AD5 /* SQLCipher OSX */ = { + isa = PBXGroup; + children = ( + 4C0041B31BFC3B2200ED2AD5 /* SQLCipher OSX.h */, + 4C0041B51BFC3B2200ED2AD5 /* Info.plist */, + ); + path = "SQLCipher OSX"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -127,6 +161,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041AE1BFC3B2200ED2AD5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C0041BD1BFC3C8300ED2AD5 /* SQLCipher.h in Headers */, + 4C0041B41BFC3B2200ED2AD5 /* SQLCipher OSX.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D2AAC043055464E500DB518D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -156,6 +199,25 @@ productReference = 4C0041981BFC382400ED2AD5 /* SQLCipher.framework */; productType = "com.apple.product-type.framework"; }; + 4C0041B01BFC3B2200ED2AD5 /* SQLCipher OSX */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C0041B61BFC3B2200ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher OSX" */; + buildPhases = ( + 4C0041AC1BFC3B2200ED2AD5 /* Sources */, + 4C0041AD1BFC3B2200ED2AD5 /* Frameworks */, + 4C0041AE1BFC3B2200ED2AD5 /* Headers */, + 4C0041AF1BFC3B2200ED2AD5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4C0041BA1BFC3C6E00ED2AD5 /* PBXTargetDependency */, + ); + name = "SQLCipher OSX"; + productName = "SQLCipher OSX"; + productReference = 4C0041B11BFC3B2200ED2AD5 /* SQLCipher.framework */; + productType = "com.apple.product-type.framework"; + }; D2AAC045055464E500DB518D /* sqlcipher */ = { isa = PBXNativeTarget; buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "sqlcipher" */; @@ -185,6 +247,9 @@ 4C0041971BFC382400ED2AD5 = { CreatedOnToolsVersion = 7.1; }; + 4C0041B01BFC3B2200ED2AD5 = { + CreatedOnToolsVersion = 7.1; + }; }; }; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "sqlcipher" */; @@ -202,6 +267,7 @@ projectRoot = ""; targets = ( 4C0041971BFC382400ED2AD5 /* SQLCipher iOS */, + 4C0041B01BFC3B2200ED2AD5 /* SQLCipher OSX */, D2AAC045055464E500DB518D /* sqlcipher */, 9069D08B0FCE185A0042E34C /* amalgamation */, ); @@ -216,6 +282,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041AF1BFC3B2200ED2AD5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -243,6 +316,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041AC1BFC3B2200ED2AD5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D2AAC044055464E500DB518D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -264,6 +344,11 @@ target = 9069D08B0FCE185A0042E34C /* amalgamation */; targetProxy = 4C0041A11BFC392D00ED2AD5 /* PBXContainerItemProxy */; }; + 4C0041BA1BFC3C6E00ED2AD5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9069D08B0FCE185A0042E34C /* amalgamation */; + targetProxy = 4C0041B91BFC3C6E00ED2AD5 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -388,7 +473,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; BITCODE_GENERATION_MODE = marker; @@ -519,6 +603,141 @@ }; name = Release; }; + 4C0041B71BFC3B2200ED2AD5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; + BITCODE_GENERATION_MODE = marker; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_VERSION = A; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = macosx/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_CFLAGS = ( + "-DSQLITE_HAS_CODEC", + "-DSQLITE_TEMP_STORE=2", + "-DSQLITE_THREADSAFE", + "-DSQLCIPHER_CRYPTO_CC", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; + PRODUCT_NAME = SQLCipher; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALID_ARCHS = "i386 x86_64"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Debug; + }; + 4C0041B81BFC3B2200ED2AD5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; + BITCODE_GENERATION_MODE = bitcode; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FRAMEWORK_VERSION = A; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = macosx/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = ( + "-DSQLITE_HAS_CODEC", + "-DSQLITE_TEMP_STORE=2", + "-DSQLITE_THREADSAFE", + "-DSQLCIPHER_CRYPTO_CC", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; + PRODUCT_NAME = SQLCipher; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = macosx; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALID_ARCHS = "i386 x86_64"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; 9069D08C0FCE185A0042E34C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -574,6 +793,14 @@ ); defaultConfigurationIsVisible = 0; }; + 4C0041B61BFC3B2200ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher OSX" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C0041B71BFC3B2200ED2AD5 /* Debug */, + 4C0041B81BFC3B2200ED2AD5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; 9069D0900FCE18970042E34C /* Build configuration list for PBXAggregateTarget "amalgamation" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher OSX.xcscheme b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher OSX.xcscheme new file mode 100644 index 0000000..9b69b15 --- /dev/null +++ b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher OSX.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 71691b6a1ccd2a7ae2d0fa8f03ad822ae6aaac9e Mon Sep 17 00:00:00 2001 From: Christian Noon Date: Tue, 17 Nov 2015 21:03:22 -0800 Subject: [PATCH 20/36] Created a new tvOS framework target supporting tvOS 9.0+. --- macosx/Info-tvOS.plist | 30 +++ sqlcipher.xcodeproj/project.pbxproj | 221 ++++++++++++++++-- .../xcschemes/SQLCipher OSX.xcscheme | 6 +- .../xcschemes/SQLCipher tvOS.xcscheme | 80 +++++++ 4 files changed, 320 insertions(+), 17 deletions(-) create mode 100644 macosx/Info-tvOS.plist create mode 100644 sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher tvOS.xcscheme diff --git a/macosx/Info-tvOS.plist b/macosx/Info-tvOS.plist new file mode 100644 index 0000000..5234c89 --- /dev/null +++ b/macosx/Info-tvOS.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.3.1 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + UIRequiredDeviceCapabilities + + arm64 + + + diff --git a/sqlcipher.xcodeproj/project.pbxproj b/sqlcipher.xcodeproj/project.pbxproj index 6d8dbdc..6e92c21 100644 --- a/sqlcipher.xcodeproj/project.pbxproj +++ b/sqlcipher.xcodeproj/project.pbxproj @@ -23,9 +23,10 @@ /* Begin PBXBuildFile section */ 4C0041A61BFC3A5000ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041A51BFC3A5000ED2AD5 /* Security.framework */; }; 4C0041AB1BFC3A7E00ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4C0041B41BFC3B2200ED2AD5 /* SQLCipher OSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041B31BFC3B2200ED2AD5 /* SQLCipher OSX.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4C0041BC1BFC3C7500ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041BB1BFC3C7500ED2AD5 /* Security.framework */; }; 4C0041BD1BFC3C8300ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041CE1BFC3D3900ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041CD1BFC3D3900ED2AD5 /* Security.framework */; }; + 4C0041CF1BFC3D4000ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9069D0A30FCE1A4D0042E34C /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; /* End PBXBuildFile section */ @@ -51,6 +52,13 @@ remoteGlobalIDString = 9069D08B0FCE185A0042E34C; remoteInfo = amalgamation; }; + 4C0041CB1BFC3D3000ED2AD5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9069D08B0FCE185A0042E34C; + remoteInfo = amalgamation; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -59,9 +67,10 @@ 4C0041A81BFC3A7E00ED2AD5 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = macosx/Info.plist; sourceTree = ""; }; 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLCipher.h; path = macosx/SQLCipher.h; sourceTree = ""; }; 4C0041B11BFC3B2200ED2AD5 /* SQLCipher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLCipher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C0041B31BFC3B2200ED2AD5 /* SQLCipher OSX.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SQLCipher OSX.h"; sourceTree = ""; }; - 4C0041B51BFC3B2200ED2AD5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4C0041BB1BFC3C7500ED2AD5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 4C0041C31BFC3CC000ED2AD5 /* SQLCipher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLCipher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C0041CD1BFC3D3900ED2AD5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 4C0041D01BFC3D9A00ED2AD5 /* Info-tvOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-tvOS.plist"; path = "macosx/Info-tvOS.plist"; sourceTree = ""; }; 9069D0A20FCE1A4D0042E34C /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite3.c; sourceTree = ""; }; D2AAC046055464E500DB518D /* libsqlcipher.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsqlcipher.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -82,6 +91,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041BF1BFC3CC000ED2AD5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C0041CE1BFC3D3900ED2AD5 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D289987405E68DCB004EDB86 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -98,7 +115,6 @@ children = ( 08FB7795FE84155DC02AAC07 /* Source */, 4C0041A41BFC3A3800ED2AD5 /* Supporting Files */, - 4C0041B21BFC3B2200ED2AD5 /* SQLCipher OSX */, 4C0041A71BFC3A5400ED2AD5 /* Frameworks */, 1AB674ADFE9D54B511CA2CBB /* Products */, ); @@ -119,6 +135,7 @@ D2AAC046055464E500DB518D /* libsqlcipher.a */, 4C0041981BFC382400ED2AD5 /* SQLCipher.framework */, 4C0041B11BFC3B2200ED2AD5 /* SQLCipher.framework */, + 4C0041C31BFC3CC000ED2AD5 /* SQLCipher.framework */, ); name = Products; sourceTree = ""; @@ -128,6 +145,7 @@ children = ( 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */, 4C0041A81BFC3A7E00ED2AD5 /* Info.plist */, + 4C0041D01BFC3D9A00ED2AD5 /* Info-tvOS.plist */, ); name = "Supporting Files"; sourceTree = ""; @@ -135,21 +153,13 @@ 4C0041A71BFC3A5400ED2AD5 /* Frameworks */ = { isa = PBXGroup; children = ( + 4C0041CD1BFC3D3900ED2AD5 /* Security.framework */, 4C0041BB1BFC3C7500ED2AD5 /* Security.framework */, 4C0041A51BFC3A5000ED2AD5 /* Security.framework */, ); name = Frameworks; sourceTree = ""; }; - 4C0041B21BFC3B2200ED2AD5 /* SQLCipher OSX */ = { - isa = PBXGroup; - children = ( - 4C0041B31BFC3B2200ED2AD5 /* SQLCipher OSX.h */, - 4C0041B51BFC3B2200ED2AD5 /* Info.plist */, - ); - path = "SQLCipher OSX"; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -166,7 +176,14 @@ buildActionMask = 2147483647; files = ( 4C0041BD1BFC3C8300ED2AD5 /* SQLCipher.h in Headers */, - 4C0041B41BFC3B2200ED2AD5 /* SQLCipher OSX.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C0041C01BFC3CC000ED2AD5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C0041CF1BFC3D4000ED2AD5 /* SQLCipher.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -218,6 +235,25 @@ productReference = 4C0041B11BFC3B2200ED2AD5 /* SQLCipher.framework */; productType = "com.apple.product-type.framework"; }; + 4C0041C21BFC3CC000ED2AD5 /* SQLCipher tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C0041C81BFC3CC000ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher tvOS" */; + buildPhases = ( + 4C0041BE1BFC3CC000ED2AD5 /* Sources */, + 4C0041BF1BFC3CC000ED2AD5 /* Frameworks */, + 4C0041C01BFC3CC000ED2AD5 /* Headers */, + 4C0041C11BFC3CC000ED2AD5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4C0041CC1BFC3D3000ED2AD5 /* PBXTargetDependency */, + ); + name = "SQLCipher tvOS"; + productName = "SQLCipher tvOS"; + productReference = 4C0041C31BFC3CC000ED2AD5 /* SQLCipher.framework */; + productType = "com.apple.product-type.framework"; + }; D2AAC045055464E500DB518D /* sqlcipher */ = { isa = PBXNativeTarget; buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "sqlcipher" */; @@ -250,6 +286,9 @@ 4C0041B01BFC3B2200ED2AD5 = { CreatedOnToolsVersion = 7.1; }; + 4C0041C21BFC3CC000ED2AD5 = { + CreatedOnToolsVersion = 7.1; + }; }; }; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "sqlcipher" */; @@ -268,6 +307,7 @@ targets = ( 4C0041971BFC382400ED2AD5 /* SQLCipher iOS */, 4C0041B01BFC3B2200ED2AD5 /* SQLCipher OSX */, + 4C0041C21BFC3CC000ED2AD5 /* SQLCipher tvOS */, D2AAC045055464E500DB518D /* sqlcipher */, 9069D08B0FCE185A0042E34C /* amalgamation */, ); @@ -289,6 +329,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041C11BFC3CC000ED2AD5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -323,6 +370,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041BE1BFC3CC000ED2AD5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D2AAC044055464E500DB518D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -349,6 +403,11 @@ target = 9069D08B0FCE185A0042E34C /* amalgamation */; targetProxy = 4C0041B91BFC3C6E00ED2AD5 /* PBXContainerItemProxy */; }; + 4C0041CC1BFC3D3000ED2AD5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9069D08B0FCE185A0042E34C /* amalgamation */; + targetProxy = 4C0041CB1BFC3D3000ED2AD5 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -738,6 +797,132 @@ }; name = Release; }; + 4C0041C91BFC3CC000ED2AD5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; + BITCODE_GENERATION_MODE = marker; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = "macosx/Info-tvOS.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_CFLAGS = ( + "-DSQLITE_HAS_CODEC", + "-DSQLITE_TEMP_STORE=2", + "-DSQLITE_THREADSAFE", + "-DSQLCIPHER_CRYPTO_CC", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; + PRODUCT_NAME = SQLCipher; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALID_ARCHS = arm64; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 4C0041CA1BFC3CC000ED2AD5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; + BITCODE_GENERATION_MODE = bitcode; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = "macosx/Info-tvOS.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = ( + "-DSQLITE_HAS_CODEC", + "-DSQLITE_TEMP_STORE=2", + "-DSQLITE_THREADSAFE", + "-DSQLCIPHER_CRYPTO_CC", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; + PRODUCT_NAME = SQLCipher; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + VALID_ARCHS = arm64; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; 9069D08C0FCE185A0042E34C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -801,6 +986,14 @@ ); defaultConfigurationIsVisible = 0; }; + 4C0041C81BFC3CC000ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C0041C91BFC3CC000ED2AD5 /* Debug */, + 4C0041CA1BFC3CC000ED2AD5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; 9069D0900FCE18970042E34C /* Build configuration list for PBXAggregateTarget "amalgamation" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher OSX.xcscheme b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher OSX.xcscheme index 9b69b15..a1b6956 100644 --- a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher OSX.xcscheme +++ b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher OSX.xcscheme @@ -15,7 +15,7 @@ @@ -46,7 +46,7 @@ @@ -64,7 +64,7 @@ diff --git a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher tvOS.xcscheme b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher tvOS.xcscheme new file mode 100644 index 0000000..64430e2 --- /dev/null +++ b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher tvOS.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 1372da7f603c99ac2509c2d9a3e41ff66e100b0c Mon Sep 17 00:00:00 2001 From: Christian Noon Date: Tue, 17 Nov 2015 21:09:56 -0800 Subject: [PATCH 21/36] Created a new watchOS framework target supporting watchOS 2.0+. --- sqlcipher.xcodeproj/project.pbxproj | 219 ++++++++++++++++++ .../xcschemes/SQLCipher tvOS.xcscheme | 6 +- .../xcschemes/SQLCipher watchOS.xcscheme | 80 +++++++ 3 files changed, 302 insertions(+), 3 deletions(-) create mode 100644 sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher watchOS.xcscheme diff --git a/sqlcipher.xcodeproj/project.pbxproj b/sqlcipher.xcodeproj/project.pbxproj index 6e92c21..5cbe282 100644 --- a/sqlcipher.xcodeproj/project.pbxproj +++ b/sqlcipher.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 4C0041BD1BFC3C8300ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4C0041CE1BFC3D3900ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041CD1BFC3D3900ED2AD5 /* Security.framework */; }; 4C0041CF1BFC3D4000ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041E11BFC3F0800ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041E01BFC3F0800ED2AD5 /* Security.framework */; }; + 4C0041E21BFC3F5A00ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9069D0A30FCE1A4D0042E34C /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; /* End PBXBuildFile section */ @@ -59,6 +61,13 @@ remoteGlobalIDString = 9069D08B0FCE185A0042E34C; remoteInfo = amalgamation; }; + 4C0041DE1BFC3F0100ED2AD5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9069D08B0FCE185A0042E34C; + remoteInfo = amalgamation; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -71,6 +80,8 @@ 4C0041C31BFC3CC000ED2AD5 /* SQLCipher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLCipher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4C0041CD1BFC3D3900ED2AD5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.0.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; 4C0041D01BFC3D9A00ED2AD5 /* Info-tvOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-tvOS.plist"; path = "macosx/Info-tvOS.plist"; sourceTree = ""; }; + 4C0041D61BFC3E2500ED2AD5 /* SQLCipher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLCipher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C0041E01BFC3F0800ED2AD5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS2.0.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; 9069D0A20FCE1A4D0042E34C /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite3.c; sourceTree = ""; }; D2AAC046055464E500DB518D /* libsqlcipher.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsqlcipher.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -99,6 +110,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041D21BFC3E2500ED2AD5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C0041E11BFC3F0800ED2AD5 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D289987405E68DCB004EDB86 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -136,6 +155,7 @@ 4C0041981BFC382400ED2AD5 /* SQLCipher.framework */, 4C0041B11BFC3B2200ED2AD5 /* SQLCipher.framework */, 4C0041C31BFC3CC000ED2AD5 /* SQLCipher.framework */, + 4C0041D61BFC3E2500ED2AD5 /* SQLCipher.framework */, ); name = Products; sourceTree = ""; @@ -153,6 +173,7 @@ 4C0041A71BFC3A5400ED2AD5 /* Frameworks */ = { isa = PBXGroup; children = ( + 4C0041E01BFC3F0800ED2AD5 /* Security.framework */, 4C0041CD1BFC3D3900ED2AD5 /* Security.framework */, 4C0041BB1BFC3C7500ED2AD5 /* Security.framework */, 4C0041A51BFC3A5000ED2AD5 /* Security.framework */, @@ -187,6 +208,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041D31BFC3E2500ED2AD5 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C0041E21BFC3F5A00ED2AD5 /* SQLCipher.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D2AAC043055464E500DB518D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -254,6 +283,25 @@ productReference = 4C0041C31BFC3CC000ED2AD5 /* SQLCipher.framework */; productType = "com.apple.product-type.framework"; }; + 4C0041D51BFC3E2500ED2AD5 /* SQLCipher watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C0041DB1BFC3E2600ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher watchOS" */; + buildPhases = ( + 4C0041D11BFC3E2500ED2AD5 /* Sources */, + 4C0041D21BFC3E2500ED2AD5 /* Frameworks */, + 4C0041D31BFC3E2500ED2AD5 /* Headers */, + 4C0041D41BFC3E2500ED2AD5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4C0041DF1BFC3F0100ED2AD5 /* PBXTargetDependency */, + ); + name = "SQLCipher watchOS"; + productName = SQLCipher; + productReference = 4C0041D61BFC3E2500ED2AD5 /* SQLCipher.framework */; + productType = "com.apple.product-type.framework"; + }; D2AAC045055464E500DB518D /* sqlcipher */ = { isa = PBXNativeTarget; buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "sqlcipher" */; @@ -289,6 +337,9 @@ 4C0041C21BFC3CC000ED2AD5 = { CreatedOnToolsVersion = 7.1; }; + 4C0041D51BFC3E2500ED2AD5 = { + CreatedOnToolsVersion = 7.1; + }; }; }; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "sqlcipher" */; @@ -308,6 +359,7 @@ 4C0041971BFC382400ED2AD5 /* SQLCipher iOS */, 4C0041B01BFC3B2200ED2AD5 /* SQLCipher OSX */, 4C0041C21BFC3CC000ED2AD5 /* SQLCipher tvOS */, + 4C0041D51BFC3E2500ED2AD5 /* SQLCipher watchOS */, D2AAC045055464E500DB518D /* sqlcipher */, 9069D08B0FCE185A0042E34C /* amalgamation */, ); @@ -336,6 +388,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041D41BFC3E2500ED2AD5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -377,6 +436,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C0041D11BFC3E2500ED2AD5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D2AAC044055464E500DB518D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -408,6 +474,11 @@ target = 9069D08B0FCE185A0042E34C /* amalgamation */; targetProxy = 4C0041CB1BFC3D3000ED2AD5 /* PBXContainerItemProxy */; }; + 4C0041DF1BFC3F0100ED2AD5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9069D08B0FCE185A0042E34C /* amalgamation */; + targetProxy = 4C0041DE1BFC3F0100ED2AD5 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -840,7 +911,9 @@ GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "macosx/Info-tvOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = YES; OTHER_CFLAGS = ( "-DSQLITE_HAS_CODEC", @@ -859,6 +932,7 @@ VALID_ARCHS = arm64; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Debug; }; @@ -901,7 +975,9 @@ GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "macosx/Info-tvOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = ( "-DSQLITE_HAS_CODEC", @@ -920,6 +996,141 @@ VALID_ARCHS = arm64; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; + 4C0041DC1BFC3E2600ED2AD5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; + BITCODE_GENERATION_MODE = marker; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = macosx/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_CFLAGS = ( + "-DSQLITE_HAS_CODEC", + "-DSQLITE_TEMP_STORE=2", + "-DSQLITE_THREADSAFE", + "-DSQLCIPHER_CRYPTO_CC", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; + PRODUCT_NAME = SQLCipher; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "watchsimulator watchos"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = 4; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALID_ARCHS = armv7k; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Debug; + }; + 4C0041DD1BFC3E2600ED2AD5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + APPLICATION_EXTENSION_API_ONLY = YES; + "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=iphonesimulator*]" = "$(ARCHS_STANDARD)"; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD)"; + BITCODE_GENERATION_MODE = bitcode; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = macosx/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.9; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = ( + "-DSQLITE_HAS_CODEC", + "-DSQLITE_TEMP_STORE=2", + "-DSQLITE_THREADSAFE", + "-DSQLCIPHER_CRYPTO_CC", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; + PRODUCT_NAME = SQLCipher; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "watchsimulator watchos"; + TARGETED_DEVICE_FAMILY = 4; + TVOS_DEPLOYMENT_TARGET = 9.0; + VALIDATE_PRODUCT = YES; + VALID_ARCHS = armv7k; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Release; }; @@ -994,6 +1205,14 @@ ); defaultConfigurationIsVisible = 0; }; + 4C0041DB1BFC3E2600ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C0041DC1BFC3E2600ED2AD5 /* Debug */, + 4C0041DD1BFC3E2600ED2AD5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; 9069D0900FCE18970042E34C /* Build configuration list for PBXAggregateTarget "amalgamation" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher tvOS.xcscheme b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher tvOS.xcscheme index 64430e2..9104d67 100644 --- a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher tvOS.xcscheme +++ b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher tvOS.xcscheme @@ -15,7 +15,7 @@ @@ -46,7 +46,7 @@ @@ -64,7 +64,7 @@ diff --git a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher watchOS.xcscheme b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher watchOS.xcscheme new file mode 100644 index 0000000..c0058e9 --- /dev/null +++ b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher watchOS.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 09b03f1646130a1582954dcf6c797b22afc492d1 Mon Sep 17 00:00:00 2001 From: Christian Noon Date: Tue, 17 Nov 2015 21:28:53 -0800 Subject: [PATCH 22/36] Updated buildable name in watchOS scheme to latest version. --- .../xcshareddata/xcschemes/SQLCipher watchOS.xcscheme | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher watchOS.xcscheme b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher watchOS.xcscheme index c0058e9..db6e6d9 100644 --- a/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher watchOS.xcscheme +++ b/sqlcipher.xcodeproj/xcshareddata/xcschemes/SQLCipher watchOS.xcscheme @@ -15,7 +15,7 @@ @@ -46,7 +46,7 @@ @@ -64,7 +64,7 @@ From f4595d3e5ffe386bb0033a0e80b8135f993b4d12 Mon Sep 17 00:00:00 2001 From: Christian Noon Date: Tue, 17 Nov 2015 22:10:00 -0800 Subject: [PATCH 23/36] Fixed build related issues with included files and umbrella header. Resolved the following: - Added sqlite3.h to the project to be copied in framework bundle - Added sqlite3.c to all the framework targets to be compiled - Added sqlite3.h to umbrella header - Added clang warning suppression to compile without warnings --- macosx/SQLCipher.h | 2 + sqlcipher.xcodeproj/project.pbxproj | 84 +++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/macosx/SQLCipher.h b/macosx/SQLCipher.h index d43dd88..1023799 100644 --- a/macosx/SQLCipher.h +++ b/macosx/SQLCipher.h @@ -3,3 +3,5 @@ FOUNDATION_EXPORT double SQLCipherVersionNumber; FOUNDATION_EXPORT const unsigned char SQLCipherVersionString[]; + +#import "sqlite3.h" diff --git a/sqlcipher.xcodeproj/project.pbxproj b/sqlcipher.xcodeproj/project.pbxproj index 5cbe282..b15edcc 100644 --- a/sqlcipher.xcodeproj/project.pbxproj +++ b/sqlcipher.xcodeproj/project.pbxproj @@ -29,6 +29,14 @@ 4C0041CF1BFC3D4000ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4C0041E11BFC3F0800ED2AD5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C0041E01BFC3F0800ED2AD5 /* Security.framework */; }; 4C0041E21BFC3F5A00ED2AD5 /* SQLCipher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041A91BFC3A7E00ED2AD5 /* SQLCipher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041FA1BFC46A600ED2AD5 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041F91BFC46A600ED2AD5 /* sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041FB1BFC46A600ED2AD5 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041F91BFC46A600ED2AD5 /* sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041FC1BFC46A600ED2AD5 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041F91BFC46A600ED2AD5 /* sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041FD1BFC46A600ED2AD5 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C0041F91BFC46A600ED2AD5 /* sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C0041FE1BFC474700ED2AD5 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; + 4C0041FF1BFC474700ED2AD5 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; + 4C0042001BFC474700ED2AD5 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; + 4C0042011BFC474800ED2AD5 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; 9069D0A30FCE1A4D0042E34C /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 9069D0A20FCE1A4D0042E34C /* sqlite3.c */; }; /* End PBXBuildFile section */ @@ -82,6 +90,7 @@ 4C0041D01BFC3D9A00ED2AD5 /* Info-tvOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-tvOS.plist"; path = "macosx/Info-tvOS.plist"; sourceTree = ""; }; 4C0041D61BFC3E2500ED2AD5 /* SQLCipher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SQLCipher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4C0041E01BFC3F0800ED2AD5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS2.0.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 4C0041F91BFC46A600ED2AD5 /* sqlite3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqlite3.h; sourceTree = ""; }; 9069D0A20FCE1A4D0042E34C /* sqlite3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqlite3.c; sourceTree = ""; }; D2AAC046055464E500DB518D /* libsqlcipher.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsqlcipher.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -144,6 +153,7 @@ isa = PBXGroup; children = ( 9069D0A20FCE1A4D0042E34C /* sqlite3.c */, + 4C0041F91BFC46A600ED2AD5 /* sqlite3.h */, ); name = Source; sourceTree = ""; @@ -188,6 +198,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4C0041FA1BFC46A600ED2AD5 /* sqlite3.h in Headers */, 4C0041AB1BFC3A7E00ED2AD5 /* SQLCipher.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -196,6 +207,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4C0041FB1BFC46A600ED2AD5 /* sqlite3.h in Headers */, 4C0041BD1BFC3C8300ED2AD5 /* SQLCipher.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -204,6 +216,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4C0041FC1BFC46A600ED2AD5 /* sqlite3.h in Headers */, 4C0041CF1BFC3D4000ED2AD5 /* SQLCipher.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -212,6 +225,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 4C0041FD1BFC46A600ED2AD5 /* sqlite3.h in Headers */, 4C0041E21BFC3F5A00ED2AD5 /* SQLCipher.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -419,6 +433,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4C0041FE1BFC474700ED2AD5 /* sqlite3.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -426,6 +441,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4C0041FF1BFC474700ED2AD5 /* sqlite3.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -433,6 +449,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4C0042001BFC474700ED2AD5 /* sqlite3.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -440,6 +457,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4C0042011BFC474800ED2AD5 /* sqlite3.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -638,10 +656,17 @@ "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = macosx/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -653,6 +678,12 @@ "-DSQLITE_TEMP_STORE=2", "-DSQLITE_THREADSAFE", "-DSQLCIPHER_CRYPTO_CC", + "-Wno-ambiguous-macro", + "-Wno-#warnings", + "-Wno-conversion", + "-Wno-unused-const-variable", + "-Wno-unused-function", + "-Wno-unreachable-code", ); PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; PRODUCT_NAME = SQLCipher; @@ -703,10 +734,17 @@ GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = macosx/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -718,6 +756,12 @@ "-DSQLITE_TEMP_STORE=2", "-DSQLITE_THREADSAFE", "-DSQLCIPHER_CRYPTO_CC", + "-Wno-ambiguous-macro", + "-Wno-#warnings", + "-Wno-conversion", + "-Wno-unused-const-variable", + "-Wno-unused-function", + "-Wno-unreachable-code", ); PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; PRODUCT_NAME = SQLCipher; @@ -788,6 +832,12 @@ "-DSQLITE_TEMP_STORE=2", "-DSQLITE_THREADSAFE", "-DSQLCIPHER_CRYPTO_CC", + "-Wno-ambiguous-macro", + "-Wno-#warnings", + "-Wno-conversion", + "-Wno-unused-const-variable", + "-Wno-unused-function", + "-Wno-unreachable-code", ); PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; PRODUCT_NAME = SQLCipher; @@ -854,6 +904,12 @@ "-DSQLITE_TEMP_STORE=2", "-DSQLITE_THREADSAFE", "-DSQLCIPHER_CRYPTO_CC", + "-Wno-ambiguous-macro", + "-Wno-#warnings", + "-Wno-conversion", + "-Wno-unused-const-variable", + "-Wno-unused-function", + "-Wno-unreachable-code", ); PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; PRODUCT_NAME = SQLCipher; @@ -920,6 +976,12 @@ "-DSQLITE_TEMP_STORE=2", "-DSQLITE_THREADSAFE", "-DSQLCIPHER_CRYPTO_CC", + "-Wno-ambiguous-macro", + "-Wno-#warnings", + "-Wno-conversion", + "-Wno-unused-const-variable", + "-Wno-unused-function", + "-Wno-unreachable-code", ); PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; PRODUCT_NAME = SQLCipher; @@ -984,6 +1046,12 @@ "-DSQLITE_TEMP_STORE=2", "-DSQLITE_THREADSAFE", "-DSQLCIPHER_CRYPTO_CC", + "-Wno-ambiguous-macro", + "-Wno-#warnings", + "-Wno-conversion", + "-Wno-unused-const-variable", + "-Wno-unused-function", + "-Wno-unreachable-code", ); PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; PRODUCT_NAME = SQLCipher; @@ -1053,6 +1121,12 @@ "-DSQLITE_TEMP_STORE=2", "-DSQLITE_THREADSAFE", "-DSQLCIPHER_CRYPTO_CC", + "-Wno-ambiguous-macro", + "-Wno-#warnings", + "-Wno-conversion", + "-Wno-unused-const-variable", + "-Wno-unused-function", + "-Wno-unreachable-code", ); PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; PRODUCT_NAME = SQLCipher; @@ -1118,6 +1192,12 @@ "-DSQLITE_TEMP_STORE=2", "-DSQLITE_THREADSAFE", "-DSQLCIPHER_CRYPTO_CC", + "-Wno-ambiguous-macro", + "-Wno-#warnings", + "-Wno-conversion", + "-Wno-unused-const-variable", + "-Wno-unused-function", + "-Wno-unreachable-code", ); PRODUCT_BUNDLE_IDENTIFIER = net.zetetic.SQLCipher; PRODUCT_NAME = SQLCipher; @@ -1188,6 +1268,7 @@ 4C00419F1BFC382500ED2AD5 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 4C0041B61BFC3B2200ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher OSX" */ = { isa = XCConfigurationList; @@ -1196,6 +1277,7 @@ 4C0041B81BFC3B2200ED2AD5 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 4C0041C81BFC3CC000ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher tvOS" */ = { isa = XCConfigurationList; @@ -1204,6 +1286,7 @@ 4C0041CA1BFC3CC000ED2AD5 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 4C0041DB1BFC3E2600ED2AD5 /* Build configuration list for PBXNativeTarget "SQLCipher watchOS" */ = { isa = XCConfigurationList; @@ -1212,6 +1295,7 @@ 4C0041DD1BFC3E2600ED2AD5 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 9069D0900FCE18970042E34C /* Build configuration list for PBXAggregateTarget "amalgamation" */ = { isa = XCConfigurationList; From f5563904625614a52da075bc7133e9d2e7095612 Mon Sep 17 00:00:00 2001 From: Steve Thomas Date: Wed, 27 Jan 2016 10:53:24 -0600 Subject: [PATCH 24/36] Added cipher_isHex() --- src/crypto.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/crypto.h b/src/crypto.h index b048b49..1148c30 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -160,6 +160,19 @@ static void cipher_bin2hex(const unsigned char* in, int sz, char *out) { } } +static int cipher_isHex(const unsigned char *hex, int sz){ + int i; + for(i = 0; i < sz; i++) { + unsigned char c = hex[i]; + if ((c < '0' || c > '9') && + (c < 'A' || c > 'F') && + (c < 'a' || c > 'f')) { + return 0; + } + } + return 1; +} + /* extensions defined in crypto_impl.c */ typedef struct codec_ctx codec_ctx; From a5d41bf0ade6f69b2fbfb9e79451101e4c236bac Mon Sep 17 00:00:00 2001 From: Steve Thomas Date: Wed, 27 Jan 2016 10:59:39 -0600 Subject: [PATCH 25/36] Validate Hex --- src/crypto_impl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto_impl.c b/src/crypto_impl.c index 12fefb8..1e559ee 100644 --- a/src/crypto_impl.c +++ b/src/crypto_impl.c @@ -885,12 +885,12 @@ static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) { if(ctx->read_ctx->provider->random(ctx->read_ctx->provider_ctx, ctx->kdf_salt, FILE_HEADER_SZ) != SQLITE_OK) return SQLITE_ERROR; ctx->need_kdf_salt = 0; } - if (c_ctx->pass_sz == ((c_ctx->key_sz * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0) { + if (c_ctx->pass_sz == ((c_ctx->key_sz * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, c_ctx->key_sz * 2)) { int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */ const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */ CODEC_TRACE(("cipher_ctx_key_derive: using raw key from hex\n")); cipher_hex2bin(z, n, c_ctx->key); - } else if (c_ctx->pass_sz == (((c_ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0) { + } else if (c_ctx->pass_sz == (((c_ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3) && sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, (c_ctx->key_sz + ctx->kdf_salt_sz) * 2)) { const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */ CODEC_TRACE(("cipher_ctx_key_derive: using raw key from hex\n")); cipher_hex2bin(z, (c_ctx->key_sz * 2), c_ctx->key); From 376eb11e20ea276d46d430b17e809f50d2939468 Mon Sep 17 00:00:00 2001 From: Nick Parker Date: Mon, 22 Feb 2016 10:40:43 -0600 Subject: [PATCH 26/36] Snapshot of upstream SQLite 3.11.0 --- Makefile.arm-wince-mingw32ce-gcc | 138 - Makefile.in | 232 +- Makefile.linux-gcc | 5 - Makefile.msc | 797 +- Makefile.vxworks | 673 - README.md | 19 +- VERSION | 2 +- addopcodes.awk | 34 - autoconf/Makefile.am | 10 +- autoconf/Makefile.msc | 921 ++ autoconf/README | 32 - autoconf/README.txt | 113 + autoconf/config.guess | 1530 -- autoconf/config.sub | 1773 --- autoconf/configure.ac | 67 +- autoconf/depcomp | 708 - autoconf/install-sh | 527 - autoconf/ltmain.sh | 9655 ------------- autoconf/missing | 331 - autoconf/tea/Makefile.in | 2 +- autoconf/tea/win/nmakehlp.c | 6 +- configure | 420 +- configure.ac | 73 +- ext/async/sqlite3async.c | 16 +- ext/fts1/fts1.c | 6 +- ext/fts1/simple_tokenizer.c | 2 +- ext/fts3/fts3.c | 99 +- ext/fts3/fts3Int.h | 19 +- ext/fts3/fts3_expr.c | 226 +- ext/fts3/fts3_icu.c | 13 +- ext/fts3/fts3_snippet.c | 314 +- ext/fts3/fts3_tokenizer.c | 15 +- ext/fts3/fts3_write.c | 36 +- ext/fts3/tool/fts3view.c | 2 +- ext/fts3/unicode/mkunicode.tcl | 223 +- ext/fts3/unicode/parseunicode.tcl | 146 + ext/fts5/extract_api_docs.tcl | 252 + ext/fts5/fts5.h | 578 + ext/fts5/fts5Int.h | 776 + ext/fts5/fts5_aux.c | 562 + ext/fts5/fts5_buffer.c | 392 + ext/fts5/fts5_config.c | 945 ++ ext/fts5/fts5_expr.c | 2560 ++++ ext/fts5/fts5_hash.c | 527 + ext/fts5/fts5_index.c | 6281 ++++++++ ext/fts5/fts5_main.c | 2710 ++++ ext/fts5/fts5_storage.c | 1125 ++ ext/fts5/fts5_tcl.c | 1150 ++ ext/fts5/fts5_test_mi.c | 424 + ext/fts5/fts5_test_tok.c | 482 + ext/fts5/fts5_tokenize.c | 1242 ++ ext/fts5/fts5_unicode2.c | 360 + ext/fts5/fts5_varint.c | 345 + ext/fts5/fts5_vocab.c | 641 + ext/fts5/fts5parse.y | 184 + ext/fts5/mkportersteps.tcl | 222 + ext/fts5/test/fts5_common.tcl | 642 + ext/fts5/test/fts5aa.test | 562 + ext/fts5/test/fts5ab.test | 297 + ext/fts5/test/fts5ac.test | 279 + ext/fts5/test/fts5ad.test | 245 + ext/fts5/test/fts5ae.test | 312 + ext/fts5/test/fts5af.test | 148 + ext/fts5/test/fts5ag.test | 145 + ext/fts5/test/fts5ah.test | 170 + ext/fts5/test/fts5ai.test | 58 + ext/fts5/test/fts5aj.test | 69 + ext/fts5/test/fts5ak.test | 150 + ext/fts5/test/fts5al.test | 300 + ext/fts5/test/fts5alter.test | 103 + ext/fts5/test/fts5auto.test | 345 + ext/fts5/test/fts5aux.test | 250 + ext/fts5/test/fts5auxdata.test | 115 + ext/fts5/test/fts5bigpl.test | 64 + ext/fts5/test/fts5bigtok.test | 67 + ext/fts5/test/fts5columnsize.test | 151 + ext/fts5/test/fts5config.test | 251 + ext/fts5/test/fts5conflict.test | 70 + ext/fts5/test/fts5content.test | 258 + ext/fts5/test/fts5corrupt.test | 99 + ext/fts5/test/fts5corrupt2.test | 272 + ext/fts5/test/fts5corrupt3.test | 408 + ext/fts5/test/fts5detail.test | 244 + ext/fts5/test/fts5dlidx.test | 200 + ext/fts5/test/fts5doclist.test | 47 + ext/fts5/test/fts5ea.test | 99 + ext/fts5/test/fts5eb.test | 69 + ext/fts5/test/fts5fault1.test | 354 + ext/fts5/test/fts5fault2.test | 140 + ext/fts5/test/fts5fault3.test | 113 + ext/fts5/test/fts5fault4.test | 398 + ext/fts5/test/fts5fault5.test | 133 + ext/fts5/test/fts5fault6.test | 295 + ext/fts5/test/fts5fault7.test | 119 + ext/fts5/test/fts5fault8.test | 60 + ext/fts5/test/fts5fault9.test | 156 + ext/fts5/test/fts5faultA.test | 64 + ext/fts5/test/fts5full.test | 43 + ext/fts5/test/fts5hash.test | 133 + ext/fts5/test/fts5integrity.test | 213 + ext/fts5/test/fts5matchinfo.test | 471 + ext/fts5/test/fts5merge.test | 194 + ext/fts5/test/fts5merge2.test | 59 + ext/fts5/test/fts5near.test | 71 + ext/fts5/test/fts5onepass.test | 181 + ext/fts5/test/fts5optimize.test | 66 + ext/fts5/test/fts5phrase.test | 119 + ext/fts5/test/fts5plan.test | 67 + ext/fts5/test/fts5porter.test | 11806 ++++++++++++++++ ext/fts5/test/fts5porter2.test | 70 + ext/fts5/test/fts5prefix.test | 345 + ext/fts5/test/fts5query.test | 83 + ext/fts5/test/fts5rank.test | 100 + ext/fts5/test/fts5rebuild.test | 67 + ext/fts5/test/fts5restart.test | 152 + ext/fts5/test/fts5rowid.test | 219 + ext/fts5/test/fts5simple.test | 413 + ext/fts5/test/fts5simple2.test | 338 + ext/fts5/test/fts5simple3.test | 85 + ext/fts5/test/fts5synonym.test | 424 + ext/fts5/test/fts5synonym2.test | 164 + ext/fts5/test/fts5tok1.test | 115 + ext/fts5/test/fts5tok2.test | 47 + ext/fts5/test/fts5tokenizer.test | 266 + ext/fts5/test/fts5unicode.test | 62 + ext/fts5/test/fts5unicode2.test | 589 + ext/fts5/test/fts5unicode3.test | 129 + ext/fts5/test/fts5unindexed.test | 79 + ext/fts5/test/fts5update.test | 121 + ext/fts5/test/fts5version.test | 64 + ext/fts5/test/fts5vocab.test | 449 + ext/fts5/tool/fts5speed.tcl | 64 + ext/fts5/tool/fts5txt2db.tcl | 228 + ext/fts5/tool/loadfts5.tcl | 172 + ext/fts5/tool/mkfts5c.tcl | 113 + ext/fts5/tool/showfts5.tcl | 97 + ext/icu/icu.c | 2 +- ext/misc/amatch.c | 4 +- ext/misc/closure.c | 4 +- ext/misc/ieee754.c | 6 +- ext/misc/json1.c | 2192 +++ ext/misc/series.c | 405 + ext/misc/spellfix.c | 205 +- ext/rbu/rbu.c | 124 + ext/rbu/rbu1.test | 680 + ext/rbu/rbu10.test | 188 + ext/rbu/rbu11.test | 198 + ext/rbu/rbu12.test | 235 + ext/rbu/rbu13.test | 65 + ext/rbu/rbu14.test | 95 + ext/rbu/rbu3.test | 207 + ext/rbu/rbu5.test | 331 + ext/rbu/rbu6.test | 103 + ext/rbu/rbu7.test | 110 + ext/rbu/rbu8.test | 75 + ext/rbu/rbu9.test | 128 + ext/rbu/rbuA.test | 84 + ext/rbu/rbuB.test | 62 + ext/rbu/rbu_common.tcl | 38 + ext/rbu/rbucrash.test | 149 + ext/rbu/rbudiff.test | 150 + ext/rbu/rbufault.test | 237 + ext/rbu/rbufault2.test | 58 + ext/rbu/rbufts.test | 134 + ext/rbu/rbusave.test | 105 + ext/rbu/sqlite3rbu.c | 4060 ++++++ ext/rbu/sqlite3rbu.h | 461 + ext/rbu/test_rbu.c | 279 + ext/rtree/rtree.c | 48 +- ext/rtree/rtree1.test | 55 + ext/rtree/rtreeC.test | 83 + ext/rtree/rtreeE.test | 15 +- ext/rtree/sqlite3rtree.h | 2 + main.mk | 251 +- manifest | 851 +- manifest.uuid | 2 +- mkopcodec.awk | 50 - mkopcodeh.awk | 230 - mptest/mptest.c | 79 +- src/alter.c | 48 +- src/analyze.c | 53 +- src/attach.c | 21 +- src/backup.c | 28 +- src/bitvec.c | 12 +- src/btmutex.c | 42 +- src/btree.c | 2063 +-- src/btree.h | 82 +- src/btreeInt.h | 41 +- src/build.c | 631 +- src/callback.c | 14 +- src/complete.c | 2 +- src/ctime.c | 12 + src/date.c | 111 +- src/dbstat.c | 121 +- src/delete.c | 167 +- src/expr.c | 542 +- src/fkey.c | 39 +- src/func.c | 107 +- src/global.c | 7 +- src/insert.c | 357 +- src/legacy.c | 2 +- src/lempar.c | 864 -- src/loadext.c | 14 +- src/main.c | 242 +- src/malloc.c | 318 +- src/mem1.c | 5 +- src/mem3.c | 2 +- src/mem5.c | 54 +- src/mutex.c | 23 +- src/mutex_noop.c | 2 +- src/mutex_unix.c | 23 +- src/mutex_w32.c | 24 + src/os.c | 54 +- src/os_common.h | 28 +- src/os_unix.c | 588 +- src/os_win.c | 61 +- src/pager.c | 570 +- src/pager.h | 32 +- src/parse.y | 209 +- src/pcache.c | 139 +- src/pcache.h | 23 +- src/pcache1.c | 506 +- src/pragma.c | 592 +- src/pragma.h | 87 +- src/prepare.c | 91 +- src/printf.c | 177 +- src/resolve.c | 189 +- src/rowset.c | 2 +- src/select.c | 933 +- src/shell.c | 1009 +- src/sqlite.h.in | 407 +- src/sqlite3.rc | 2 + src/sqlite3ext.h | 31 +- src/sqliteInt.h | 431 +- src/status.c | 40 +- src/tclsqlite.c | 72 +- src/test1.c | 266 +- src/test2.c | 2 +- src/test3.c | 53 +- src/test8.c | 61 +- src/test_config.c | 54 + src/test_fs.c | 589 +- src/test_func.c | 35 +- src/test_loadext.c | 2 +- src/test_malloc.c | 26 +- src/test_multiplex.c | 17 +- src/test_mutex.c | 97 +- src/test_rtree.c | 48 +- src/test_sqllog.c | 81 +- src/test_tclvar.c | 194 +- src/test_windirent.c | 157 + src/test_windirent.h | 105 + src/threads.c | 13 +- src/tokenize.c | 236 +- src/treeview.c | 486 + src/trigger.c | 36 +- src/update.c | 228 +- src/utf.c | 6 +- src/util.c | 53 +- src/vdbe.c | 1116 +- src/vdbe.h | 23 +- src/vdbeInt.h | 121 +- src/vdbeapi.c | 153 +- src/vdbeaux.c | 945 +- src/vdbeblob.c | 116 +- src/vdbemem.c | 100 +- src/vdbesort.c | 49 +- src/vdbetrace.c | 14 +- src/vtab.c | 108 +- src/vxworks.h | 3 + src/wal.c | 438 +- src/wal.h | 9 + src/walker.c | 11 +- src/where.c | 3324 +---- src/whereInt.h | 101 +- src/wherecode.c | 1722 +++ src/whereexpr.c | 1359 ++ test/affinity2.test | 61 + test/alter3.test | 12 +- test/analyze3.test | 20 +- test/analyze9.test | 3 - test/analyzeB.test | 1 - test/analyzeD.test | 1 - test/analyzeF.test | 5 +- test/analyzer1.test | 52 + test/atof1.test | 2 +- test/autoindex5.test | 129 + test/bc_common.tcl | 4 +- test/cacheflush.test | 323 + test/capi3c.test | 23 + test/capi3d.test | 4 +- test/cffault.test | 158 + test/check.test | 20 + test/collate4.test | 8 +- test/conflict2.test | 8 +- test/corrupt2.test | 49 +- test/corrupt7.test | 49 +- test/corruptC.test | 5 + test/corruptE.test | 46 +- test/corruptH.test | 1 - test/corruptI.test | 154 + test/cost.test | 3 - test/cursorhint.test | 162 + test/date.test | 9 + test/delete.test | 1 - test/delete4.test | 145 + test/distinct.test | 17 + test/e_blobbytes.test | 2 - test/e_blobclose.test | 1 - test/e_blobopen.test | 1 - test/e_blobwrite.test | 1 - test/e_createtable.test | 15 +- test/e_delete.test | 13 +- test/e_expr.test | 8 +- test/e_insert.test | 16 +- test/e_reindex.test | 7 +- test/e_resolve.test | 12 +- test/e_update.test | 16 +- test/e_uri.test | 2 + test/e_walauto.test | 1 - test/e_walckpt.test | 1 - test/enc3.test | 5 +- test/extraquick.test | 16 + test/filectrl.test | 1 - test/fkey1.test | 34 + test/fkey5.test | 4 +- test/fkey8.test | 1 - test/fordelete.test | 209 + test/fts3atoken.test | 110 +- test/fts3conf.test | 43 +- test/fts3d.test | 2 +- test/fts3defer2.test | 6 + test/fts3expr3.test | 32 + test/fts3expr4.test | 1 - test/fts3fault.test | 8 +- test/fts3join.test | 2 - test/fts3matchinfo.test | 39 +- test/fts3offsets.test | 123 + test/fts3query.test | 4 +- test/fts3snippet.test | 1 - test/fts4check.test | 1 - test/fts4content.test | 5 +- test/fts4growth.test | 1 - test/fts4growth2.test | 1 - test/fts4incr.test | 4 +- test/fts4langid.test | 46 +- test/fts4noti.test | 3 - test/fts4onepass.test | 146 + test/fts4unicode.test | 14 +- test/fuzz3.test | 3 + test/fuzzcheck.c | 1188 ++ test/fuzzdata1.db | Bin 0 -> 4398080 bytes test/fuzzdata1.txt | Bin 2966109 -> 0 bytes test/{fuzzdata2.txt => fuzzdata2.db} | Bin 15739506 -> 17021952 bytes test/fuzzdata3.db | Bin 0 -> 11848704 bytes test/fuzzdata4.db | Bin 0 -> 2021376 bytes test/fuzzer1.test | 46 - test/fuzzer2.test | 72 + test/hexlit.test | 3 + test/hidden.test | 153 + test/ieee754.test | 60 + test/in.test | 20 +- test/incrcorrupt.test | 1 - test/index.test | 6 +- test/index2.test | 3 +- test/index3.test | 49 +- test/index5.test | 6 +- test/index6.test | 49 + test/indexedby.test | 6 +- test/indexexpr1.test | 327 + test/join.test | 26 + test/join5.test | 23 + test/json101.test | 360 + test/json102.test | 301 + test/json103.test | 78 + test/like.test | 53 +- test/like3.test | 7 +- test/lookaside.test | 4 +- test/malloc5.test | 37 +- test/mallocK.test | 1 - test/mallocL.test | 1 - test/malloc_common.tcl | 16 +- test/memdb.test | 7 +- test/memsubsys1.test | 9 +- test/memsubsys2.test | 7 +- test/misc1.test | 26 + test/misc4.test | 21 + test/mkfuzzdata1.tcl | 113 - test/mmap1.test | 65 +- test/mmap4.test | 104 + test/mutex1.test | 39 +- test/numindex1.test | 79 + test/offset1.test | 161 + test/orderby1.test | 17 + test/orderby9.test | 62 + test/oserror.test | 4 +- test/ovfl.test | 2 - test/parser1.test | 79 + test/pcache.test | 2 +- test/pcache2.test | 9 +- test/permutations.test | 67 +- test/pragma.test | 47 +- test/pragma2.test | 83 +- test/progress.test | 1 - test/quota.test | 1 + test/rbu.test | 17 + test/releasetest.tcl | 496 +- test/rollback2.test | 1 - test/rollbackfault.test | 2 - test/rowallock.test | 67 + test/rowid.test | 3 + test/{savepoint3.test => savepointfault.test} | 13 +- test/select4.test | 26 + test/select7.test | 18 + test/select8.test | 1 - test/shared3.test | 1 - test/shared4.test | 1 - test/shrink.test | 2 + test/skipscan1.test | 30 + test/snapshot.test | 339 + test/snapshot_fault.test | 164 + test/sort.test | 46 - test/sort2.test | 28 +- test/sort3.test | 52 +- test/sort5.test | 1 - test/speedtest1.c | 76 +- test/spellfix.test | 116 + test/spellfix2.test | 118 + test/spellfix3.test | 43 + test/sqldiff1.test | 65 + test/sqllimits1.test | 17 +- test/sqllog.test | 113 + test/stat.test | 67 + test/subtype1.test | 31 + test/symlink.test | 191 + test/sync.test | 11 +- test/syscall.test | 4 +- test/sysfault.test | 1 + test/tabfunc01.test | 123 + test/table.test | 28 + test/tester.tcl | 281 +- test/threadtest2.c | 2 +- test/threadtest3.c | 70 +- test/tkt-9f2eb3abac.test | 1 - test/tkt-ba7cbfaedc.test | 2 - test/tkt3871.test | 10 +- test/trace.test | 8 + test/transitive1.test | 74 +- test/trigger7.test | 1 - test/triggerE.test | 2 - test/unique2.test | 8 + test/uri.test | 8 + test/view.test | 35 +- test/vtab1.test | 102 +- test/vtab2.test | 9 +- test/vtab4.test | 32 +- test/vtab6.test | 5 + test/vtabE.test | 2 + test/vtabH.test | 202 + test/vtabI.test | 126 + test/vtab_shared.test | 1 - test/wal.test | 104 +- test/wal3.test | 147 +- test/wal6.test | 43 +- test/walcksum.test | 54 - test/walcrash.test | 3 +- test/waloverwrite.test | 162 + test/walprotocol.test | 177 + test/walslow.test | 158 + test/where.test | 50 +- test/where2.test | 9 +- test/where4.test | 40 +- test/where7.test | 12 + test/where8.test | 22 +- test/whereC.test | 1 + test/whereD.test | 67 +- test/whereG.test | 37 + test/whereI.test | 1 - test/{where8m.test => wherefault.test} | 12 +- test/with1.test | 142 + test/with2.test | 4 +- test/with3.test | 64 + test/withM.test | 3 - test/without_rowid1.test | 51 + test/without_rowid3.test | 16 + test/without_rowid5.test | 6 +- test/without_rowid6.test | 4 + test/wordcount.c | 5 +- test/zeroblob.test | 54 +- tool/GetFile.cs | 450 + tool/GetTclKit.bat | 273 + tool/addopcodes.tcl | 63 + tool/build-all-msvc.bat | 84 +- tool/cg_anno.tcl | 24 + tool/diffdb.c | 44 - tool/fuzzershell.c | 35 +- tool/lemon.c | 381 +- tool/lempar.c | 410 +- tool/loadfts.c | 242 + tool/mkautoconfamal.sh | 69 +- tool/mkkeywordhash.c | 63 +- tool/mkmsvcmin.tcl | 98 + tool/mkopcodec.tcl | 50 + tool/mkopcodeh.tcl | 234 + tool/mkpragmatab.tcl | 8 +- tool/mksqlite3c-noext.tcl | 4 + tool/mksqlite3c.tcl | 18 +- tool/mksqlite3h.tcl | 3 +- tool/mkvsix.tcl | 15 +- tool/opcodeDoc.awk | 23 - tool/replace.tcl | 20 + tool/run-speed-test.sh | 68 + tool/showdb.c | 350 +- tool/showjournal.c | 6 +- tool/showstat4.c | 4 +- tool/showwal.c | 7 +- tool/space_used.tcl | 111 - tool/spaceanal.tcl | 59 +- tool/speedtest16.c | 4 +- tool/speedtest8inst1.c | 4 +- tool/sqldiff.c | 693 +- tool/srcck1.c | 158 + tool/tostr.awk | 8 - tool/tostr.tcl | 12 + tool/vdbe_profile.tcl | 8 + tool/warnings.sh | 28 +- 526 files changed, 91752 insertions(+), 28942 deletions(-) delete mode 100644 Makefile.arm-wince-mingw32ce-gcc delete mode 100644 Makefile.vxworks delete mode 100644 addopcodes.awk create mode 100644 autoconf/Makefile.msc delete mode 100644 autoconf/README create mode 100644 autoconf/README.txt delete mode 100755 autoconf/config.guess delete mode 100755 autoconf/config.sub delete mode 100755 autoconf/depcomp delete mode 100755 autoconf/install-sh delete mode 100644 autoconf/ltmain.sh delete mode 100755 autoconf/missing create mode 100644 ext/fts3/unicode/parseunicode.tcl create mode 100644 ext/fts5/extract_api_docs.tcl create mode 100644 ext/fts5/fts5.h create mode 100644 ext/fts5/fts5Int.h create mode 100644 ext/fts5/fts5_aux.c create mode 100644 ext/fts5/fts5_buffer.c create mode 100644 ext/fts5/fts5_config.c create mode 100644 ext/fts5/fts5_expr.c create mode 100644 ext/fts5/fts5_hash.c create mode 100644 ext/fts5/fts5_index.c create mode 100644 ext/fts5/fts5_main.c create mode 100644 ext/fts5/fts5_storage.c create mode 100644 ext/fts5/fts5_tcl.c create mode 100644 ext/fts5/fts5_test_mi.c create mode 100644 ext/fts5/fts5_test_tok.c create mode 100644 ext/fts5/fts5_tokenize.c create mode 100644 ext/fts5/fts5_unicode2.c create mode 100644 ext/fts5/fts5_varint.c create mode 100644 ext/fts5/fts5_vocab.c create mode 100644 ext/fts5/fts5parse.y create mode 100644 ext/fts5/mkportersteps.tcl create mode 100644 ext/fts5/test/fts5_common.tcl create mode 100644 ext/fts5/test/fts5aa.test create mode 100644 ext/fts5/test/fts5ab.test create mode 100644 ext/fts5/test/fts5ac.test create mode 100644 ext/fts5/test/fts5ad.test create mode 100644 ext/fts5/test/fts5ae.test create mode 100644 ext/fts5/test/fts5af.test create mode 100644 ext/fts5/test/fts5ag.test create mode 100644 ext/fts5/test/fts5ah.test create mode 100644 ext/fts5/test/fts5ai.test create mode 100644 ext/fts5/test/fts5aj.test create mode 100644 ext/fts5/test/fts5ak.test create mode 100644 ext/fts5/test/fts5al.test create mode 100644 ext/fts5/test/fts5alter.test create mode 100644 ext/fts5/test/fts5auto.test create mode 100644 ext/fts5/test/fts5aux.test create mode 100644 ext/fts5/test/fts5auxdata.test create mode 100644 ext/fts5/test/fts5bigpl.test create mode 100644 ext/fts5/test/fts5bigtok.test create mode 100644 ext/fts5/test/fts5columnsize.test create mode 100644 ext/fts5/test/fts5config.test create mode 100644 ext/fts5/test/fts5conflict.test create mode 100644 ext/fts5/test/fts5content.test create mode 100644 ext/fts5/test/fts5corrupt.test create mode 100644 ext/fts5/test/fts5corrupt2.test create mode 100644 ext/fts5/test/fts5corrupt3.test create mode 100644 ext/fts5/test/fts5detail.test create mode 100644 ext/fts5/test/fts5dlidx.test create mode 100644 ext/fts5/test/fts5doclist.test create mode 100644 ext/fts5/test/fts5ea.test create mode 100644 ext/fts5/test/fts5eb.test create mode 100644 ext/fts5/test/fts5fault1.test create mode 100644 ext/fts5/test/fts5fault2.test create mode 100644 ext/fts5/test/fts5fault3.test create mode 100644 ext/fts5/test/fts5fault4.test create mode 100644 ext/fts5/test/fts5fault5.test create mode 100644 ext/fts5/test/fts5fault6.test create mode 100644 ext/fts5/test/fts5fault7.test create mode 100644 ext/fts5/test/fts5fault8.test create mode 100644 ext/fts5/test/fts5fault9.test create mode 100644 ext/fts5/test/fts5faultA.test create mode 100644 ext/fts5/test/fts5full.test create mode 100644 ext/fts5/test/fts5hash.test create mode 100644 ext/fts5/test/fts5integrity.test create mode 100644 ext/fts5/test/fts5matchinfo.test create mode 100644 ext/fts5/test/fts5merge.test create mode 100644 ext/fts5/test/fts5merge2.test create mode 100644 ext/fts5/test/fts5near.test create mode 100644 ext/fts5/test/fts5onepass.test create mode 100644 ext/fts5/test/fts5optimize.test create mode 100644 ext/fts5/test/fts5phrase.test create mode 100644 ext/fts5/test/fts5plan.test create mode 100644 ext/fts5/test/fts5porter.test create mode 100644 ext/fts5/test/fts5porter2.test create mode 100644 ext/fts5/test/fts5prefix.test create mode 100644 ext/fts5/test/fts5query.test create mode 100644 ext/fts5/test/fts5rank.test create mode 100644 ext/fts5/test/fts5rebuild.test create mode 100644 ext/fts5/test/fts5restart.test create mode 100644 ext/fts5/test/fts5rowid.test create mode 100644 ext/fts5/test/fts5simple.test create mode 100644 ext/fts5/test/fts5simple2.test create mode 100644 ext/fts5/test/fts5simple3.test create mode 100644 ext/fts5/test/fts5synonym.test create mode 100644 ext/fts5/test/fts5synonym2.test create mode 100644 ext/fts5/test/fts5tok1.test create mode 100644 ext/fts5/test/fts5tok2.test create mode 100644 ext/fts5/test/fts5tokenizer.test create mode 100644 ext/fts5/test/fts5unicode.test create mode 100644 ext/fts5/test/fts5unicode2.test create mode 100644 ext/fts5/test/fts5unicode3.test create mode 100644 ext/fts5/test/fts5unindexed.test create mode 100644 ext/fts5/test/fts5update.test create mode 100644 ext/fts5/test/fts5version.test create mode 100644 ext/fts5/test/fts5vocab.test create mode 100644 ext/fts5/tool/fts5speed.tcl create mode 100644 ext/fts5/tool/fts5txt2db.tcl create mode 100644 ext/fts5/tool/loadfts5.tcl create mode 100644 ext/fts5/tool/mkfts5c.tcl create mode 100644 ext/fts5/tool/showfts5.tcl create mode 100644 ext/misc/json1.c create mode 100644 ext/misc/series.c create mode 100644 ext/rbu/rbu.c create mode 100644 ext/rbu/rbu1.test create mode 100644 ext/rbu/rbu10.test create mode 100644 ext/rbu/rbu11.test create mode 100644 ext/rbu/rbu12.test create mode 100644 ext/rbu/rbu13.test create mode 100644 ext/rbu/rbu14.test create mode 100644 ext/rbu/rbu3.test create mode 100644 ext/rbu/rbu5.test create mode 100644 ext/rbu/rbu6.test create mode 100644 ext/rbu/rbu7.test create mode 100644 ext/rbu/rbu8.test create mode 100644 ext/rbu/rbu9.test create mode 100644 ext/rbu/rbuA.test create mode 100644 ext/rbu/rbuB.test create mode 100644 ext/rbu/rbu_common.tcl create mode 100644 ext/rbu/rbucrash.test create mode 100644 ext/rbu/rbudiff.test create mode 100644 ext/rbu/rbufault.test create mode 100644 ext/rbu/rbufault2.test create mode 100644 ext/rbu/rbufts.test create mode 100644 ext/rbu/rbusave.test create mode 100644 ext/rbu/sqlite3rbu.c create mode 100644 ext/rbu/sqlite3rbu.h create mode 100644 ext/rbu/test_rbu.c delete mode 100644 mkopcodec.awk delete mode 100644 mkopcodeh.awk delete mode 100644 src/lempar.c create mode 100644 src/test_windirent.c create mode 100644 src/test_windirent.h create mode 100644 src/treeview.c create mode 100644 src/wherecode.c create mode 100644 src/whereexpr.c create mode 100644 test/affinity2.test create mode 100644 test/analyzer1.test create mode 100644 test/autoindex5.test create mode 100644 test/cacheflush.test create mode 100644 test/cffault.test create mode 100644 test/cursorhint.test create mode 100644 test/delete4.test create mode 100644 test/extraquick.test create mode 100644 test/fordelete.test create mode 100644 test/fts3offsets.test create mode 100644 test/fts4onepass.test create mode 100644 test/fuzzcheck.c create mode 100644 test/fuzzdata1.db delete mode 100644 test/fuzzdata1.txt rename test/{fuzzdata2.txt => fuzzdata2.db} (75%) create mode 100644 test/fuzzdata3.db create mode 100644 test/fuzzdata4.db create mode 100644 test/fuzzer2.test create mode 100644 test/hidden.test create mode 100644 test/ieee754.test create mode 100644 test/indexexpr1.test create mode 100644 test/json101.test create mode 100644 test/json102.test create mode 100644 test/json103.test delete mode 100644 test/mkfuzzdata1.tcl create mode 100644 test/mmap4.test create mode 100644 test/numindex1.test create mode 100644 test/offset1.test create mode 100644 test/orderby9.test create mode 100644 test/parser1.test create mode 100644 test/rbu.test create mode 100644 test/rowallock.test rename test/{savepoint3.test => savepointfault.test} (94%) create mode 100644 test/snapshot.test create mode 100644 test/snapshot_fault.test create mode 100644 test/spellfix2.test create mode 100644 test/spellfix3.test create mode 100644 test/sqldiff1.test create mode 100644 test/sqllog.test create mode 100644 test/subtype1.test create mode 100644 test/symlink.test create mode 100644 test/tabfunc01.test create mode 100644 test/vtabH.test create mode 100644 test/vtabI.test create mode 100644 test/waloverwrite.test create mode 100644 test/walprotocol.test rename test/{where8m.test => wherefault.test} (84%) create mode 100644 test/with3.test create mode 100644 tool/GetFile.cs create mode 100644 tool/GetTclKit.bat create mode 100644 tool/addopcodes.tcl create mode 100755 tool/cg_anno.tcl delete mode 100644 tool/diffdb.c create mode 100644 tool/loadfts.c create mode 100644 tool/mkmsvcmin.tcl create mode 100644 tool/mkopcodec.tcl create mode 100644 tool/mkopcodeh.tcl delete mode 100644 tool/opcodeDoc.awk create mode 100644 tool/replace.tcl create mode 100644 tool/run-speed-test.sh delete mode 100644 tool/space_used.tcl create mode 100644 tool/srcck1.c delete mode 100644 tool/tostr.awk create mode 100644 tool/tostr.tcl diff --git a/Makefile.arm-wince-mingw32ce-gcc b/Makefile.arm-wince-mingw32ce-gcc deleted file mode 100644 index 323b7ea..0000000 --- a/Makefile.arm-wince-mingw32ce-gcc +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/make -# -# Makefile for SQLITE -# -# This is a template makefile for SQLite. Most people prefer to -# use the autoconf generated "configure" script to generate the -# makefile automatically. But that does not work for everybody -# and in every situation. If you are having problems with the -# "configure" script, you might want to try this makefile as an -# alternative. Create a copy of this file, edit the parameters -# below and type "make". -# - -#### The directory where to find the mingw32ce tools -MINGW32CE = /opt/mingw32ce/bin - -#### The target prefix of the mingw32ce tools -TARGET = arm-wince-mingw32ce - -#### The toplevel directory of the source tree. This is the directory -# that contains this "Makefile.in" and the "configure.in" script. -# -TOP = ../sqlite - -#### C Compiler and options for use in building executables that -# will run on the platform that is doing the build. -# -BCC = gcc -g -O2 -#BCC = /opt/ancic/bin/c89 -0 - -#### If the target operating system supports the "usleep()" system -# call, then define the HAVE_USLEEP macro for all C modules. -# -USLEEP = -#USLEEP = -DHAVE_USLEEP=1 - -#### If you want the SQLite library to be safe for use within a -# multi-threaded program, then define the following macro -# appropriately: -# -THREADSAFE = -DTHREADSAFE=1 -#THREADSAFE = -DTHREADSAFE=0 - -#### Specify any extra linker options needed to make the library -# thread safe -# -#THREADLIB = -lpthread -THREADLIB = - -#### Specify any extra libraries needed to access required functions. -# -#TLIBS = -lrt # fdatasync on Solaris 8 -TLIBS = - -#### Leave SQLITE_DEBUG undefined for maximum speed. Use SQLITE_DEBUG=1 -# to check for memory leaks. Use SQLITE_DEBUG=2 to print a log of all -# malloc()s and free()s in order to track down memory leaks. -# -# SQLite uses some expensive assert() statements in the inner loop. -# You can make the library go almost twice as fast if you compile -# with -DNDEBUG=1 -# -#OPTS = -DSQLITE_DEBUG=2 -#OPTS = -DSQLITE_DEBUG=1 -#OPTS = -OPTS = -DNDEBUG=1 -DSQLITE_OS_WIN=1 -D_WIN32_WCE=1 -#OPTS += -DHAVE_FDATASYNC=1 - -#### The suffix to add to executable files. ".exe" for windows. -# Nothing for unix. -# -EXE = .exe -#EXE = - -#### C Compile and options for use in building executables that -# will run on the target platform. This is usually the same -# as BCC, unless you are cross-compiling. -# -#TCC = gcc -O6 -#TCC = gcc -g -O0 -Wall -#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage -#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6 -TCC = $(MINGW32CE)/$(TARGET)-gcc -O2 -#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive - -#### Tools used to build a static library. -# -#AR = ar cr -#AR = /opt/mingw/bin/i386-mingw32-ar cr -AR = $(MINGW32CE)/$(TARGET)-ar cr -#RANLIB = ranlib -#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib -RANLIB = $(MINGW32CE)/$(TARGET)-ranlib - -#MKSHLIB = gcc -shared -#SO = so -#SHPREFIX = lib -MKSHLIB = $(MINGW32CE)/$(TARGET)-gcc -shared -SO = dll -SHPREFIX = - -#### Extra compiler options needed for programs that use the TCL library. -# -#TCL_FLAGS = -#TCL_FLAGS = -DSTATIC_BUILD=1 -TCL_FLAGS = -I/home/drh/tcltk/8.5linux -#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1 -#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux - -#### Linker options needed to link against the TCL library. -# -#LIBTCL = -ltcl -lm -ldl -LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl -#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt -#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc - -#### Additional objects for SQLite library when TCL support is enabled. -TCLOBJ = -#TCLOBJ = tclsqlite.o - -#### Compiler options needed for programs that use the readline() library. -# -READLINE_FLAGS = -#READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline - -#### Linker options needed by programs using readline() must link against. -# -LIBREADLINE = -#LIBREADLINE = -static -lreadline -ltermcap - -#### Which "awk" program provides nawk compatibilty -# -# NAWK = nawk -NAWK = awk - -# You should not have to change anything below this line -############################################################################### -include $(TOP)/main.mk diff --git a/Makefile.in b/Makefile.in index 0591150..013cf44 100644 --- a/Makefile.in +++ b/Makefile.in @@ -54,6 +54,7 @@ LIBTCL = @TCL_LIB_SPEC@ # Compiler options needed for programs that use the readline() library. # READLINE_FLAGS = -DHAVE_READLINE=@TARGET_HAVE_READLINE@ @TARGET_READLINE_INC@ +READLINE_FLAGS += -DHAVE_EDITLINE=@TARGET_HAVE_EDITLINE@ # The library that programs using readline() must link against. # @@ -65,7 +66,7 @@ TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@ # Any target libraries which libsqlite must be linked against # -TLIBS = @LIBS@ +TLIBS = @LIBS@ $(LIBS) # Flags controlling use of the in memory btree implementation # @@ -155,9 +156,6 @@ LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(TCC) $(LTCOMPILE_EXTRAS) LTLINK = $(LIBTOOL) --mode=link $(TCC) $(LTCOMPILE_EXTRAS) @LDFLAGS@ $(LTLINK_EXTRAS) LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL) -# nawk compatible awk. -NAWK = @AWK@ - # You should not have to change anything below this line ############################################################################### @@ -173,18 +171,20 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \ fts3_tokenize_vtab.lo \ fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ + fts5.lo \ func.lo global.lo hash.lo \ - icu.lo insert.lo journal.lo legacy.lo loadext.lo \ + icu.lo insert.lo journal.lo json1.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ memjournal.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ - random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \ - table.lo threads.lo tokenize.lo trigger.lo \ + random.lo resolve.lo rowset.lo rtree.lo select.lo sqlite3rbu.lo status.lo \ + table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ - vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo + vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ + utf.lo vtab.lo # Object files for the amalgamation. # @@ -270,9 +270,10 @@ SRC = \ $(TOP)/src/sqliteInt.h \ $(TOP)/src/sqliteLimit.h \ $(TOP)/src/table.c \ - $(TOP)/src/threads.c \ $(TOP)/src/tclsqlite.c \ + $(TOP)/src/threads.c \ $(TOP)/src/tokenize.c \ + $(TOP)/src/treeview.c \ $(TOP)/src/trigger.c \ $(TOP)/src/utf.c \ $(TOP)/src/update.c \ @@ -293,6 +294,8 @@ SRC = \ $(TOP)/src/wal.h \ $(TOP)/src/walker.c \ $(TOP)/src/where.c \ + $(TOP)/src/wherecode.c \ + $(TOP)/src/whereexpr.c \ $(TOP)/src/whereInt.h # Source code for extensions @@ -339,6 +342,12 @@ SRC += \ SRC += \ $(TOP)/ext/rtree/rtree.h \ $(TOP)/ext/rtree/rtree.c +SRC += \ + $(TOP)/ext/rbu/sqlite3rbu.h \ + $(TOP)/ext/rbu/sqlite3rbu.c +SRC += \ + $(TOP)/ext/misc/json1.c + # Generated source code files @@ -393,9 +402,11 @@ TESTSRC = \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ + $(TOP)/src/test_windirent.c \ $(TOP)/src/test_wsd.c \ $(TOP)/ext/fts3/fts3_term.c \ - $(TOP)/ext/fts3/fts3_test.c + $(TOP)/ext/fts3/fts3_test.c \ + $(TOP)/ext/rbu/test_rbu.c # Statically linked extensions # @@ -405,10 +416,14 @@ TESTSRC += \ $(TOP)/ext/misc/eval.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ + $(TOP)/ext/fts5/fts5_tcl.c \ + $(TOP)/ext/fts5/fts5_test_mi.c \ + $(TOP)/ext/fts5/fts5_test_tok.c \ $(TOP)/ext/misc/ieee754.c \ $(TOP)/ext/misc/nextchar.c \ $(TOP)/ext/misc/percentile.c \ $(TOP)/ext/misc/regexp.c \ + $(TOP)/ext/misc/series.c \ $(TOP)/ext/misc/spellfix.c \ $(TOP)/ext/misc/totype.c \ $(TOP)/ext/misc/wholenumber.c @@ -450,6 +465,8 @@ TESTSRC2 = \ $(TOP)/src/vdbemem.c \ $(TOP)/src/vdbetrace.c \ $(TOP)/src/where.c \ + $(TOP)/src/wherecode.c \ + $(TOP)/src/whereexpr.c \ parse.c \ $(TOP)/ext/fts3/fts3.c \ $(TOP)/ext/fts3/fts3_aux.c \ @@ -510,6 +527,33 @@ EXTHDR += \ EXTHDR += \ $(TOP)/ext/rtree/sqlite3rtree.h +# executables needed for testing +# +TESTPROGS = \ + testfixture$(TEXE) \ + sqlite3$(TEXE) \ + sqlite3_analyzer$(TEXE) \ + sqldiff$(TEXE) + +# Databases containing fuzzer test cases +# +FUZZDATA = \ + $(TOP)/test/fuzzdata1.db \ + $(TOP)/test/fuzzdata2.db \ + $(TOP)/test/fuzzdata3.db \ + $(TOP)/test/fuzzdata4.db + +# Standard options to testfixture +# +TESTOPTS = --verbose=file --output=test-out.txt + +# Extra compiler options for various shell tools +# +SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 +SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS +FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 +FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 + # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. # @@ -532,16 +576,26 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la -version-info "8:6:8" \ -avoid-version -sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h - $(LTLINK) $(READLINE_FLAGS) \ - -o $@ $(TOP)/src/shell.c libsqlite3.la \ +sqlite3$(TEXE): $(TOP)/src/shell.c sqlite3.c + $(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \ + $(TOP)/src/shell.c sqlite3.c \ $(LIBREADLINE) $(TLIBS) -rpath "$(libdir)" sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h - $(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) + $(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) + +srcck1$(BEXE): $(TOP)/tool/srcck1.c + $(BCC) -o srcck1$(BEXE) $(TOP)/tool/srcck1.c + +sourcetest: srcck1$(BEXE) sqlite3.c + ./srcck1 sqlite3.c fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h - $(LTLINK) -o $@ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) + $(LTLINK) -o $@ $(FUZZERSHELL_OPT) \ + $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) + +fuzzcheck$(TEXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h + $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) mptester$(TEXE): sqlite3.c $(TOP)/mptest/mptest.c $(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \ @@ -567,19 +621,23 @@ mptest: mptester$(TEXE) # files are automatically generated. This target takes care of # all that automatic generation. # -.target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl +.target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl fts5.c rm -rf tsrc mkdir tsrc cp -f $(SRC) tsrc rm tsrc/sqlite.h.in tsrc/parse.y $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) vdbe.new mv vdbe.new tsrc/vdbe.c + cp fts5.c fts5.h tsrc touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl $(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl cp tsrc/shell.c tsrc/sqlite3ext.h . +sqlite3ext.h: .target_source + cp tsrc/sqlite3ext.h . + tclsqlite3.c: sqlite3.c echo '#ifndef USE_SYSTEM_SQLITE' >tclsqlite3.c cat sqlite3.c >>tclsqlite3.c @@ -596,9 +654,9 @@ sqlite3.lo: sqlite3.c # Rules to build the LEMON compiler generator # -lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/src/lempar.c +lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c $(BCC) -o $@ $(TOP)/tool/lemon.c - cp $(TOP)/src/lempar.c . + cp $(TOP)/tool/lempar.c . # Rules to build individual *.o files from generated *.c files. This # applies to: @@ -779,6 +837,9 @@ threads.lo: $(TOP)/src/threads.c $(HDR) tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c +treeview.lo: $(TOP)/src/treeview.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/treeview.c + trigger.lo: $(TOP)/src/trigger.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/trigger.c @@ -827,6 +888,12 @@ walker.lo: $(TOP)/src/walker.c $(HDR) where.lo: $(TOP)/src/where.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/where.c +wherecode.lo: $(TOP)/src/wherecode.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wherecode.c + +whereexpr.lo: $(TOP)/src/whereexpr.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/whereexpr.c + tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR) $(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c @@ -842,22 +909,22 @@ tclsqlite3$(TEXE): tclsqlite-shell.lo libsqlite3.la # Rules to build opcodes.c and opcodes.h # -opcodes.c: opcodes.h $(TOP)/mkopcodec.awk - $(NAWK) -f $(TOP)/mkopcodec.awk opcodes.h >opcodes.c +opcodes.c: opcodes.h $(TOP)/tool/mkopcodec.tcl + $(TCLSH_CMD) $(TOP)/tool/mkopcodec.tcl opcodes.h >opcodes.c -opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk - cat parse.h $(TOP)/src/vdbe.c | $(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h +opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/tool/mkopcodeh.tcl + cat parse.h $(TOP)/src/vdbe.c | $(TCLSH_CMD) $(TOP)/tool/mkopcodeh.tcl >opcodes.h # Rules to build parse.c and parse.h - the outputs of lemon. # parse.h: parse.c -parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk +parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl cp $(TOP)/src/parse.y . rm -f parse.h ./lemon$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y mv parse.h parse.h.temp - $(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h + $(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION $(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h @@ -933,6 +1000,45 @@ fts3_write.lo: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR) rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c +json1.lo: $(TOP)/ext/misc/json1.c + $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c + +# FTS5 things +# +FTS5_SRC = \ + $(TOP)/ext/fts5/fts5.h \ + $(TOP)/ext/fts5/fts5Int.h \ + $(TOP)/ext/fts5/fts5_aux.c \ + $(TOP)/ext/fts5/fts5_buffer.c \ + $(TOP)/ext/fts5/fts5_main.c \ + $(TOP)/ext/fts5/fts5_config.c \ + $(TOP)/ext/fts5/fts5_expr.c \ + $(TOP)/ext/fts5/fts5_hash.c \ + $(TOP)/ext/fts5/fts5_index.c \ + fts5parse.c fts5parse.h \ + $(TOP)/ext/fts5/fts5_storage.c \ + $(TOP)/ext/fts5/fts5_tokenize.c \ + $(TOP)/ext/fts5/fts5_unicode2.c \ + $(TOP)/ext/fts5/fts5_varint.c \ + $(TOP)/ext/fts5/fts5_vocab.c \ + +fts5parse.c: $(TOP)/ext/fts5/fts5parse.y lemon + cp $(TOP)/ext/fts5/fts5parse.y . + rm -f fts5parse.h + ./lemon $(OPTS) fts5parse.y + +fts5parse.h: fts5parse.c + +fts5.c: $(FTS5_SRC) + $(TCLSH_CMD) $(TOP)/ext/fts5/tool/mkfts5c.tcl + cp $(TOP)/ext/fts5/fts5.h . + +fts5.lo: fts5.c $(HDR) $(EXTHDR) + $(LTCOMPILE) -DSQLITE_CORE -c fts5.c + +sqlite3rbu.lo: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR) + $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rbu/sqlite3rbu.c + # Rules to build the 'testfixture' application. # @@ -955,51 +1061,58 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC) -o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS) # A very detailed test running most or all test cases -fulltest: testfixture$(TEXE) sqlite3$(TEXE) fuzztest - ./testfixture$(TEXE) $(TOP)/test/all.test +fulltest: $(TESTPROGS) fuzztest + ./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS) # Really really long testing -soaktest: testfixture$(TEXE) sqlite3$(TEXE) fuzzoomtest - ./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 +soaktest: $(TESTPROGS) + ./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS) -# Do extra testing but not aeverything. -fulltestonly: testfixture$(TEXE) sqlite3$(TEXE) +# Do extra testing but not everything. +fulltestonly: $(TESTPROGS) fuzztest ./testfixture$(TEXE) $(TOP)/test/full.test # Fuzz testing -fuzztest: fuzzershell$(TEXE) - ./fuzzershell$(TEXE) $(TOP)/test/fuzzdata1.txt $(TOP)/test/fuzzdata2.txt +fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) + ./fuzzcheck$(TEXE) $(FUZZDATA) -fuzzoomtest: fuzzershell$(TEXE) - ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt --oom +fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) + ./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA) -# This is the common case. Run many tests but not those that take -# a really long time. +valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) + valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA) + +# Minimal testing that runs in less than 3 minutes # -test: testfixture$(TEXE) sqlite3$(TEXE) fuzztest - ./testfixture$(TEXE) $(TOP)/test/veryquick.test +quicktest: ./testfixture$(TEXE) + ./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS) + +# This is the common case. Run many tests that do not take too long, +# including fuzzcheck, sqlite3_analyzer, and sqldiff tests. +# +test: $(TESTPROGS) sourcetest fastfuzztest + ./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS) # Run a test using valgrind. This can take a really long time # because valgrind is so much slower than a native machine. # -valgrindtest: testfixture$(TEXE) sqlite3$(TEXE) fuzzershell$(TEXE) - valgrind -v ./fuzzershell$(TEXE) -f $(TOP)/test/fuzzdata1.txt - OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind +valgrindtest: $(TESTPROGS) valgrindfuzz + OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS) # A very fast test that checks basic sanity. The name comes from # the 60s-era electronics testing: "Turn it on and see if smoke # comes out." # -smoketest: testfixture$(TEXE) fuzzershell$(TEXE) - ./testfixture$(TEXE) $(TOP)/test/main.test +smoketest: $(TESTPROGS) fuzzcheck$(TEXE) + ./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS) sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl echo "#define TCLSH 2" > $@ - echo "#define SQLITE_ENABLE_DBSTAT_VTAB" >> $@ + echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@ cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@ echo "static const char *tclsh_main_loop(void){" >> $@ echo "static const char *zMainloop = " >> $@ - $(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl >> $@ + $(TCLSH_CMD) $(TOP)/tool/tostr.tcl $(TOP)/tool/spaceanal.tcl >> $@ echo "; return zMainloop; }" >> $@ sqlite3_analyzer$(TEXE): sqlite3_analyzer.c @@ -1029,6 +1142,12 @@ wordcount$(TEXE): $(TOP)/test/wordcount.c sqlite3.c speedtest1$(TEXE): $(TOP)/test/speedtest1.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/test/speedtest1.c sqlite3.lo $(TLIBS) +rbu$(EXE): $(TOP)/ext/rbu/rbu.c $(TOP)/ext/rbu/sqlite3rbu.c sqlite3.lo + $(LTLINK) -I. -o $@ $(TOP)/ext/rbu/rbu.c sqlite3.lo $(TLIBS) + +loadfts$(EXE): $(TOP)/tool/loadfts.c libsqlite3.la + $(LTLINK) $(TOP)/tool/loadfts.c libsqlite3.la -o $@ $(TLIBS) + # This target will fail if the SQLite amalgamation contains any exported # symbols that do not begin with "sqlite3_". It is run as part of the # releasetest.tcl script. @@ -1037,10 +1156,15 @@ checksymbols: sqlite3.lo nm -g --defined-only sqlite3.o | grep -v " sqlite3_" ; test $$? -ne 0 echo '0 errors out of 1 tests' -# Build the amalgamation-autoconf package. +# Build the amalgamation-autoconf package. The amalamgation-tarball target builds +# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz. +# The snapshot-tarball target builds a tarball named by the SHA1 hash # amalgamation-tarball: sqlite3.c - TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh + TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal + +snapshot-tarball: sqlite3.c + TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot # The next two rules are used to support the "threadtest" target. Building # threadtest runs a few thread-safety tests that are implemented in C. This @@ -1054,7 +1178,7 @@ THREADTEST3_SRC = $(TOP)/test/threadtest3.c \ $(TOP)/test/tt3_lookaside1.c threadtest3$(TEXE): sqlite3.lo $(THREADTEST3_SRC) - $(LTLINK) $(TOP)/test/threadtest3.c sqlite3.lo -o $@ $(TLIBS) + $(LTLINK) $(TOP)/test/threadtest3.c $(TOP)/src/test_multiplex.c sqlite3.lo -o $@ $(TLIBS) threadtest: threadtest3$(TEXE) ./threadtest3$(TEXE) @@ -1068,9 +1192,9 @@ lib_install: libsqlite3.la $(INSTALL) -d $(DESTDIR)$(libdir) $(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir) -install: sqlite3$(BEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install} +install: sqlite3$(TEXE) lib_install sqlite3.h sqlite3.pc ${HAVE_TCL:1=tcl_install} $(INSTALL) -d $(DESTDIR)$(bindir) - $(LTINSTALL) sqlite3$(BEXE) $(DESTDIR)$(bindir) + $(LTINSTALL) sqlite3$(TEXE) $(DESTDIR)$(bindir) $(INSTALL) -d $(DESTDIR)$(includedir) $(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(includedir) $(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(includedir) @@ -1106,9 +1230,15 @@ clean: rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c rm -f sqlite-*-output.vsix rm -f mptester mptester.exe + rm -f rbu rbu.exe + rm -f srcck1 srcck1.exe + rm -f fuzzershell fuzzershell.exe + rm -f fuzzcheck fuzzcheck.exe + rm -f sqldiff sqldiff.exe + rm -f fts5.* fts5parse.* distclean: clean - rm -f config.log config.status libtool Makefile sqlite3.pc + rm -f config.h config.log config.status libtool Makefile sqlite3.pc # # Windows section diff --git a/Makefile.linux-gcc b/Makefile.linux-gcc index 1c9f24f..1491a4b 100644 --- a/Makefile.linux-gcc +++ b/Makefile.linux-gcc @@ -118,11 +118,6 @@ READLINE_FLAGS = LIBREADLINE = #LIBREADLINE = -static -lreadline -ltermcap -#### Which "awk" program provides nawk compatibilty -# -# NAWK = nawk -NAWK = awk - # You should not have to change anything below this line ############################################################################### include $(TOP)/main.mk diff --git a/Makefile.msc b/Makefile.msc index df39851..843f9a2 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -10,11 +10,13 @@ # TOP = . +# <> # Set this non-0 to create and use the SQLite amalgamation file. # !IFNDEF USE_AMALGAMATION USE_AMALGAMATION = 1 !ENDIF +# <> # Set this non-0 to enable full warnings (-W4, etc) when compiling. # @@ -36,6 +38,13 @@ USE_STDCALL = 0 DYNAMIC_SHELL = 0 !ENDIF +# Set this non-0 to enable extra code that attempts to detect misuse of the +# SQLite API. +# +!IFNDEF API_ARMOR +API_ARMOR = 0 +!ENDIF + # If necessary, create a list of harmless compiler warnings to disable when # compiling the various tools. For the SQLite source code itself, warnings, # if any, will be disabled from within it. @@ -43,7 +52,7 @@ DYNAMIC_SHELL = 0 !IFNDEF NO_WARN !IF $(USE_FULLWARN)!=0 NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 -NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706 +NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706 !ENDIF !ENDIF @@ -61,11 +70,13 @@ USE_WP81_OPTS = 0 SPLIT_AMALGAMATION = 0 !ENDIF +# <> # Set this non-0 to use the International Components for Unicode (ICU). # !IFNDEF USE_ICU USE_ICU = 0 !ENDIF +# <> # Set this non-0 to dynamically link to the MSVC runtime library. # @@ -115,20 +126,28 @@ USE_RC = 1 FOR_WINRT = 0 !ENDIF -# Set this non-0 to compile binaries suitable for the UAP environment. +# Set this non-0 to compile binaries suitable for the UWP environment. # This setting does not apply to any binaries that require Tcl to operate # properly (i.e. the text fixture, etc). # -!IFNDEF FOR_UAP -FOR_UAP = 0 +!IFNDEF FOR_UWP +FOR_UWP = 0 !ENDIF +# Set this non-0 to compile binaries suitable for the Windows 10 platform. +# +!IFNDEF FOR_WIN10 +FOR_WIN10 = 0 +!ENDIF + +# <> # Set this non-0 to skip attempting to look for and/or link with the Tcl # runtime library. # !IFNDEF NO_TCL NO_TCL = 0 !ENDIF +# <> # Set this to non-0 to create and use PDBs. # @@ -179,6 +198,49 @@ DEBUG = 0 OPTIMIZATIONS = 2 !ENDIF +# Set the source code file to be used by executables and libraries when +# they need the amalgamation. +# +!IFNDEF SQLITE3C +!IF $(SPLIT_AMALGAMATION)!=0 +SQLITE3C = sqlite3-all.c +!ELSE +SQLITE3C = sqlite3.c +!ENDIF +!ENDIF + +# Set the include code file to be used by executables and libraries when +# they need SQLite. +# +!IFNDEF SQLITE3H +SQLITE3H = sqlite3.h +!ENDIF + +# This is the name to use for the SQLite dynamic link library (DLL). +# +!IFNDEF SQLITE3DLL +SQLITE3DLL = sqlite3.dll +!ENDIF + +# This is the name to use for the SQLite import library (LIB). +# +!IFNDEF SQLITE3LIB +SQLITE3LIB = sqlite3.lib +!ENDIF + +# This is the name to use for the SQLite shell executable (EXE). +# +!IFNDEF SQLITE3EXE +SQLITE3EXE = sqlite3.exe +!ENDIF + +# This is the argument used to set the program database (PDB) file for the +# SQLite shell executable (EXE). +# +!IFNDEF SQLITE3EXEPDB +SQLITE3EXEPDB = /pdb:sqlite3sh.pdb +!ENDIF + # These are the "standard" SQLite compilation options used when compiling for # the Windows platform. # @@ -188,10 +250,32 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 !ENDIF +# These are the "extended" SQLite compilation options used when compiling for +# the Windows 10 platform. +# +!IFNDEF EXT_FEATURE_FLAGS +!IF $(FOR_WIN10)!=0 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_SYSTEM_MALLOC=1 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_OMIT_LOCALTIME=1 +!ELSE +EXT_FEATURE_FLAGS = +!ENDIF +!ENDIF + ############################################################################### ############################### END OF OPTIONS ################################ ############################################################################### +# When compiling for the Windows 10 platform, the PLATFORM macro must be set +# to an appropriate value (e.g. x86, x64, arm, arm64, etc). +# +!IF $(FOR_WIN10)!=0 +!IFNDEF PLATFORM +!ERROR Using the FOR_WIN10 option requires a value for PLATFORM. +!ENDIF +!ENDIF + # This assumes that MSVC is always installed in 32-bit Program Files directory # and sets the variable for use in locating other 32-bit installs accordingly. # @@ -222,7 +306,7 @@ LD = link.exe RC = rc.exe !ENDIF -# Check for the MSVC runtime library path macro. Othertise, this value will +# Check for the MSVC runtime library path macro. Otherwise, this value will # default to the 'lib' directory underneath the MSVC installation directory. # !IFNDEF CRTLIBPATH @@ -259,7 +343,7 @@ NCC = $(NCC:\\=\) NCC = $(CC) !ENDIF -# Check for the MSVC native runtime library path macro. Othertise, +# Check for the MSVC native runtime library path macro. Otherwise, # this value will default to the 'lib' directory underneath the MSVC # installation directory. # @@ -269,7 +353,7 @@ NCRTLIBPATH = $(VCINSTALLDIR)\lib NCRTLIBPATH = $(NCRTLIBPATH:\\=\) -# Check for the Platform SDK library path macro. Othertise, this +# Check for the Platform SDK library path macro. Otherwise, this # value will default to the 'lib' directory underneath the Windows # SDK installation directory (the environment variable used appears # to be available when using Visual C++ 2008 or later via the @@ -281,13 +365,23 @@ NSDKLIBPATH = $(WINDOWSSDKDIR)\lib NSDKLIBPATH = $(NSDKLIBPATH:\\=\) +# Check for the UCRT library path macro. Otherwise, this value will +# default to the version-specific, platform-specific 'lib' directory +# underneath the Windows SDK installation directory. +# +!IFNDEF UCRTLIBPATH +UCRTLIBPATH = $(WINDOWSSDKDIR)\lib\$(WINDOWSSDKLIBVERSION)\ucrt\$(PLATFORM) +!ENDIF + +UCRTLIBPATH = $(UCRTLIBPATH:\\=\) + # C compiler and options for use in building executables that # will run on the platform that is doing the build. # !IF $(USE_FULLWARN)!=0 -BCC = $(NCC) -nologo -W4 +BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS) !ELSE -BCC = $(NCC) -nologo -W3 +BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS) !ENDIF # Check if assembly code listings should be generated for the source @@ -315,13 +409,22 @@ NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)" # same unless your are cross-compiling.) # !IF $(USE_FULLWARN)!=0 -TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 +TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS) !ELSE -TCC = $(CC) -nologo -W3 +TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS) !ENDIF TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src -fp:precise -RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src +RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS) + +# Adjust the names of the primary targets for use with Windows 10. +# +!IF $(FOR_WIN10)!=0 +SQLITE3DLL = winsqlite3.dll +SQLITE3LIB = winsqlite3.lib +SQLITE3EXE = winsqlite3shell.exe +SQLITE3EXEPDB = +!ENDIF # Check if we want to use the "stdcall" calling convention when compiling. # This is not supported by the compilers for non-x86 platforms. It should @@ -330,7 +433,7 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src # to how the Tcl library functions are declared and exported (i.e. without # an explicit calling convention, which results in "cdecl"). # -!IF $(USE_STDCALL)!=0 +!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0 !IF "$(PLATFORM)"=="x86" CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall @@ -351,7 +454,7 @@ SHELL_CCONV_OPTS = # These are additional compiler options used for the core library. # !IFNDEF CORE_COMPILE_OPTS -!IF $(DYNAMIC_SHELL)!=0 +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport) !ELSE CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) @@ -362,7 +465,7 @@ CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) # when linking. # !IFNDEF CORE_LINK_DEP -!IF $(DYNAMIC_SHELL)!=0 +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 CORE_LINK_DEP = !ELSE CORE_LINK_DEP = sqlite3.def @@ -372,7 +475,7 @@ CORE_LINK_DEP = sqlite3.def # These are additional linker options used for the core library. # !IFNDEF CORE_LINK_OPTS -!IF $(DYNAMIC_SHELL)!=0 +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 CORE_LINK_OPTS = !ELSE CORE_LINK_OPTS = /DEF:sqlite3.def @@ -382,30 +485,41 @@ CORE_LINK_OPTS = /DEF:sqlite3.def # These are additional compiler options used for the shell executable. # !IFNDEF SHELL_COMPILE_OPTS -!IF $(DYNAMIC_SHELL)!=0 +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport) !ELSE SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) !ENDIF !ENDIF +# This is the source code that the shell executable should be compiled +# with. +# +!IFNDEF SHELL_CORE_SRC +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_SRC = +!ELSE +SHELL_CORE_SRC = $(SQLITE3C) +!ENDIF +!ENDIF + # This is the core library that the shell executable should depend on. # !IFNDEF SHELL_CORE_DEP -!IF $(DYNAMIC_SHELL)!=0 -SHELL_CORE_DEP = sqlite3.dll +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_DEP = $(SQLITE3DLL) !ELSE -SHELL_CORE_DEP = libsqlite3.lib +SHELL_CORE_DEP = !ENDIF !ENDIF # This is the core library that the shell executable should link with. # !IFNDEF SHELL_CORE_LIB -!IF $(DYNAMIC_SHELL)!=0 -SHELL_CORE_LIB = sqlite3.lib +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_LIB = $(SQLITE3LIB) !ELSE -SHELL_CORE_LIB = libsqlite3.lib +SHELL_CORE_LIB = !ENDIF !ENDIF @@ -434,6 +548,13 @@ TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP !ENDIF +# C compiler options for the Windows 10 platform (needs MSVC 2015). +# +!IF $(FOR_WIN10)!=0 +TCC = $(TCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +BCC = $(BCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +!ENDIF + # Also, we need to dynamically link to the correct MSVC runtime # when compiling for WinRT (e.g. debug or release) OR if the # USE_CRT_DLL option is set to force dynamically linking to the @@ -457,6 +578,7 @@ BCC = $(BCC) -MT !ENDIF !ENDIF +# <> # The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in # any extension header files by default. For non-amalgamation # builds, we need to make sure the compiler can find these. @@ -480,6 +602,7 @@ MKSQLITE3C_ARGS = --linemacros MKSQLITE3C_ARGS = !ENDIF !ENDIF +# <> # Define -DNDEBUG to compile without debugging (i.e., for production usage) # Omitting the define will cause extra debugging code to be inserted and @@ -491,14 +614,14 @@ BCC = $(BCC) -DNDEBUG RCC = $(RCC) -DNDEBUG !ENDIF -!IF $(DEBUG)>0 -TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR -RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR +!IF $(DEBUG)>0 || $(API_ARMOR)!=0 || $(FOR_WIN10)!=0 +TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1 +RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1 !ENDIF !IF $(DEBUG)>2 -TCC = $(TCC) -DSQLITE_DEBUG -RCC = $(RCC) -DSQLITE_DEBUG +TCC = $(TCC) -DSQLITE_DEBUG=1 +RCC = $(RCC) -DSQLITE_DEBUG=1 !ENDIF !IF $(DEBUG)>4 || $(OSTRACE)!=0 @@ -507,8 +630,8 @@ RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1 !ENDIF !IF $(DEBUG)>5 -TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE -RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE +TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1 +RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1 !ENDIF # Prevent warnings about "insecure" MSVC runtime library functions @@ -544,6 +667,7 @@ RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 !ENDIF !ENDIF +# <> # The locations of the Tcl header and library files. Also, the library that # non-stubs enabled programs using Tcl must link against. These variables # (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment @@ -562,6 +686,14 @@ TCLLIBDIR = c:\tcl\lib LIBTCL = tcl85.lib !ENDIF +!IFNDEF LIBTCLSTUB +LIBTCLSTUB = tclstub85.lib +!ENDIF + +!IFNDEF LIBTCLPATH +LIBTCLPATH = c:\tcl\bin +!ENDIF + # The locations of the ICU header and library files. These variables # (ICUINCDIR, ICULIBDIR, and LIBICU) may be overridden via the environment # prior to running nmake in order to match the actual installed location on @@ -587,6 +719,7 @@ LIBICU = icuuc.lib icuin.lib !IFNDEF TCLSH_CMD TCLSH_CMD = tclsh85 !ENDIF +# <> # Compiler options needed for programs that use the readline() library. # @@ -644,8 +777,8 @@ REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_WIN32_USE_UUID=1 # Add the required and optional SQLite compilation options into the command # lines used to invoke the MSVC code and resource compilers. # -TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) -RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) +TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) +RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) # Add in any optional parameters specified on the commane line, e.g. # nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1" @@ -685,6 +818,7 @@ TCC = $(TCC) -Zi BCC = $(BCC) -Zi !ENDIF +# <> # If ICU support is enabled, add the compiler options for it. # !IF $(USE_ICU)!=0 @@ -695,6 +829,7 @@ RCC = $(RCC) -I$(TOP)\ext\icu TCC = $(TCC) -I$(ICUINCDIR) RCC = $(RCC) -I$(ICUINCDIR) !ENDIF +# <> # Command line prefixes for compiling code, compiling resources, # linking, etc. @@ -772,9 +907,10 @@ LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelH LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib !ENDIF -# When compiling for UAP, some extra linker options are also required. +# When compiling for UWP or the Windows 10 platform, some extra linker +# options are also required. # -!IF $(FOR_UAP)!=0 +!IF $(FOR_UWP)!=0 || $(FOR_WIN10)!=0 LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib LTLINKOPTS = $(LTLINKOPTS) mincore.lib !IFDEF PSDKLIBPATH @@ -782,12 +918,24 @@ LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)" !ENDIF !ENDIF +!IF $(FOR_WIN10)!=0 +LTLINKOPTS = $(LTLINKOPTS) /guard:cf "/LIBPATH:$(UCRTLIBPATH)" +!IF $(DEBUG)>1 +LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrtd.lib /DEFAULTLIB:ucrtd.lib +!ELSE +LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib +!ENDIF +!ENDIF + # If either debugging or symbols are enabled, enable PDBs. # !IF $(DEBUG)>1 || $(SYMBOLS)!=0 -LDFLAGS = /DEBUG +LDFLAGS = /DEBUG $(LDOPTS) +!ELSE +LDFLAGS = $(LDOPTS) !ENDIF +# <> # Start with the Tcl related linker options. # !IF $(NO_TCL)==0 @@ -801,16 +949,12 @@ LTLIBS = $(LIBTCL) LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR) LTLIBS = $(LTLIBS) $(LIBICU) !ENDIF - -# nawk compatible awk. -# -!IFNDEF NAWK -NAWK = gawk.exe -!ENDIF +# <> # You should not have to change anything below this line ############################################################################### +# <> # Object files for the SQLite library (non-amalgamation). # LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ @@ -820,6 +964,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \ fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \ fts3_tokenize_vtab.lo fts3_unicode.lo fts3_unicode2.lo fts3_write.lo \ + fts5.lo \ func.lo global.lo hash.lo \ icu.lo insert.lo journal.lo legacy.lo loadext.lo \ main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \ @@ -827,11 +972,13 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \ mutex.lo mutex_noop.lo mutex_unix.lo mutex_w32.lo \ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ - random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \ - table.lo threads.lo tokenize.lo trigger.lo \ + random.lo resolve.lo rowset.lo rtree.lo select.lo sqlite3rbu.lo status.lo \ + table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo util.lo vacuum.lo \ vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ - vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo + vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ + utf.lo vtab.lo +# <> # Object files for the amalgamation. # @@ -839,11 +986,15 @@ LIBOBJS1 = sqlite3.lo # Determine the real value of LIBOBJ based on the 'configure' script # +# <> !IF $(USE_AMALGAMATION)==0 LIBOBJ = $(LIBOBJS0) !ELSE +# <> LIBOBJ = $(LIBOBJS1) +# <> !ENDIF +# <> # Determine if embedded resource compilation and usage are enabled. # @@ -853,9 +1004,10 @@ LIBRESOBJS = sqlite3res.lo LIBRESOBJS = !ENDIF -# All of the source code files. +# <> +# Core source code files, part 1. # -SRC1 = \ +SRC00 = \ $(TOP)\src\alter.c \ $(TOP)\src\analyze.c \ $(TOP)\src\attach.c \ @@ -864,8 +1016,6 @@ SRC1 = \ $(TOP)\src\bitvec.c \ $(TOP)\src\btmutex.c \ $(TOP)\src\btree.c \ - $(TOP)\src\btree.h \ - $(TOP)\src\btreeInt.h \ $(TOP)\src\build.c \ $(TOP)\src\callback.c \ $(TOP)\src\complete.c \ @@ -879,8 +1029,6 @@ SRC1 = \ $(TOP)\src\func.c \ $(TOP)\src\global.c \ $(TOP)\src\hash.c \ - $(TOP)\src\hash.h \ - $(TOP)\src\hwtime.h \ $(TOP)\src\insert.c \ $(TOP)\src\journal.c \ $(TOP)\src\legacy.c \ @@ -893,29 +1041,22 @@ SRC1 = \ $(TOP)\src\mem3.c \ $(TOP)\src\mem5.c \ $(TOP)\src\memjournal.c \ - $(TOP)\src\msvc.h \ $(TOP)\src\mutex.c \ - $(TOP)\src\mutex.h \ $(TOP)\src\mutex_noop.c \ $(TOP)\src\mutex_unix.c \ $(TOP)\src\mutex_w32.c \ $(TOP)\src\notify.c \ $(TOP)\src\os.c \ - $(TOP)\src\os.h \ - $(TOP)\src\os_common.h \ - $(TOP)\src\os_setup.h \ $(TOP)\src\os_unix.c \ - $(TOP)\src\os_win.c \ - $(TOP)\src\os_win.h -SRC2 = \ + $(TOP)\src\os_win.c + +# Core source code files, part 2. +# +SRC01 = \ $(TOP)\src\pager.c \ - $(TOP)\src\pager.h \ - $(TOP)\src\parse.y \ $(TOP)\src\pcache.c \ - $(TOP)\src\pcache.h \ $(TOP)\src\pcache1.c \ $(TOP)\src\pragma.c \ - $(TOP)\src\pragma.h \ $(TOP)\src\prepare.c \ $(TOP)\src\printf.c \ $(TOP)\src\random.c \ @@ -923,93 +1064,143 @@ SRC2 = \ $(TOP)\src\rowset.c \ $(TOP)\src\select.c \ $(TOP)\src\status.c \ - $(TOP)\src\shell.c \ - $(TOP)\src\sqlite.h.in \ - $(TOP)\src\sqlite3ext.h \ - $(TOP)\src\sqliteInt.h \ - $(TOP)\src\sqliteLimit.h \ $(TOP)\src\table.c \ $(TOP)\src\threads.c \ $(TOP)\src\tclsqlite.c \ $(TOP)\src\tokenize.c \ + $(TOP)\src\treeview.c \ $(TOP)\src\trigger.c \ $(TOP)\src\utf.c \ $(TOP)\src\update.c \ $(TOP)\src\util.c \ $(TOP)\src\vacuum.c \ $(TOP)\src\vdbe.c \ - $(TOP)\src\vdbe.h \ $(TOP)\src\vdbeapi.c \ $(TOP)\src\vdbeaux.c \ $(TOP)\src\vdbeblob.c \ $(TOP)\src\vdbemem.c \ $(TOP)\src\vdbesort.c \ $(TOP)\src\vdbetrace.c \ - $(TOP)\src\vdbeInt.h \ $(TOP)\src\vtab.c \ - $(TOP)\src\vxworks.h \ $(TOP)\src\wal.c \ - $(TOP)\src\wal.h \ $(TOP)\src\walker.c \ $(TOP)\src\where.c \ + $(TOP)\src\wherecode.c \ + $(TOP)\src\whereexpr.c + +# Shell source code files. +# +SRC02 = \ + $(TOP)\src\shell.c + +# Core miscellaneous files. +# +SRC03 = \ + $(TOP)\src\parse.y + +# Core header files, part 1. +# +SRC04 = \ + $(TOP)\src\btree.h \ + $(TOP)\src\btreeInt.h \ + $(TOP)\src\hash.h \ + $(TOP)\src\hwtime.h \ + $(TOP)\src\msvc.h \ + $(TOP)\src\mutex.h \ + $(TOP)\src\os.h \ + $(TOP)\src\os_common.h \ + $(TOP)\src\os_setup.h \ + $(TOP)\src\os_win.h + +# Core header files, part 2. +# +SRC05 = \ + $(TOP)\src\pager.h \ + $(TOP)\src\pcache.h \ + $(TOP)\src\pragma.h \ + $(TOP)\src\sqlite.h.in \ + $(TOP)\src\sqlite3ext.h \ + $(TOP)\src\sqliteInt.h \ + $(TOP)\src\sqliteLimit.h \ + $(TOP)\src\vdbe.h \ + $(TOP)\src\vdbeInt.h \ + $(TOP)\src\vxworks.h \ + $(TOP)\src\wal.h \ $(TOP)\src\whereInt.h -# Source code for extensions +# Extension source code files, part 1. # -SRC3 = \ +SRC06 = \ $(TOP)\ext\fts1\fts1.c \ - $(TOP)\ext\fts1\fts1.h \ $(TOP)\ext\fts1\fts1_hash.c \ - $(TOP)\ext\fts1\fts1_hash.h \ $(TOP)\ext\fts1\fts1_porter.c \ - $(TOP)\ext\fts1\fts1_tokenizer.h \ $(TOP)\ext\fts1\fts1_tokenizer1.c \ $(TOP)\ext\fts2\fts2.c \ - $(TOP)\ext\fts2\fts2.h \ $(TOP)\ext\fts2\fts2_hash.c \ - $(TOP)\ext\fts2\fts2_hash.h \ $(TOP)\ext\fts2\fts2_icu.c \ $(TOP)\ext\fts2\fts2_porter.c \ - $(TOP)\ext\fts2\fts2_tokenizer.h \ $(TOP)\ext\fts2\fts2_tokenizer.c \ $(TOP)\ext\fts2\fts2_tokenizer1.c -SRC4 = \ + +# Extension source code files, part 2. +# +SRC07 = \ $(TOP)\ext\fts3\fts3.c \ - $(TOP)\ext\fts3\fts3.h \ - $(TOP)\ext\fts3\fts3Int.h \ $(TOP)\ext\fts3\fts3_aux.c \ $(TOP)\ext\fts3\fts3_expr.c \ $(TOP)\ext\fts3\fts3_hash.c \ - $(TOP)\ext\fts3\fts3_hash.h \ $(TOP)\ext\fts3\fts3_icu.c \ $(TOP)\ext\fts3\fts3_porter.c \ $(TOP)\ext\fts3\fts3_snippet.c \ - $(TOP)\ext\fts3\fts3_tokenizer.h \ $(TOP)\ext\fts3\fts3_tokenizer.c \ $(TOP)\ext\fts3\fts3_tokenizer1.c \ $(TOP)\ext\fts3\fts3_tokenize_vtab.c \ $(TOP)\ext\fts3\fts3_unicode.c \ $(TOP)\ext\fts3\fts3_unicode2.c \ $(TOP)\ext\fts3\fts3_write.c \ - $(TOP)\ext\icu\sqliteicu.h \ $(TOP)\ext\icu\icu.c \ - $(TOP)\ext\rtree\rtree.h \ - $(TOP)\ext\rtree\rtree.c + $(TOP)\ext\rtree\rtree.c \ + $(TOP)\ext\rbu\sqlite3rbu.c \ + $(TOP)\ext\misc\json1.c +# Extension header files, part 1. +# +SRC08 = \ + $(TOP)\ext\fts1\fts1.h \ + $(TOP)\ext\fts1\fts1_hash.h \ + $(TOP)\ext\fts1\fts1_tokenizer.h \ + $(TOP)\ext\fts2\fts2.h \ + $(TOP)\ext\fts2\fts2_hash.h \ + $(TOP)\ext\fts2\fts2_tokenizer.h + +# Extension header files, part 2. +# +SRC09 = \ + $(TOP)\ext\fts3\fts3.h \ + $(TOP)\ext\fts3\fts3Int.h \ + $(TOP)\ext\fts3\fts3_hash.h \ + $(TOP)\ext\fts3\fts3_tokenizer.h \ + $(TOP)\ext\icu\sqliteicu.h \ + $(TOP)\ext\rtree\rtree.h \ + $(TOP)\ext\rbu\sqlite3rbu.h # Generated source code files # -SRC5 = \ - keywordhash.h \ +SRC10 = \ opcodes.c \ + parse.c + +# Generated header files +# +SRC11 = \ + keywordhash.h \ opcodes.h \ - parse.c \ parse.h \ - sqlite3.h + $(SQLITE3H) # All source code files. # -SRC = $(SRC1) $(SRC2) $(SRC3) $(SRC4) $(SRC5) +SRC = $(SRC00) $(SRC01) $(SRC02) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11) # Source code to the test files. # @@ -1052,11 +1243,13 @@ TESTSRC = \ $(TOP)\src\test_tclvar.c \ $(TOP)\src\test_thread.c \ $(TOP)\src\test_vfs.c \ + $(TOP)\src\test_windirent.c \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ - $(TOP)\ext\fts3\fts3_test.c + $(TOP)\ext\fts3\fts3_test.c \ + $(TOP)\ext\rbu\test_rbu.c -# Statically linked extensions +# Statically linked extensions. # TESTEXT = \ $(TOP)\ext\misc\amatch.c \ @@ -1064,62 +1257,26 @@ TESTEXT = \ $(TOP)\ext\misc\eval.c \ $(TOP)\ext\misc\fileio.c \ $(TOP)\ext\misc\fuzzer.c \ + $(TOP)\ext\fts5\fts5_tcl.c \ + $(TOP)\ext\fts5\fts5_test_mi.c \ + $(TOP)\ext\fts5\fts5_test_tok.c \ $(TOP)\ext\misc\ieee754.c \ $(TOP)\ext\misc\nextchar.c \ $(TOP)\ext\misc\percentile.c \ $(TOP)\ext\misc\regexp.c \ + $(TOP)\ext\misc\series.c \ $(TOP)\ext\misc\spellfix.c \ $(TOP)\ext\misc\totype.c \ $(TOP)\ext\misc\wholenumber.c - # Source code to the library files needed by the test fixture # TESTSRC2 = \ - $(TOP)\src\attach.c \ - $(TOP)\src\backup.c \ - $(TOP)\src\bitvec.c \ - $(TOP)\src\btree.c \ - $(TOP)\src\build.c \ - $(TOP)\src\ctime.c \ - $(TOP)\src\date.c \ - $(TOP)\src\dbstat.c \ - $(TOP)\src\expr.c \ - $(TOP)\src\func.c \ - $(TOP)\src\insert.c \ - $(TOP)\src\wal.c \ - $(TOP)\src\main.c \ - $(TOP)\src\mem5.c \ - $(TOP)\src\os.c \ - $(TOP)\src\os_unix.c \ - $(TOP)\src\os_win.c \ - $(TOP)\src\pager.c \ - $(TOP)\src\pragma.c \ - $(TOP)\src\prepare.c \ - $(TOP)\src\printf.c \ - $(TOP)\src\random.c \ - $(TOP)\src\pcache.c \ - $(TOP)\src\pcache1.c \ - $(TOP)\src\select.c \ - $(TOP)\src\tokenize.c \ - $(TOP)\src\utf.c \ - $(TOP)\src\util.c \ - $(TOP)\src\vdbeapi.c \ - $(TOP)\src\vdbeaux.c \ - $(TOP)\src\vdbe.c \ - $(TOP)\src\vdbemem.c \ - $(TOP)\src\vdbesort.c \ - $(TOP)\src\vdbetrace.c \ - $(TOP)\src\where.c \ - parse.c \ - $(TOP)\ext\fts3\fts3.c \ - $(TOP)\ext\fts3\fts3_aux.c \ - $(TOP)\ext\fts3\fts3_expr.c \ - $(TOP)\ext\fts3\fts3_tokenizer.c \ - $(TOP)\ext\fts3\fts3_tokenize_vtab.c \ - $(TOP)\ext\fts3\fts3_unicode.c \ - $(TOP)\ext\fts3\fts3_unicode2.c \ - $(TOP)\ext\fts3\fts3_write.c \ + $(SRC00) \ + $(SRC01) \ + $(SRC06) \ + $(SRC07) \ + $(SRC10) \ $(TOP)\ext\async\sqlite3async.c # Header files used by all library source files. @@ -1141,7 +1298,7 @@ HDR = \ $(TOP)\src\pcache.h \ parse.h \ $(TOP)\src\pragma.h \ - sqlite3.h \ + $(SQLITE3H) \ $(TOP)\src\sqlite3ext.h \ $(TOP)\src\sqliteInt.h \ $(TOP)\src\sqliteLimit.h \ @@ -1172,30 +1329,104 @@ EXTHDR = $(EXTHDR) \ EXTHDR = $(EXTHDR) \ $(TOP)\ext\rtree\sqlite3rtree.h +# executables needed for testing +# +TESTPROGS = \ + testfixture.exe \ + $(SQLITE3EXE) \ + sqlite3_analyzer.exe \ + sqldiff.exe + +# Databases containing fuzzer test cases +# +FUZZDATA = \ + $(TOP)\test\fuzzdata1.db \ + $(TOP)\test\fuzzdata2.db \ + $(TOP)\test\fuzzdata3.db \ + $(TOP)\test\fuzzdata4.db +# <> + +# Additional compiler options for the shell. These are only effective +# when the shell is not being dynamically linked. +# +!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS +!ENDIF + +# <> +# Extra compiler options for various test tools. +# +MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5 +FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 +FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 + +# Standard options to testfixture. +# +TESTOPTS = --verbose=file --output=test-out.txt + +# Extra targets for the "all" target that require Tcl. +# +!IF $(NO_TCL)==0 +ALL_TCL_TARGETS = libtclsqlite3.lib +!ELSE +ALL_TCL_TARGETS = +!ENDIF +# <> + # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. # -all: dll libsqlite3.lib sqlite3.exe libtclsqlite3.lib +all: dll libsqlite3.lib shell $(ALL_TCL_TARGETS) + +# Dynamic link library section. +# +dll: $(SQLITE3DLL) + +# Shell executable. +# +shell: $(SQLITE3EXE) libsqlite3.lib: $(LIBOBJ) $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) +# <> libtclsqlite3.lib: tclsqlite.lo libsqlite3.lib - $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS) + $(LTLIB) $(LTLIBOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCLSTUB) $(TLIBS) +# <> -sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h - $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \ - /link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) +$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) + $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) -sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h - $(LTLINK) $(TOP)\tool\sqldiff.c sqlite3.c +# <> +sqlite3.def: libsqlite3.lib + echo EXPORTS > sqlite3.def + dumpbin /all libsqlite3.lib \ + | $(TCLSH_CMD) $(TOP)\tool\replace.tcl include "^\s+1 _?(sqlite3_.*)$$" \1 \ + | sort >> sqlite3.def +# <> -fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h - $(LTLINK) $(TOP)\tool\fuzzershell.c sqlite3.c +$(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) + $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(SHELL_CORE_SRC) \ + /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) -mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h - $(LTLINK) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \ - /link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) +# <> +sqldiff.exe: $(TOP)\tool\sqldiff.c $(SQLITE3C) $(SQLITE3H) + $(LTLINK) $(NO_WARN) $(TOP)\tool\sqldiff.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) + +srcck1.exe: $(TOP)\tool\srcck1.c + $(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\srcck1.c + +sourcetest: srcck1.exe sqlite3.c + srcck1.exe sqlite3.c + +fuzzershell.exe: $(TOP)\tool\fuzzershell.c $(SQLITE3C) $(SQLITE3H) + $(LTLINK) $(NO_WARN) $(FUZZERSHELL_COMPILE_OPTS) $(TOP)\tool\fuzzershell.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) + +fuzzcheck.exe: $(TOP)\test\fuzzcheck.c $(SQLITE3C) $(SQLITE3H) + $(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(TOP)\test\fuzzcheck.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) + +mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H) + $(LTLINK) $(NO_WARN) $(MPTESTER_COMPILE_OPTS) $(TOP)\mptest\mptest.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20 MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20 @@ -1217,49 +1448,50 @@ mptest: mptester.exe # files are automatically generated. This target takes care of # all that automatic generation. # -.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl +.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c -rmdir /Q/S tsrc 2>NUL -mkdir tsrc - for %i in ($(SRC1)) do copy /Y %i tsrc - for %i in ($(SRC2)) do copy /Y %i tsrc - for %i in ($(SRC3)) do copy /Y %i tsrc - for %i in ($(SRC4)) do copy /Y %i tsrc - for %i in ($(SRC5)) do copy /Y %i tsrc + for %i in ($(SRC00)) do copy /Y %i tsrc + for %i in ($(SRC01)) do copy /Y %i tsrc + for %i in ($(SRC02)) do copy /Y %i tsrc + for %i in ($(SRC03)) do copy /Y %i tsrc + for %i in ($(SRC04)) do copy /Y %i tsrc + for %i in ($(SRC05)) do copy /Y %i tsrc + for %i in ($(SRC06)) do copy /Y %i tsrc + for %i in ($(SRC07)) do copy /Y %i tsrc + for %i in ($(SRC08)) do copy /Y %i tsrc + for %i in ($(SRC09)) do copy /Y %i tsrc + for %i in ($(SRC10)) do copy /Y %i tsrc + for %i in ($(SRC11)) do copy /Y %i tsrc + copy /Y fts5.c tsrc + copy /Y fts5.h tsrc del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new move vdbe.new tsrc\vdbe.c echo > .target_source -sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl +sqlite3.c: .target_source sqlite3ext.h $(TOP)\tool\mksqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl $(MKSQLITE3C_ARGS) copy tsrc\shell.c . - copy tsrc\sqlite3ext.h . sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl - -# Set the source code file to be used by executables and libraries when -# they need the amalgamation. -# -!IF $(SPLIT_AMALGAMATION)!=0 -SQLITE3C = sqlite3-all.c -!ELSE -SQLITE3C = sqlite3.c -!ENDIF +# <> # Rule to build the amalgamation # sqlite3.lo: $(SQLITE3C) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C) +# <> # Rules to build the LEMON compiler generator # -lempar.c: $(TOP)\src\lempar.c - copy $(TOP)\src\lempar.c . +lempar.c: $(TOP)\tool\lempar.c + copy $(TOP)\tool\lempar.c . lemon.exe: $(TOP)\tool\lemon.c lempar.c $(BCC) $(NO_WARN) -Daccess=_access \ - -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS) + -Fe$@ $(TOP)\tool\lemon.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS) # Rules to build individual *.lo files from generated *.c files. This # applies to: @@ -1272,20 +1504,24 @@ parse.lo: parse.c $(HDR) opcodes.lo: opcodes.c $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c opcodes.c +# <> # Rule to build the Win32 resources object file. # !IF $(USE_RC)!=0 -$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(HDR) +# <> +$(LIBRESOBJS): $(TOP)\src\sqlite3.rc $(SQLITE3H) echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h for /F %%V in ('type "$(TOP)\VERSION"') do ( \ echo #define SQLITE_RESOURCE_VERSION %%V \ - | $(NAWK) "/.*/ { gsub(/[.]/,\",\");print }" >> sqlite3rc.h \ + | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact . ^, >> sqlite3rc.h \ ) echo #endif >> sqlite3rc.h $(LTRCOMPILE) -fo $(LIBRESOBJS) $(TOP)\src\sqlite3.rc +# <> !ENDIF +# <> # Rules to build individual *.lo files from files in the src directory. # alter.lo: $(TOP)\src\alter.c $(HDR) @@ -1453,6 +1689,9 @@ threads.lo: $(TOP)\src\threads.c $(HDR) tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\tokenize.c +treeview.lo: $(TOP)\src\treeview.c $(HDR) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\treeview.c + trigger.lo: $(TOP)\src\trigger.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c @@ -1501,40 +1740,49 @@ walker.lo: $(TOP)\src\walker.c $(HDR) where.lo: $(TOP)\src\where.c $(HDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\where.c +wherecode.lo: $(TOP)\src\wherecode.c $(HDR) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wherecode.c + +whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c + tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c -tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(LIBRESOBJS) - $(LTLINK) $(SQLITE3C) /link $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS) +tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS) + $(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS) # Rules to build opcodes.c and opcodes.h # -opcodes.c: opcodes.h $(TOP)\mkopcodec.awk - $(NAWK) -f $(TOP)\mkopcodec.awk opcodes.h > opcodes.c +opcodes.c: opcodes.h $(TOP)\tool\mkopcodec.tcl + $(TCLSH_CMD) $(TOP)\tool\mkopcodec.tcl opcodes.h > opcodes.c -opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\mkopcodeh.awk - type parse.h $(TOP)\src\vdbe.c | $(NAWK) -f $(TOP)\mkopcodeh.awk > opcodes.h +opcodes.h: parse.h $(TOP)\src\vdbe.c $(TOP)\tool\mkopcodeh.tcl + type parse.h $(TOP)\src\vdbe.c | $(TCLSH_CMD) $(TOP)\tool\mkopcodeh.tcl > opcodes.h # Rules to build parse.c and parse.h - the outputs of lemon. # parse.h: parse.c -parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk +parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl del /Q parse.y parse.h parse.h.temp 2>NUL copy $(TOP)\src\parse.y . - .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y + .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) parse.y move parse.h parse.h.temp - $(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h + $(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h -sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION - $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h +$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION + $(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) + +sqlite3ext.h: .target_source + copy tsrc\sqlite3ext.h . mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c - $(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) \ - $(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS) + $(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \ + $(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS) keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe .\mkkeywordhash.exe > keywordhash.h @@ -1606,6 +1854,47 @@ fts3_write.lo: $(TOP)\ext\fts3\fts3_write.c $(HDR) $(EXTHDR) rtree.lo: $(TOP)\ext\rtree\rtree.c $(HDR) $(EXTHDR) $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c $(TOP)\ext\rtree\rtree.c +# FTS5 things +# +FTS5_SRC = \ + $(TOP)\ext\fts5\fts5.h \ + $(TOP)\ext\fts5\fts5Int.h \ + $(TOP)\ext\fts5\fts5_aux.c \ + $(TOP)\ext\fts5\fts5_buffer.c \ + $(TOP)\ext\fts5\fts5_main.c \ + $(TOP)\ext\fts5\fts5_config.c \ + $(TOP)\ext\fts5\fts5_expr.c \ + $(TOP)\ext\fts5\fts5_hash.c \ + $(TOP)\ext\fts5\fts5_index.c \ + fts5parse.c fts5parse.h \ + $(TOP)\ext\fts5\fts5_storage.c \ + $(TOP)\ext\fts5\fts5_tokenize.c \ + $(TOP)\ext\fts5\fts5_unicode2.c \ + $(TOP)\ext\fts5\fts5_varint.c \ + $(TOP)\ext\fts5\fts5_vocab.c + +fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe + copy $(TOP)\ext\fts5\fts5parse.y . + del /Q fts5parse.h 2>NUL + .\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) fts5parse.y + +fts5parse.h: fts5parse.c + +fts5.c: $(FTS5_SRC) + $(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl + copy $(TOP)\ext\fts5\fts5.h . + +fts5.lo: fts5.c $(HDR) $(EXTHDR) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c + +fts5_ext.lo: fts5.c $(HDR) $(EXTHDR) + $(LTCOMPILE) $(NO_WARN) -c fts5.c + +fts5.dll: fts5_ext.lo + $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ fts5_ext.lo + +sqlite3rbu.lo: $(TOP)\ext\rbu\sqlite3rbu.c $(HDR) $(EXTHDR) + $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)\ext\rbu\sqlite3rbu.c # Rules to build the 'testfixture' application. # @@ -1618,7 +1907,7 @@ TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN) -TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) $(SHELL_CORE_DEP) +TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C) !IF $(USE_AMALGAMATION)==0 TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) @@ -1626,49 +1915,67 @@ TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0) TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1) !ENDIF -testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR) +testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \ -DBUILD_sqlite -I$(TCLINCDIR) \ $(TESTFIXTURE_SRC) \ - /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) + /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) extensiontest: testfixture.exe testloadext.dll - .\testfixture.exe $(TOP)\test\loadext.test + @set PATH=$(LIBTCLPATH);$(PATH) + .\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS) -fulltest: testfixture.exe sqlite3.exe fuzztest - .\testfixture.exe $(TOP)\test\all.test +fulltest: $(TESTPROGS) fuzztest + @set PATH=$(LIBTCLPATH);$(PATH) + .\testfixture.exe $(TOP)\test\all.test $(TESTOPTS) -soaktest: testfixture.exe sqlite3.exe fuzzoomtest - .\testfixture.exe $(TOP)\test\all.test -soak=1 +soaktest: $(TESTPROGS) + @set PATH=$(LIBTCLPATH);$(PATH) + .\testfixture.exe $(TOP)\test\all.test -soak=1 $(TESTOPTS) -fulltestonly: testfixture.exe sqlite3.exe fuzztest +fulltestonly: $(TESTPROGS) fuzztest + @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\full.test -queryplantest: testfixture.exe sqlite3.exe - .\testfixture.exe $(TOP)\test\permutations.test queryplanner +queryplantest: testfixture.exe shell + @set PATH=$(LIBTCLPATH);$(PATH) + .\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS) -fuzztest: fuzzershell.exe - .\fuzzershell.exe $(TOP)\test\fuzzdata1.txt $(TOP)\test\fuzzdata2.txt +fuzztest: fuzzcheck.exe + .\fuzzcheck.exe $(FUZZDATA) -fuzzoomtest: fuzzershell.exe - .\fuzzershell.exe -f $(TOP)\test\fuzzdata1.txt --oom +fastfuzztest: fuzzcheck.exe + .\fuzzcheck.exe --limit-mem 100M $(FUZZDATA) -test: testfixture.exe sqlite3.exe fuzztest - .\testfixture.exe $(TOP)\test\veryquick.test +# Minimal testing that runs in less than 3 minutes (on a fast machine) +# +quicktest: testfixture.exe sourcetest + @set PATH=$(LIBTCLPATH);$(PATH) + .\testfixture.exe $(TOP)\test\extraquick.test $(TESTOPTS) -smoketest: testfixture.exe - .\testfixture.exe $(TOP)\test\main.test +# This is the common case. Run many tests that do not take too long, +# including fuzzcheck, sqlite3_analyzer, and sqldiff tests. +# +test: $(TESTPROGS) sourcetest fastfuzztest + @set PATH=$(LIBTCLPATH);$(PATH) + .\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS) -sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl - copy $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@ +smoketest: $(TESTPROGS) + @set PATH=$(LIBTCLPATH);$(PATH) + .\testfixture.exe $(TOP)\test\main.test $(TESTOPTS) + +sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl + echo #define TCLSH 2 > $@ + echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@ + copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@ echo static const char *tclsh_main_loop(void){ >> $@ echo static const char *zMainloop = >> $@ - $(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@ + $(TCLSH_CMD) $(TOP)\tool\tostr.tcl $(TOP)\tool\spaceanal.tcl >> $@ echo ; return zMainloop; } >> $@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS) - $(LTLINK) $(NO_WARN) -DBUILD_sqlite -DSQLITE_ENABLE_DBSTAT_VTAB -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \ - /link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) + $(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \ + /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) testloadext.lo: $(TOP)\src\test_loadext.c $(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c @@ -1676,45 +1983,51 @@ testloadext.lo: $(TOP)\src\test_loadext.c testloadext.dll: testloadext.lo $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo -showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) +showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\tool\showdb.c $(SQLITE3C) + $(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) -showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) +showstat4.exe: $(TOP)\tool\showstat4.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\tool\showstat4.c $(SQLITE3C) + $(TOP)\tool\showstat4.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) -showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) +showjournal.exe: $(TOP)\tool\showjournal.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\tool\showjournal.c $(SQLITE3C) + $(TOP)\tool\showjournal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) -showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) +showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\tool\showwal.c $(SQLITE3C) + $(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) -fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) +fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) + $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) -rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) +rollback-test.exe: $(TOP)\tool\rollback-test.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\tool\rollback-test.c $(SQLITE3C) + $(TOP)\tool\rollback-test.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) -LogEst.exe: $(TOP)\tool\logest.c sqlite3.h - $(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c +LogEst.exe: $(TOP)\tool\logest.c $(SQLITE3H) + $(LTLINK) $(NO_WARN) -Fe$@ $(TOP)\tool\LogEst.c /link $(LDFLAGS) $(LTLINKOPTS) -wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) +wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\test\wordcount.c $(SQLITE3C) + $(TOP)\test\wordcount.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) -speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) +speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \ - $(TOP)\test\speedtest1.c $(SQLITE3C) + $(TOP)\test\speedtest1.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) + +rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H) + $(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU -Fe$@ \ + $(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) +# <> clean: - del /Q *.exp *.lo *.ilk *.lib *.obj *.pdb 2>NUL - del /Q *.cod *.da *.bb *.bbg gmon.out 2>NUL - del /Q sqlite3.h opcodes.c opcodes.h 2>NUL + 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 $(SQLITE3C) $(SQLITE3H) opcodes.c opcodes.h 2>NUL del /Q lemon.* lempar.c parse.* 2>NUL del /Q mkkeywordhash.* keywordhash.h 2>NUL del /Q notasharedlib.* 2>NUL @@ -1730,23 +2043,13 @@ clean: del /Q testfixture.exe test.db 2>NUL del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL - del /Q mptester.exe wordcount.exe 2>NUL - del /Q sqlite3.exe sqlite3.dll sqlite3.def 2>NUL + del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL + del /Q $(SQLITE3EXE) $(SQLITE3DLL) sqlite3.def 2>NUL del /Q sqlite3.c sqlite3-*.c 2>NUL del /Q sqlite3rc.h 2>NUL del /Q shell.c sqlite3ext.h 2>NUL del /Q sqlite3_analyzer.exe sqlite3_analyzer.c 2>NUL del /Q sqlite-*-output.vsix 2>NUL - -# Dynamic link library section. -# -dll: sqlite3.dll - -sqlite3.def: libsqlite3.lib - echo EXPORTS > sqlite3.def - dumpbin /all libsqlite3.lib \ - | $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \ - | sort >> sqlite3.def - -sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) - $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) + del /Q fuzzershell.exe fuzzcheck.exe sqldiff.exe 2>NUL + del /Q fts5.* fts5parse.* 2>NUL +# <> diff --git a/Makefile.vxworks b/Makefile.vxworks deleted file mode 100644 index 706261f..0000000 --- a/Makefile.vxworks +++ /dev/null @@ -1,673 +0,0 @@ -#!/usr/make -# -# Makefile for SQLITE on VxWorks - -ifeq ($(FORCPU),) - FORCPU = SH32gnule -endif - -TOOL_FAMILY = gnu - -include $(WIND_USR)/tool/gnu/make.$(FORCPU) - -#### The toplevel directory of the source tree. This is the directory -# that contains this "Makefile.in" and the "configure.in" script. -# -TOP = . - -#### C Compiler and options for use in building executables that -# will run on the platform that is doing the build. -# -BCC = gcc -g -O2 -#BCC = /opt/ancic/bin/c89 -0 - -#### If the target operating system supports the "usleep()" system -# call, then define the HAVE_USLEEP macro for all C modules. -# -USLEEP = -#USLEEP = -DHAVE_USLEEP=1 - -#### If you want the SQLite library to be safe for use within a -# multi-threaded program, then define the following macro -# appropriately: -# -THREADSAFE = -DSQLITE_THREADSAFE=1 -#THREADSAFE = -DSQLITE_THREADSAFE=0 - -#### Specify any extra linker options needed to make the library -# thread safe -# -#THREADLIB = -lpthread -THREADLIB = - -#### Specify any extra libraries needed to access required functions. -# -ifeq ($(CPU),SH32) - # for SH4 shared library - TLIBS_SHARED += -L$(WIND_USR)/lib/sh/SH32/commonle/PIC -else - # for all other CPUs shared library - TLIBS_SHARED += $(LD_LINK_PATH_ATEND) $(LD_PARTIAL_LAST_FLAGS) -endif -# for static library -TLIBS += $(LD_LINK_PATH_ATEND) $(LD_PARTIAL_LAST_FLAGS) - -#### Leave SQLITE_DEBUG undefined for maximum speed. Use SQLITE_DEBUG=1 -# to check for memory leaks. Use SQLITE_DEBUG=2 to print a log of all -# malloc()s and free()s in order to track down memory leaks. -# -# SQLite uses some expensive assert() statements in the inner loop. -# You can make the library go almost twice as fast if you compile -# with -DNDEBUG=1 -# -#OPTS = -DSQLITE_DEBUG=2 -#OPTS = -DSQLITE_DEBUG=1 -#OPTS = -OPTS = -DNDEBUG=1 -DSQLITE_OS_UNIX=1 $(THREADSAFE) -OPTS += -DSQLITE_OMIT_LOAD_EXTENSION=1 -OPTS += -DSQLITE_ENABLE_LOCKING_STYLE=1 -OPTS += -DSQLITE_THREAD_OVERRIDE_LOCK=0 -OPTS += -DSQLITE_ENABLE_COLUMN_METADATA=1 -OPTS += -DHAVE_FDATASYNC=1 - -#### The suffix to add to executable files. ".exe" for windows. -# Nothing for unix. -# -EXE = .vxe -#EXE = - -#### C Compile and options for use in building executables that -# will run on the target platform. This is usually the same -# as BCC, unless you are cross-compiling. -# -#TCC = gcc -O6 -#TCC = gcc -g -O0 -Wall -#TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage -#TCC = /opt/mingw/bin/i386-mingw32-gcc -O6 -TCC = $(CC) $(DEFINE_CC) -O2 -g -mrtp $(CC_ARCH_SPEC) -D_REENTRANT=1 -D_VX_CPU=_VX_$(CPU) -D_VX_TOOL_FAMILY=$(TOOL_FAMILY) -D_VX_TOOL=$(TOOL) -TCC += -I$(WIND_USR)/h -I$(WIND_USR)/h/wrn/coreip -#TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive - -#TCC_SHARED = $(TCC) -fPIC -TCC_SHARED = $(TCC) - -#### Tools used to build a static library. -# -#ARX = ar cr -#ARX = /opt/mingw/bin/i386-mingw32-ar cr -AR += cr -#RANLIB = ranlib -#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib - -#MKSHLIB = gcc -shared -#SO = so -#SHPREFIX = lib -MKSHLIB = $(CC) $(DEFINE_CC) -mrtp -shared $(CC_ARCH_SPEC) -D_VX_CPU=_VX_$(CPU) -D_VX_TOOL_FAMILY=$(TOOL_FAMILY) -D_VX_TOOL=$(TOOL) -SO = so -SHPREFIX = lib - -#### Extra compiler options needed for programs that use the TCL library. -# -#TCL_FLAGS = -#TCL_FLAGS = -DSTATIC_BUILD=1 -TCL_FLAGS = -I/home/drh/tcltk/8.5linux -#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1 -#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux - -#### Linker options needed to link against the TCL library. -# -#LIBTCL = -ltcl -lm -ldl -LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl -#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt -#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc - -#### Additional objects for SQLite library when TCL support is enabled. -TCLOBJ = -#TCLOBJ = tclsqlite.o - -#### Compiler options needed for programs that use the readline() library. -# -READLINE_FLAGS = -#READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline - -#### Linker options needed by programs using readline() must link against. -# -LIBREADLINE = -#LIBREADLINE = -static -lreadline -ltermcap - -#### Which "awk" program provides nawk compatibilty -# -# NAWK = nawk -NAWK = awk - - -#### Pasted and adapted main.mk file -############################################################################### -# The following macros should be defined before this script is -# invoked: -# -# TOP The toplevel directory of the source tree. This is the -# directory that contains this "Makefile.in" and the -# "configure.in" script. -# -# BCC C Compiler and options for use in building executables that -# will run on the platform that is doing the build. -# -# THREADLIB Specify any extra linker options needed to make the library -# thread safe -# -# OPTS Extra compiler command-line options. -# -# EXE The suffix to add to executable files. ".exe" for windows -# and "" for Unix. -# -# TCC C Compiler and options for use in building executables that -# will run on the target platform. This is usually the same -# as BCC, unless you are cross-compiling. -# -# AR Tools used to build a static library. -# RANLIB -# -# TCL_FLAGS Extra compiler options needed for programs that use the -# TCL library. -# -# LIBTCL Linker options needed to link against the TCL library. -# -# READLINE_FLAGS Compiler options needed for programs that use the -# readline() library. -# -# LIBREADLINE Linker options needed by programs using readline() must -# link against. -# -# NAWK Nawk compatible awk program. Older (obsolete?) solaris -# systems need this to avoid using the original AT&T AWK. -# -# Once the macros above are defined, the rest of this make script will -# build the SQLite library and testing tools. -################################################################################ - -# This is how we compile -# -TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) -TCCX_SHARED = $(TCC_SHARED) $(OPTS) -I. -I$(TOP)/src -I$(TOP) \ - -I$(TOP)/ext/rtree -I$(TOP)/ext/icu -I$(TOP)/ext/fts3 \ - -I$(TOP)/ext/async - -# Object files for the SQLite library. -# -LIBOBJ+= alter.o analyze.o attach.o auth.o \ - backup.o bitvec.o btmutex.o btree.o build.o \ - callback.o complete.o date.o delete.o expr.o fault.o \ - fts3.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \ - fts3_tokenizer.o fts3_tokenizer1.o \ - func.o global.o hash.o \ - icu.o insert.o journal.o legacy.o loadext.o \ - main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \ - memjournal.o \ - mutex.o mutex_noop.o mutex_unix.o mutex_w32.o \ - notify.o opcodes.o os.o os_unix.o os_win.o \ - pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \ - random.o resolve.o rowset.o rtree.o select.o status.o \ - table.o tokenize.o trigger.o \ - update.o util.o vacuum.o \ - vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o \ - walker.o where.o utf.o vtab.o - - - -# All of the source code files. -# -SRC = \ - $(TOP)/src/alter.c \ - $(TOP)/src/analyze.c \ - $(TOP)/src/attach.c \ - $(TOP)/src/auth.c \ - $(TOP)/src/backup.c \ - $(TOP)/src/bitvec.c \ - $(TOP)/src/btmutex.c \ - $(TOP)/src/btree.c \ - $(TOP)/src/btree.h \ - $(TOP)/src/btreeInt.h \ - $(TOP)/src/build.c \ - $(TOP)/src/callback.c \ - $(TOP)/src/complete.c \ - $(TOP)/src/ctime.c \ - $(TOP)/src/date.c \ - $(TOP)/src/delete.c \ - $(TOP)/src/expr.c \ - $(TOP)/src/fault.c \ - $(TOP)/src/func.c \ - $(TOP)/src/global.c \ - $(TOP)/src/hash.c \ - $(TOP)/src/hash.h \ - $(TOP)/src/hwtime.h \ - $(TOP)/src/insert.c \ - $(TOP)/src/journal.c \ - $(TOP)/src/legacy.c \ - $(TOP)/src/loadext.c \ - $(TOP)/src/main.c \ - $(TOP)/src/malloc.c \ - $(TOP)/src/mem0.c \ - $(TOP)/src/mem1.c \ - $(TOP)/src/mem2.c \ - $(TOP)/src/mem3.c \ - $(TOP)/src/mem5.c \ - $(TOP)/src/memjournal.c \ - $(TOP)/src/msvc.h \ - $(TOP)/src/mutex.c \ - $(TOP)/src/mutex.h \ - $(TOP)/src/mutex_noop.c \ - $(TOP)/src/mutex_unix.c \ - $(TOP)/src/mutex_w32.c \ - $(TOP)/src/notify.c \ - $(TOP)/src/os.c \ - $(TOP)/src/os.h \ - $(TOP)/src/os_common.h \ - $(TOP)/src/os_setup.h \ - $(TOP)/src/os_unix.c \ - $(TOP)/src/os_win.c \ - $(TOP)/src/os_win.h \ - $(TOP)/src/pager.c \ - $(TOP)/src/pager.h \ - $(TOP)/src/parse.y \ - $(TOP)/src/pcache.c \ - $(TOP)/src/pcache.h \ - $(TOP)/src/pcache1.c \ - $(TOP)/src/pragma.c \ - $(TOP)/src/prepare.c \ - $(TOP)/src/printf.c \ - $(TOP)/src/random.c \ - $(TOP)/src/resolve.c \ - $(TOP)/src/rowset.c \ - $(TOP)/src/select.c \ - $(TOP)/src/status.c \ - $(TOP)/src/shell.c \ - $(TOP)/src/sqlite.h.in \ - $(TOP)/src/sqlite3ext.h \ - $(TOP)/src/sqliteInt.h \ - $(TOP)/src/sqliteLimit.h \ - $(TOP)/src/table.c \ - $(TOP)/src/tclsqlite.c \ - $(TOP)/src/tokenize.c \ - $(TOP)/src/trigger.c \ - $(TOP)/src/utf.c \ - $(TOP)/src/update.c \ - $(TOP)/src/util.c \ - $(TOP)/src/vacuum.c \ - $(TOP)/src/vdbe.c \ - $(TOP)/src/vdbe.h \ - $(TOP)/src/vdbeapi.c \ - $(TOP)/src/vdbeaux.c \ - $(TOP)/src/vdbeblob.c \ - $(TOP)/src/vdbemem.c \ - $(TOP)/src/vdbeInt.h \ - $(TOP)/src/vtab.c \ - $(TOP)/src/walker.c \ - $(TOP)/src/where.c - -# Source code for extensions -# -SRC += \ - $(TOP)/ext/fts1/fts1.c \ - $(TOP)/ext/fts1/fts1.h \ - $(TOP)/ext/fts1/fts1_hash.c \ - $(TOP)/ext/fts1/fts1_hash.h \ - $(TOP)/ext/fts1/fts1_porter.c \ - $(TOP)/ext/fts1/fts1_tokenizer.h \ - $(TOP)/ext/fts1/fts1_tokenizer1.c -SRC += \ - $(TOP)/ext/fts2/fts2.c \ - $(TOP)/ext/fts2/fts2.h \ - $(TOP)/ext/fts2/fts2_hash.c \ - $(TOP)/ext/fts2/fts2_hash.h \ - $(TOP)/ext/fts2/fts2_icu.c \ - $(TOP)/ext/fts2/fts2_porter.c \ - $(TOP)/ext/fts2/fts2_tokenizer.h \ - $(TOP)/ext/fts2/fts2_tokenizer.c \ - $(TOP)/ext/fts2/fts2_tokenizer1.c -SRC += \ - $(TOP)/ext/fts3/fts3.c \ - $(TOP)/ext/fts3/fts3.h \ - $(TOP)/ext/fts3/fts3_expr.c \ - $(TOP)/ext/fts3/fts3_expr.h \ - $(TOP)/ext/fts3/fts3_hash.c \ - $(TOP)/ext/fts3/fts3_hash.h \ - $(TOP)/ext/fts3/fts3_icu.c \ - $(TOP)/ext/fts3/fts3_porter.c \ - $(TOP)/ext/fts3/fts3_tokenizer.h \ - $(TOP)/ext/fts3/fts3_tokenizer.c \ - $(TOP)/ext/fts3/fts3_tokenizer1.c -SRC += \ - $(TOP)/ext/icu/sqliteicu.h \ - $(TOP)/ext/icu/icu.c -SRC += \ - $(TOP)/ext/rtree/rtree.h \ - $(TOP)/ext/rtree/rtree.c - - -# Generated source code files -# -SRC += \ - keywordhash.h \ - opcodes.c \ - opcodes.h \ - parse.c \ - parse.h \ - sqlite3.h - - -# Source code to the test files. -# -TESTSRC = \ - $(TOP)/src/test1.c \ - $(TOP)/src/test2.c \ - $(TOP)/src/test3.c \ - $(TOP)/src/test4.c \ - $(TOP)/src/test5.c \ - $(TOP)/src/test6.c \ - $(TOP)/src/test7.c \ - $(TOP)/src/test8.c \ - $(TOP)/src/test9.c \ - $(TOP)/src/test_autoext.c \ - $(TOP)/src/test_async.c \ - $(TOP)/src/test_backup.c \ - $(TOP)/src/test_btree.c \ - $(TOP)/src/test_config.c \ - $(TOP)/src/test_devsym.c \ - $(TOP)/src/test_func.c \ - $(TOP)/src/test_hexio.c \ - $(TOP)/src/test_journal.c \ - $(TOP)/src/test_malloc.c \ - $(TOP)/src/test_md5.c \ - $(TOP)/src/test_mutex.c \ - $(TOP)/src/test_onefile.c \ - $(TOP)/src/test_osinst.c \ - $(TOP)/src/test_pcache.c \ - $(TOP)/src/test_schema.c \ - $(TOP)/src/test_server.c \ - $(TOP)/src/test_tclvar.c \ - $(TOP)/src/test_thread.c \ - $(TOP)/src/test_vfs.c \ - $(TOP)/src/test_wsd.c \ - -#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c -#TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c - -TESTSRC2 = \ - $(TOP)/src/attach.c $(TOP)/src/backup.c $(TOP)/src/btree.c \ - $(TOP)/src/build.c $(TOP)/src/ctime.c $(TOP)/src/date.c \ - $(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \ - $(TOP)/src/os_unix.c $(TOP)/src/os_win.c \ - $(TOP)/src/pager.c $(TOP)/src/pragma.c $(TOP)/src/prepare.c \ - $(TOP)/src/printf.c $(TOP)/src/random.c $(TOP)/src/pcache.c \ - $(TOP)/src/pcache1.c $(TOP)/src/select.c $(TOP)/src/tokenize.c \ - $(TOP)/src/utf.c $(TOP)/src/util.c $(TOP)/src/vdbeapi.c $(TOP)/src/vdbeaux.c \ - $(TOP)/src/vdbe.c $(TOP)/src/vdbemem.c $(TOP)/src/where.c parse.c \ - $(TOP)/ext/fts3/fts3.c $(TOP)/ext/fts3/fts3_expr.c \ - $(TOP)/ext/fts3/fts3_tokenizer.c \ - $(TOP)/ext/async/sqlite3async.c - -# Header files used by all library source files. -# -HDR = \ - $(TOP)/src/btree.h \ - $(TOP)/src/btreeInt.h \ - $(TOP)/src/hash.h \ - $(TOP)/src/hwtime.h \ - keywordhash.h \ - $(TOP)/src/msvc.h \ - $(TOP)/src/mutex.h \ - opcodes.h \ - $(TOP)/src/os.h \ - $(TOP)/src/os_common.h \ - $(TOP)/src/os_setup.h \ - $(TOP)/src/os_win.h \ - $(TOP)/src/pager.h \ - $(TOP)/src/pcache.h \ - parse.h \ - sqlite3.h \ - $(TOP)/src/sqlite3ext.h \ - $(TOP)/src/sqliteInt.h \ - $(TOP)/src/sqliteLimit.h \ - $(TOP)/src/vdbe.h \ - $(TOP)/src/vdbeInt.h - -# Header files used by extensions -# -EXTHDR += \ - $(TOP)/ext/fts1/fts1.h \ - $(TOP)/ext/fts1/fts1_hash.h \ - $(TOP)/ext/fts1/fts1_tokenizer.h -EXTHDR += \ - $(TOP)/ext/fts2/fts2.h \ - $(TOP)/ext/fts2/fts2_hash.h \ - $(TOP)/ext/fts2/fts2_tokenizer.h -EXTHDR += \ - $(TOP)/ext/fts3/fts3.h \ - $(TOP)/ext/fts3/fts3_expr.h \ - $(TOP)/ext/fts3/fts3_hash.h \ - $(TOP)/ext/fts3/fts3_tokenizer.h -EXTHDR += \ - $(TOP)/ext/rtree/rtree.h -EXTHDR += \ - $(TOP)/ext/icu/sqliteicu.h - -# This is the default Makefile target. The objects listed here -# are what get build when you type just "make" with no arguments. -# -all: sqlite3.h libsqlite3.a sqlite3$(EXE) - -libsqlite3.a: $(LIBOBJ) - $(AR) libsqlite3.a $(LIBOBJ) - $(RANLIB) libsqlite3.a - -$(SHPREFIX)sqlite3.$(SO): $(LIBOBJ) - $(MKSHLIB) -o $(SHPREFIX)sqlite3.$(SO) $(LIBOBJ) $(TLIBS_SHARED) - -sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h - $(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) \ - $(TOP)/src/shell.c \ - $(LIBREADLINE) $(TLIBS) $(THREADLIB) -L. -lsqlite3 - -# This target creates a directory named "tsrc" and fills it with -# copies of all of the C source code and header files needed to -# build on the target system. Some of the C source code and header -# files are automatically generated. This target takes care of -# all that automatic generation. -# -target_source: $(SRC) - rm -rf tsrc - mkdir tsrc - cp -f $(SRC) tsrc - rm tsrc/sqlite.h.in tsrc/parse.y - touch target_source - -sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl - tclsh $(TOP)/tool/mksqlite3c.tcl - cp sqlite3.c tclsqlite3.c - cat $(TOP)/src/tclsqlite.c >>tclsqlite3.c - -fts2amal.c: target_source $(TOP)/ext/fts2/mkfts2amal.tcl - tclsh $(TOP)/ext/fts2/mkfts2amal.tcl - -fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl - tclsh $(TOP)/ext/fts3/mkfts3amal.tcl - -# Rules to build the LEMON compiler generator -# -lemon: $(TOP)/tool/lemon.c $(TOP)/src/lempar.c - $(BCC) -o lemon $(TOP)/tool/lemon.c - cp $(TOP)/src/lempar.c . - -# Rules to build individual *.o files from generated *.c files. This -# applies to: -# -# parse.o -# opcodes.o -# -%.o: %.c $(HDR) - $(TCCX_SHARED) -c $< - -# Rules to build individual *.o files from files in the src directory. -# -%.o: $(TOP)/src/%.c $(HDR) - $(TCCX_SHARED) -c $< - -tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR) - $(TCCX_SHARED) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c - - - -# Rules to build opcodes.c and opcodes.h -# -opcodes.c: opcodes.h $(TOP)/mkopcodec.awk - $(NAWK) -f $(TOP)/mkopcodec.awk opcodes.h >opcodes.c - -opcodes.h: parse.h $(TOP)/src/vdbe.c $(TOP)/mkopcodeh.awk - cat parse.h $(TOP)/src/vdbe.c | \ - $(NAWK) -f $(TOP)/mkopcodeh.awk >opcodes.h - -# Rules to build parse.c and parse.h - the outputs of lemon. -# -parse.h: parse.c - -parse.c: $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk - cp $(TOP)/src/parse.y . - rm -f parse.h - ./lemon $(OPTS) parse.y - mv parse.h parse.h.temp - awk -f $(TOP)/addopcodes.awk parse.h.temp >parse.h - -sqlite3.h: $(TOP)/src/sqlite.h.in - sed -e s/--VERS--/`cat ${TOP}/VERSION`/ \ - -e s/--VERSION-NUMBER--/`cat ${TOP}/VERSION | sed 's/[^0-9]/ /g' | $(NAWK) '{printf "%d%03d%03d",$$1,$$2,$$3}'`/ \ - $(TOP)/src/sqlite.h.in >sqlite3.h - -keywordhash.h: $(TOP)/tool/mkkeywordhash.c - $(BCC) -o mkkeywordhash $(OPTS) $(TOP)/tool/mkkeywordhash.c - ./mkkeywordhash >keywordhash.h - - - -# Rules to build the extension objects. -# -icu.o: $(TOP)/ext/icu/icu.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/icu/icu.c - -fts2.o: $(TOP)/ext/fts2/fts2.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2.c - -fts2_hash.o: $(TOP)/ext/fts2/fts2_hash.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_hash.c - -fts2_icu.o: $(TOP)/ext/fts2/fts2_icu.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_icu.c - -fts2_porter.o: $(TOP)/ext/fts2/fts2_porter.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_porter.c - -fts2_tokenizer.o: $(TOP)/ext/fts2/fts2_tokenizer.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer.c - -fts2_tokenizer1.o: $(TOP)/ext/fts2/fts2_tokenizer1.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer1.c - -fts3.o: $(TOP)/ext/fts3/fts3.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3.c - -fts3_expr.o: $(TOP)/ext/fts3/fts3_expr.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_expr.c - -fts3_hash.o: $(TOP)/ext/fts3/fts3_hash.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_hash.c - -fts3_icu.o: $(TOP)/ext/fts3/fts3_icu.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_icu.c - -fts3_porter.o: $(TOP)/ext/fts3/fts3_porter.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c - -fts3_tokenizer.o: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c - -fts3_tokenizer1.o: $(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c - -rtree.o: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR) - $(TCCX_SHARED) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c - - -# Rules for building test programs and for running tests -# -tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a - $(TCCX_SHARED) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \ - $(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB) - - -# Rules to build the 'testfixture' application. -# -TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 -TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE - -testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c - $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \ - $(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \ - -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) libsqlite3.a - -amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c - $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \ - $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \ - -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) - -fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c - $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \ - -DSQLITE_ENABLE_FTS3=1 \ - $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \ - -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) - -fulltest: testfixture$(EXE) sqlite3$(EXE) - ./testfixture$(EXE) $(TOP)/test/all.test - -soaktest: testfixture$(EXE) sqlite3$(EXE) - ./testfixture$(EXE) $(TOP)/test/all.test -soak=1 - -fulltestonly: testfixture$(EXE) sqlite3$(EXE) - ./testfixture$(EXE) $(TOP)/test/full.test - -test: testfixture$(EXE) sqlite3$(EXE) - ./testfixture$(EXE) $(TOP)/test/veryquick.test - -sqlite3_analyzer$(EXE): $(TOP)/src/tclsqlite.c sqlite3.c $(TESTSRC) \ - $(TOP)/tool/spaceanal.tcl - sed \ - -e '/^#/d' \ - -e 's,\\,\\\\,g' \ - -e 's,",\\",g' \ - -e 's,^,",' \ - -e 's,$$,\\n",' \ - $(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h - $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \ - -DTCLSH=2 -DSQLITE_TEST=1 -DSQLITE_DEBUG=1 -DSQLITE_PRIVATE="" \ - $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \ - -o sqlite3_analyzer$(EXE) \ - $(LIBTCL) $(THREADLIB) - -TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO) -$(TEST_EXTENSION): $(TOP)/src/test_loadext.c - $(MKSHLIB) $(TOP)/src/test_loadext.c -o $(TEST_EXTENSION) - -extensiontest: testfixture$(EXE) $(TEST_EXTENSION) - ./testfixture$(EXE) $(TOP)/test/loadext.test - -clean: - rm -f *.o sqlite3$(EXE) libsqlite3.a sqlite3.h opcodes.* - rm -f lemon lempar.c parse.* sqlite*.tar.gz mkkeywordhash keywordhash.h - rm -f $(PUBLISH) - rm -f *.da *.bb *.bbg gmon.out - rm -rf quota2a quota2b quota2c - rm -rf tsrc target_source - rm -f testloadext.dll libtestloadext.so - rm -f sqlite3.c fts?amal.c tclsqlite3.c - rm -f sqlite3rc.h - rm -f shell.c sqlite3ext.h - rm -f $(SHPREFIX)sqlite3.$(SO) diff --git a/README.md b/README.md index ff8dc34..dbc0205 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,10 @@ This repository contains the complete source code for the SQLite database engine. Some test scripts are also include. However, many other test scripts and most of the documentation are managed separately. +If you are reading this on a Git mirror someplace, you are doing it wrong. +The [official repository](https://www.sqlite.org/src/) is better. Go there +now. + ## Compiling First create a directory in which to place @@ -174,7 +178,7 @@ complex code. So there is a lot of complexity in the SQLite implementation. Key files: - * **sqlite3.h** - This file defines the public interface to the SQLite + * **sqlite.h.in** - This file defines the public interface to the SQLite library. Readers will need to be familiar with this interface before trying to understand how the library works internally. @@ -182,7 +186,7 @@ Key files: used internally by SQLite. * **parse.y** - This file describes the LALR(1) grammer that SQLite uses - to parse SQL statements, and the actions that are taken at each stop + to parse SQL statements, and the actions that are taken at each step in the parsing process. * **vdbe.c** - This file implements the virtual machine that runs @@ -206,6 +210,17 @@ Key files: between SQLite and the underlying operating system using the run-time pluggable VFS interface. + * **shell.c** - This file is not part of the core SQLite library. This + is the file that, when linked against sqlite3.a, generates the + "sqlite3.exe" command-line shell. + + * **tclsqlite.c** - This file implements the Tcl bindings for SQLite. It + is not part of the core SQLite library. But as most of the tests in this + repository are written in Tcl, the Tcl language bindings are important. + +There are many other source files. Each has a suscinct header comment that +describes its purpose and role within the larger system. + ## Contacts diff --git a/VERSION b/VERSION index ff280e4..afad818 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.8.10.2 +3.11.0 diff --git a/addopcodes.awk b/addopcodes.awk deleted file mode 100644 index dcd31ef..0000000 --- a/addopcodes.awk +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/awk -# -# This script appends additional token codes to the end of the -# parse.h file that lemon generates. These extra token codes are -# not used by the parser. But they are used by the tokenizer and/or -# the code generator. -# -# -BEGIN { - max = 0 -} -/^#define TK_/ { - print $0 - if( max<$3 ) max = $3 -} -END { - printf "#define TK_%-29s %4d\n", "TO_TEXT", ++max - printf "#define TK_%-29s %4d\n", "TO_BLOB", ++max - printf "#define TK_%-29s %4d\n", "TO_NUMERIC", ++max - printf "#define TK_%-29s %4d\n", "TO_INT", ++max - printf "#define TK_%-29s %4d\n", "TO_REAL", ++max - printf "#define TK_%-29s %4d\n", "ISNOT", ++max - printf "#define TK_%-29s %4d\n", "END_OF_FILE", ++max - printf "#define TK_%-29s %4d\n", "ILLEGAL", ++max - printf "#define TK_%-29s %4d\n", "SPACE", ++max - printf "#define TK_%-29s %4d\n", "UNCLOSED_STRING", ++max - printf "#define TK_%-29s %4d\n", "FUNCTION", ++max - printf "#define TK_%-29s %4d\n", "COLUMN", ++max - printf "#define TK_%-29s %4d\n", "AGG_FUNCTION", ++max - printf "#define TK_%-29s %4d\n", "AGG_COLUMN", ++max - printf "#define TK_%-29s %4d\n", "UMINUS", ++max - printf "#define TK_%-29s %4d\n", "UPLUS", ++max - printf "#define TK_%-29s %4d\n", "REGISTER", ++max -} diff --git a/autoconf/Makefile.am b/autoconf/Makefile.am index 88bc23d..0e09cfc 100644 --- a/autoconf/Makefile.am +++ b/autoconf/Makefile.am @@ -1,17 +1,19 @@ -AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE +AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE lib_LTLIBRARIES = libsqlite3.la libsqlite3_la_SOURCES = sqlite3.c libsqlite3_la_LDFLAGS = -no-undefined -version-info 8:6:8 bin_PROGRAMS = sqlite3 -sqlite3_SOURCES = shell.c sqlite3.h -sqlite3_LDADD = sqlite3.$(OBJEXT) @READLINE_LIBS@ +sqlite3_SOURCES = shell.c sqlite3.c sqlite3.h +sqlite3_LDADD = @READLINE_LIBS@ +sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@ +sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS include_HEADERS = sqlite3.h sqlite3ext.h -EXTRA_DIST = sqlite3.1 tea +EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt pkgconfigdir = ${libdir}/pkgconfig pkgconfig_DATA = sqlite3.pc diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc new file mode 100644 index 0000000..0be42b4 --- /dev/null +++ b/autoconf/Makefile.msc @@ -0,0 +1,921 @@ +#### DO NOT EDIT #### +# This makefile is automatically generated from the Makefile.msc at +# the root of the canonical SQLite source tree (not the +# amalgamation tarball) using the tool/mkmsvcmin.tcl +# script. +# + +# +# nmake Makefile for SQLite +# +############################################################################### +############################## START OF OPTIONS ############################### +############################################################################### + +# The toplevel directory of the source tree. This is the directory +# that contains this "Makefile.msc". +# +TOP = . + + +# Set this non-0 to enable full warnings (-W4, etc) when compiling. +# +!IFNDEF USE_FULLWARN +USE_FULLWARN = 0 +!ENDIF + +# Set this non-0 to use "stdcall" calling convention for the core library +# and shell executable. +# +!IFNDEF USE_STDCALL +USE_STDCALL = 0 +!ENDIF + +# Set this non-0 to have the shell executable link against the core dynamic +# link library. +# +!IFNDEF DYNAMIC_SHELL +DYNAMIC_SHELL = 0 +!ENDIF + +# Set this non-0 to enable extra code that attempts to detect misuse of the +# SQLite API. +# +!IFNDEF API_ARMOR +API_ARMOR = 0 +!ENDIF + +# If necessary, create a list of harmless compiler warnings to disable when +# compiling the various tools. For the SQLite source code itself, warnings, +# if any, will be disabled from within it. +# +!IFNDEF NO_WARN +!IF $(USE_FULLWARN)!=0 +NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206 +NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706 +!ENDIF +!ENDIF + +# Set this non-0 to use the library paths and other options necessary for +# Windows Phone 8.1. +# +!IFNDEF USE_WP81_OPTS +USE_WP81_OPTS = 0 +!ENDIF + +# Set this non-0 to split the SQLite amalgamation file into chunks to +# be used for debugging with Visual Studio. +# +!IFNDEF SPLIT_AMALGAMATION +SPLIT_AMALGAMATION = 0 +!ENDIF + + +# Set this non-0 to dynamically link to the MSVC runtime library. +# +!IFNDEF USE_CRT_DLL +USE_CRT_DLL = 0 +!ENDIF + +# Set this non-0 to link to the RPCRT4 library. +# +!IFNDEF USE_RPCRT4_LIB +USE_RPCRT4_LIB = 0 +!ENDIF + +# Set this non-0 to generate assembly code listings for the source code +# files. +# +!IFNDEF USE_LISTINGS +USE_LISTINGS = 0 +!ENDIF + +# Set this non-0 to attempt setting the native compiler automatically +# for cross-compiling the command line tools needed during the compilation +# process. +# +!IFNDEF XCOMPILE +XCOMPILE = 0 +!ENDIF + +# Set this non-0 to use the native libraries paths for cross-compiling +# the command line tools needed during the compilation process. +# +!IFNDEF USE_NATIVE_LIBPATHS +USE_NATIVE_LIBPATHS = 0 +!ENDIF + +# Set this 0 to skip the compiling and embedding of version resources. +# +!IFNDEF USE_RC +USE_RC = 1 +!ENDIF + +# Set this non-0 to compile binaries suitable for the WinRT environment. +# This setting does not apply to any binaries that require Tcl to operate +# properly (i.e. the text fixture, etc). +# +!IFNDEF FOR_WINRT +FOR_WINRT = 0 +!ENDIF + +# Set this non-0 to compile binaries suitable for the UWP environment. +# This setting does not apply to any binaries that require Tcl to operate +# properly (i.e. the text fixture, etc). +# +!IFNDEF FOR_UWP +FOR_UWP = 0 +!ENDIF + +# Set this non-0 to compile binaries suitable for the Windows 10 platform. +# +!IFNDEF FOR_WIN10 +FOR_WIN10 = 0 +!ENDIF + + +# Set this to non-0 to create and use PDBs. +# +!IFNDEF SYMBOLS +SYMBOLS = 1 +!ENDIF + +# Set this to non-0 to use the SQLite debugging heap subsystem. +# +!IFNDEF MEMDEBUG +MEMDEBUG = 0 +!ENDIF + +# Set this to non-0 to use the Win32 native heap subsystem. +# +!IFNDEF WIN32HEAP +WIN32HEAP = 0 +!ENDIF + +# Set this to non-0 to enable OSTRACE() macros, which can be useful when +# debugging. +# +!IFNDEF OSTRACE +OSTRACE = 0 +!ENDIF + +# Set this to one of the following values to enable various debugging +# features. Each level includes the debugging options from the previous +# levels. Currently, the recognized values for DEBUG are: +# +# 0 == NDEBUG: Disables assert() and other runtime diagnostics. +# 1 == SQLITE_ENABLE_API_ARMOR: extra attempts to detect misuse of the API. +# 2 == Disables NDEBUG and all optimizations and then enables PDBs. +# 3 == SQLITE_DEBUG: Enables various diagnostics messages and code. +# 4 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call. +# 5 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros. +# 6 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros. +# +!IFNDEF DEBUG +DEBUG = 0 +!ENDIF + +# Enable use of available compiler optimizations? Normally, this should be +# non-zero. Setting this to zero, thus disabling all compiler optimizations, +# can be useful for testing. +# +!IFNDEF OPTIMIZATIONS +OPTIMIZATIONS = 2 +!ENDIF + +# Set the source code file to be used by executables and libraries when +# they need the amalgamation. +# +!IFNDEF SQLITE3C +!IF $(SPLIT_AMALGAMATION)!=0 +SQLITE3C = sqlite3-all.c +!ELSE +SQLITE3C = sqlite3.c +!ENDIF +!ENDIF + +# Set the include code file to be used by executables and libraries when +# they need SQLite. +# +!IFNDEF SQLITE3H +SQLITE3H = sqlite3.h +!ENDIF + +# This is the name to use for the SQLite dynamic link library (DLL). +# +!IFNDEF SQLITE3DLL +SQLITE3DLL = sqlite3.dll +!ENDIF + +# This is the name to use for the SQLite import library (LIB). +# +!IFNDEF SQLITE3LIB +SQLITE3LIB = sqlite3.lib +!ENDIF + +# This is the name to use for the SQLite shell executable (EXE). +# +!IFNDEF SQLITE3EXE +SQLITE3EXE = sqlite3.exe +!ENDIF + +# This is the argument used to set the program database (PDB) file for the +# SQLite shell executable (EXE). +# +!IFNDEF SQLITE3EXEPDB +SQLITE3EXEPDB = /pdb:sqlite3sh.pdb +!ENDIF + +# These are the "standard" SQLite compilation options used when compiling for +# the Windows platform. +# +!IFNDEF OPT_FEATURE_FLAGS +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 +!ENDIF + +# These are the "extended" SQLite compilation options used when compiling for +# the Windows 10 platform. +# +!IFNDEF EXT_FEATURE_FLAGS +!IF $(FOR_WIN10)!=0 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4=1 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_SYSTEM_MALLOC=1 +EXT_FEATURE_FLAGS = $(EXT_FEATURE_FLAGS) -DSQLITE_OMIT_LOCALTIME=1 +!ELSE +EXT_FEATURE_FLAGS = +!ENDIF +!ENDIF + +############################################################################### +############################### END OF OPTIONS ################################ +############################################################################### + +# When compiling for the Windows 10 platform, the PLATFORM macro must be set +# to an appropriate value (e.g. x86, x64, arm, arm64, etc). +# +!IF $(FOR_WIN10)!=0 +!IFNDEF PLATFORM +!ERROR Using the FOR_WIN10 option requires a value for PLATFORM. +!ENDIF +!ENDIF + +# This assumes that MSVC is always installed in 32-bit Program Files directory +# and sets the variable for use in locating other 32-bit installs accordingly. +# +PROGRAMFILES_X86 = $(VCINSTALLDIR)\..\.. +PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\) + +# Check for the predefined command macro CC. This should point to the compiler +# binary for the target platform. If it is not defined, simply define it to +# the legacy default value 'cl.exe'. +# +!IFNDEF CC +CC = cl.exe +!ENDIF + +# Check for the command macro LD. This should point to the linker binary for +# the target platform. If it is not defined, simply define it to the legacy +# default value 'link.exe'. +# +!IFNDEF LD +LD = link.exe +!ENDIF + +# Check for the predefined command macro RC. This should point to the resource +# compiler binary for the target platform. If it is not defined, simply define +# it to the legacy default value 'rc.exe'. +# +!IFNDEF RC +RC = rc.exe +!ENDIF + +# Check for the MSVC runtime library path macro. Otherwise, this value will +# default to the 'lib' directory underneath the MSVC installation directory. +# +!IFNDEF CRTLIBPATH +CRTLIBPATH = $(VCINSTALLDIR)\lib +!ENDIF + +CRTLIBPATH = $(CRTLIBPATH:\\=\) + +# Check for the command macro NCC. This should point to the compiler binary +# for the platform the compilation process is taking place on. If it is not +# defined, simply define it to have the same value as the CC macro. When +# cross-compiling, it is suggested that this macro be modified via the command +# line (since nmake itself does not provide a built-in method to guess it). +# For example, to use the x86 compiler when cross-compiling for x64, a command +# line similar to the following could be used (all on one line): +# +# nmake /f Makefile.msc sqlite3.dll +# XCOMPILE=1 USE_NATIVE_LIBPATHS=1 +# +# Alternatively, the full path and file name to the compiler binary for the +# platform the compilation process is taking place may be specified (all on +# one line): +# +# nmake /f Makefile.msc sqlite3.dll +# "NCC=""%VCINSTALLDIR%\bin\cl.exe""" +# USE_NATIVE_LIBPATHS=1 +# +!IFDEF NCC +NCC = $(NCC:\\=\) +!ELSEIF $(XCOMPILE)!=0 +NCC = "$(VCINSTALLDIR)\bin\$(CC)" +NCC = $(NCC:\\=\) +!ELSE +NCC = $(CC) +!ENDIF + +# Check for the MSVC native runtime library path macro. Otherwise, +# this value will default to the 'lib' directory underneath the MSVC +# installation directory. +# +!IFNDEF NCRTLIBPATH +NCRTLIBPATH = $(VCINSTALLDIR)\lib +!ENDIF + +NCRTLIBPATH = $(NCRTLIBPATH:\\=\) + +# Check for the Platform SDK library path macro. Otherwise, this +# value will default to the 'lib' directory underneath the Windows +# SDK installation directory (the environment variable used appears +# to be available when using Visual C++ 2008 or later via the +# command line). +# +!IFNDEF NSDKLIBPATH +NSDKLIBPATH = $(WINDOWSSDKDIR)\lib +!ENDIF + +NSDKLIBPATH = $(NSDKLIBPATH:\\=\) + +# Check for the UCRT library path macro. Otherwise, this value will +# default to the version-specific, platform-specific 'lib' directory +# underneath the Windows SDK installation directory. +# +!IFNDEF UCRTLIBPATH +UCRTLIBPATH = $(WINDOWSSDKDIR)\lib\$(WINDOWSSDKLIBVERSION)\ucrt\$(PLATFORM) +!ENDIF + +UCRTLIBPATH = $(UCRTLIBPATH:\\=\) + +# C compiler and options for use in building executables that +# will run on the platform that is doing the build. +# +!IF $(USE_FULLWARN)!=0 +BCC = $(NCC) -nologo -W4 $(CCOPTS) $(BCCOPTS) +!ELSE +BCC = $(NCC) -nologo -W3 $(CCOPTS) $(BCCOPTS) +!ENDIF + +# Check if assembly code listings should be generated for the source +# code files to be compiled. +# +!IF $(USE_LISTINGS)!=0 +BCC = $(BCC) -FAcs +!ENDIF + +# Check if the native library paths should be used when compiling +# the command line tools used during the compilation process. If +# so, set the necessary macro now. +# +!IF $(USE_NATIVE_LIBPATHS)!=0 +NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)" + +!IFDEF NUCRTLIBPATH +NUCRTLIBPATH = $(NUCRTLIBPATH:\\=\) +NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)" +!ENDIF +!ENDIF + +# C compiler and options for use in building executables that +# will run on the target platform. (BCC and TCC are usually the +# same unless your are cross-compiling.) +# +!IF $(USE_FULLWARN)!=0 +TCC = $(CC) -nologo -W4 -DINCLUDE_MSVC_H=1 $(CCOPTS) $(TCCOPTS) +!ELSE +TCC = $(CC) -nologo -W3 $(CCOPTS) $(TCCOPTS) +!ENDIF + +TCC = $(TCC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -fp:precise +RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS) + +# Adjust the names of the primary targets for use with Windows 10. +# +!IF $(FOR_WIN10)!=0 +SQLITE3DLL = winsqlite3.dll +SQLITE3LIB = winsqlite3.lib +SQLITE3EXE = winsqlite3shell.exe +SQLITE3EXEPDB = +!ENDIF + +# Check if we want to use the "stdcall" calling convention when compiling. +# This is not supported by the compilers for non-x86 platforms. It should +# also be noted here that building any target with these "stdcall" options +# will most likely fail if the Tcl library is also required. This is due +# to how the Tcl library functions are declared and exported (i.e. without +# an explicit calling convention, which results in "cdecl"). +# +!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0 +!IF "$(PLATFORM)"=="x86" +CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +!ELSE +!IFNDEF PLATFORM +CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall +!ELSE +CORE_CCONV_OPTS = +SHELL_CCONV_OPTS = +!ENDIF +!ENDIF +!ELSE +CORE_CCONV_OPTS = +SHELL_CCONV_OPTS = +!ENDIF + +# These are additional compiler options used for the core library. +# +!IFNDEF CORE_COMPILE_OPTS +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) -DSQLITE_API=__declspec(dllexport) +!ELSE +CORE_COMPILE_OPTS = $(CORE_CCONV_OPTS) +!ENDIF +!ENDIF + +# These are the additional targets that the core library should depend on +# when linking. +# +!IFNDEF CORE_LINK_DEP +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +CORE_LINK_DEP = +!ELSE +CORE_LINK_DEP = +!ENDIF +!ENDIF + +# These are additional linker options used for the core library. +# +!IFNDEF CORE_LINK_OPTS +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +CORE_LINK_OPTS = +!ELSE +CORE_LINK_OPTS = +!ENDIF +!ENDIF + +# These are additional compiler options used for the shell executable. +# +!IFNDEF SHELL_COMPILE_OPTS +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) -DSQLITE_API=__declspec(dllimport) +!ELSE +SHELL_COMPILE_OPTS = $(SHELL_CCONV_OPTS) +!ENDIF +!ENDIF + +# This is the source code that the shell executable should be compiled +# with. +# +!IFNDEF SHELL_CORE_SRC +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_SRC = +!ELSE +SHELL_CORE_SRC = $(SQLITE3C) +!ENDIF +!ENDIF + +# This is the core library that the shell executable should depend on. +# +!IFNDEF SHELL_CORE_DEP +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_DEP = $(SQLITE3DLL) +!ELSE +SHELL_CORE_DEP = +!ENDIF +!ENDIF + +# This is the core library that the shell executable should link with. +# +!IFNDEF SHELL_CORE_LIB +!IF $(DYNAMIC_SHELL)!=0 || $(FOR_WIN10)!=0 +SHELL_CORE_LIB = $(SQLITE3LIB) +!ELSE +SHELL_CORE_LIB = +!ENDIF +!ENDIF + +# These are additional linker options used for the shell executable. +# +!IFNDEF SHELL_LINK_OPTS +SHELL_LINK_OPTS = $(SHELL_CORE_LIB) +!ENDIF + +# Check if assembly code listings should be generated for the source +# code files to be compiled. +# +!IF $(USE_LISTINGS)!=0 +TCC = $(TCC) -FAcs +!ENDIF + +# When compiling the library for use in the WinRT environment, +# the following compile-time options must be used as well to +# disable use of Win32 APIs that are not available and to enable +# use of Win32 APIs that are specific to Windows 8 and/or WinRT. +# +!IF $(FOR_WINRT)!=0 +TCC = $(TCC) -DSQLITE_OS_WINRT=1 +RCC = $(RCC) -DSQLITE_OS_WINRT=1 +TCC = $(TCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP +RCC = $(RCC) -DWINAPI_FAMILY=WINAPI_FAMILY_APP +!ENDIF + +# C compiler options for the Windows 10 platform (needs MSVC 2015). +# +!IF $(FOR_WIN10)!=0 +TCC = $(TCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +BCC = $(BCC) /d2guard4 -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE +!ENDIF + +# Also, we need to dynamically link to the correct MSVC runtime +# when compiling for WinRT (e.g. debug or release) OR if the +# USE_CRT_DLL option is set to force dynamically linking to the +# MSVC runtime library. +# +!IF $(FOR_WINRT)!=0 || $(USE_CRT_DLL)!=0 +!IF $(DEBUG)>1 +TCC = $(TCC) -MDd +BCC = $(BCC) -MDd +!ELSE +TCC = $(TCC) -MD +BCC = $(BCC) -MD +!ENDIF +!ELSE +!IF $(DEBUG)>1 +TCC = $(TCC) -MTd +BCC = $(BCC) -MTd +!ELSE +TCC = $(TCC) -MT +BCC = $(BCC) -MT +!ENDIF +!ENDIF + + +# Define -DNDEBUG to compile without debugging (i.e., for production usage) +# Omitting the define will cause extra debugging code to be inserted and +# includes extra comments when "EXPLAIN stmt" is used. +# +!IF $(DEBUG)==0 +TCC = $(TCC) -DNDEBUG +BCC = $(BCC) -DNDEBUG +RCC = $(RCC) -DNDEBUG +!ENDIF + +!IF $(DEBUG)>0 || $(API_ARMOR)!=0 || $(FOR_WIN10)!=0 +TCC = $(TCC) -DSQLITE_ENABLE_API_ARMOR=1 +RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1 +!ENDIF + +!IF $(DEBUG)>2 +TCC = $(TCC) -DSQLITE_DEBUG=1 +RCC = $(RCC) -DSQLITE_DEBUG=1 +!ENDIF + +!IF $(DEBUG)>4 || $(OSTRACE)!=0 +TCC = $(TCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1 +RCC = $(RCC) -DSQLITE_FORCE_OS_TRACE=1 -DSQLITE_DEBUG_OS_TRACE=1 +!ENDIF + +!IF $(DEBUG)>5 +TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE=1 +RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE=1 +!ENDIF + +# Prevent warnings about "insecure" MSVC runtime library functions +# being used. +# +TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS +BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS +RCC = $(RCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS + +# Prevent warnings about "deprecated" POSIX functions being used. +# +TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS +BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS +RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS + +# Use the SQLite debugging heap subsystem? +# +!IF $(MEMDEBUG)!=0 +TCC = $(TCC) -DSQLITE_MEMDEBUG=1 +RCC = $(RCC) -DSQLITE_MEMDEBUG=1 + +# Use native Win32 heap subsystem instead of malloc/free? +# +!ELSEIF $(WIN32HEAP)!=0 +TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1 +RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1 + +# Validate the heap on every call into the native Win32 heap subsystem? +# +!IF $(DEBUG)>3 +TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 +RCC = $(RCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1 +!ENDIF +!ENDIF + + +# Compiler options needed for programs that use the readline() library. +# +!IFNDEF READLINE_FLAGS +READLINE_FLAGS = -DHAVE_READLINE=0 +!ENDIF + +# The library that programs using readline() must link against. +# +!IFNDEF LIBREADLINE +LIBREADLINE = +!ENDIF + +# Should the database engine be compiled threadsafe +# +TCC = $(TCC) -DSQLITE_THREADSAFE=1 +RCC = $(RCC) -DSQLITE_THREADSAFE=1 + +# Do threads override each others locks by default (1), or do we test (-1) +# +TCC = $(TCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1 +RCC = $(RCC) -DSQLITE_THREAD_OVERRIDE_LOCK=-1 + +# Any target libraries which libsqlite must be linked against +# +!IFNDEF TLIBS +TLIBS = +!ENDIF + +# Flags controlling use of the in memory btree implementation +# +# SQLITE_TEMP_STORE is 0 to force temporary tables to be in a file, 1 to +# default to file, 2 to default to memory, and 3 to force temporary +# tables to always be in memory. +# +TCC = $(TCC) -DSQLITE_TEMP_STORE=1 +RCC = $(RCC) -DSQLITE_TEMP_STORE=1 + +# Enable/disable loadable extensions, and other optional features +# based on configuration. (-DSQLITE_OMIT*, -DSQLITE_ENABLE*). +# The same set of OMIT and ENABLE flags should be passed to the +# LEMON parser generator and the mkkeywordhash tool as well. + +# These are the required SQLite compilation options used when compiling for +# the Windows platform. +# +REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100 + +# If we are linking to the RPCRT4 library, enable features that need it. +# +!IF $(USE_RPCRT4_LIB)!=0 +REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_WIN32_USE_UUID=1 +!ENDIF + +# Add the required and optional SQLite compilation options into the command +# lines used to invoke the MSVC code and resource compilers. +# +TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) +RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) + +# Add in any optional parameters specified on the commane line, e.g. +# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1" +# +TCC = $(TCC) $(OPTS) +RCC = $(RCC) $(OPTS) + +# If compiling for debugging, add some defines. +# +!IF $(DEBUG)>1 +TCC = $(TCC) -D_DEBUG +BCC = $(BCC) -D_DEBUG +RCC = $(RCC) -D_DEBUG +!ENDIF + +# If optimizations are enabled or disabled (either implicitly or +# explicitly), add the necessary flags. +# +!IF $(DEBUG)>1 || $(OPTIMIZATIONS)==0 +TCC = $(TCC) -Od +BCC = $(BCC) -Od +!ELSEIF $(OPTIMIZATIONS)>=3 +TCC = $(TCC) -Ox +BCC = $(BCC) -Ox +!ELSEIF $(OPTIMIZATIONS)==2 +TCC = $(TCC) -O2 +BCC = $(BCC) -O2 +!ELSEIF $(OPTIMIZATIONS)==1 +TCC = $(TCC) -O1 +BCC = $(BCC) -O1 +!ENDIF + +# If symbols are enabled (or compiling for debugging), enable PDBs. +# +!IF $(DEBUG)>1 || $(SYMBOLS)!=0 +TCC = $(TCC) -Zi +BCC = $(BCC) -Zi +!ENDIF + + +# Command line prefixes for compiling code, compiling resources, +# linking, etc. +# +LTCOMPILE = $(TCC) -Fo$@ +LTRCOMPILE = $(RCC) -r +LTLIB = lib.exe +LTLINK = $(TCC) -Fe$@ + +# If requested, link to the RPCRT4 library. +# +!IF $(USE_RPCRT4_LIB)!=0 +LTLINK = $(LTLINK) rpcrt4.lib +!ENDIF + +# If a platform was set, force the linker to target that. +# Note that the vcvars*.bat family of batch files typically +# set this for you. Otherwise, the linker will attempt +# to deduce the binary type based on the object files. +!IFDEF PLATFORM +LTLINKOPTS = /NOLOGO /MACHINE:$(PLATFORM) +LTLIBOPTS = /NOLOGO /MACHINE:$(PLATFORM) +!ELSE +LTLINKOPTS = /NOLOGO +LTLIBOPTS = /NOLOGO +!ENDIF + +# When compiling for use in the WinRT environment, the following +# linker option must be used to mark the executable as runnable +# only in the context of an application container. +# +!IF $(FOR_WINRT)!=0 +LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER +!IF "$(VISUALSTUDIOVERSION)"=="12.0" || "$(VISUALSTUDIOVERSION)"=="14.0" +!IFNDEF STORELIBPATH +!IF "$(PLATFORM)"=="x86" +STORELIBPATH = $(CRTLIBPATH)\store +!ELSEIF "$(PLATFORM)"=="x64" +STORELIBPATH = $(CRTLIBPATH)\store\amd64 +!ELSEIF "$(PLATFORM)"=="ARM" +STORELIBPATH = $(CRTLIBPATH)\store\arm +!ELSE +STORELIBPATH = $(CRTLIBPATH)\store +!ENDIF +!ENDIF +STORELIBPATH = $(STORELIBPATH:\\=\) +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(STORELIBPATH)" +!ENDIF +!ENDIF + +# When compiling for Windows Phone 8.1, an extra library path is +# required. +# +!IF $(USE_WP81_OPTS)!=0 +!IFNDEF WP81LIBPATH +!IF "$(PLATFORM)"=="x86" +WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86 +!ELSEIF "$(PLATFORM)"=="ARM" +WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\ARM +!ELSE +WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86 +!ENDIF +!ENDIF +!ENDIF + +# When compiling for Windows Phone 8.1, some extra linker options +# are also required. +# +!IF $(USE_WP81_OPTS)!=0 +!IFDEF WP81LIBPATH +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(WP81LIBPATH)" +!ENDIF +LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE +LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib +LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib +!ENDIF + +# When compiling for UWP or the Windows 10 platform, some extra linker +# options are also required. +# +!IF $(FOR_UWP)!=0 || $(FOR_WIN10)!=0 +LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib +LTLINKOPTS = $(LTLINKOPTS) mincore.lib +!IFDEF PSDKLIBPATH +LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)" +!ENDIF +!ENDIF + +!IF $(FOR_WIN10)!=0 +LTLINKOPTS = $(LTLINKOPTS) /guard:cf "/LIBPATH:$(UCRTLIBPATH)" +!IF $(DEBUG)>1 +LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrtd.lib /DEFAULTLIB:ucrtd.lib +!ELSE +LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:libucrt.lib /DEFAULTLIB:ucrt.lib +!ENDIF +!ENDIF + +# If either debugging or symbols are enabled, enable PDBs. +# +!IF $(DEBUG)>1 || $(SYMBOLS)!=0 +LDFLAGS = /DEBUG $(LDOPTS) +!ELSE +LDFLAGS = $(LDOPTS) +!ENDIF + + +# You should not have to change anything below this line +############################################################################### + + +# Object files for the amalgamation. +# +LIBOBJS1 = sqlite3.lo + +# Determine the real value of LIBOBJ based on the 'configure' script +# +LIBOBJ = $(LIBOBJS1) + +# Determine if embedded resource compilation and usage are enabled. +# +!IF $(USE_RC)!=0 +LIBRESOBJS = sqlite3res.lo +!ELSE +LIBRESOBJS = +!ENDIF + + +# Additional compiler options for the shell. These are only effective +# when the shell is not being dynamically linked. +# +!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS +!ENDIF + + +# This is the default Makefile target. The objects listed here +# are what get build when you type just "make" with no arguments. +# +all: dll libsqlite3.lib shell + +# Dynamic link library section. +# +dll: $(SQLITE3DLL) + +# Shell executable. +# +shell: $(SQLITE3EXE) + +libsqlite3.lib: $(LIBOBJ) + $(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS) + + +$(SQLITE3DLL): $(LIBOBJ) $(LIBRESOBJS) $(CORE_LINK_DEP) + $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL $(CORE_LINK_OPTS) /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) + + +$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H) + $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \ + /link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS) + + +# Rule to build the amalgamation +# +sqlite3.lo: $(SQLITE3C) + $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(SQLITE3C) + + +# Rule to build the Win32 resources object file. +# +!IF $(USE_RC)!=0 +_HASHCHAR=^# +!IF ![echo !IFNDEF VERSION > rcver.vc] && \ + ![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \ + ![echo !ENDIF >> rcver.vc] +!INCLUDE rcver.vc +!ENDIF + +RESOURCE_VERSION = $(VERSION:^#=) +RESOURCE_VERSION = $(RESOURCE_VERSION:define=) +RESOURCE_VERSION = $(RESOURCE_VERSION:SQLITE_VERSION=) +RESOURCE_VERSION = $(RESOURCE_VERSION:"=) +RESOURCE_VERSION = $(RESOURCE_VERSION:.=,) + +$(LIBRESOBJS): $(TOP)\sqlite3.rc rcver.vc $(SQLITE3H) + echo #ifndef SQLITE_RESOURCE_VERSION > sqlite3rc.h + echo #define SQLITE_RESOURCE_VERSION $(RESOURCE_VERSION) >> sqlite3rc.h + echo #endif >> sqlite3rc.h + $(LTRCOMPILE) -fo $(LIBRESOBJS) -DRC_VERONLY $(TOP)\sqlite3.rc +!ENDIF + + +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 diff --git a/autoconf/README b/autoconf/README deleted file mode 100644 index dd8cca2..0000000 --- a/autoconf/README +++ /dev/null @@ -1,32 +0,0 @@ - -This package contains: - - * the SQLite library amalgamation (single file) source code distribution, - * the shell.c file used to build the sqlite3 shell too, and - * the sqlite3.h and sqlite3ext.h header files required to link programs - and sqlite extensions against the installed libary. - * autoconf/automake installation infrastucture. - -The generic installation instructions for autoconf/automake are found -in the INSTALL file. - -The following SQLite specific boolean options are supported: - - --enable-readline use readline in shell tool [default=yes] - --enable-threadsafe build a thread-safe library [default=yes] - --enable-dynamic-extensions support loadable extensions [default=yes] - -The default value for the CFLAGS variable (options passed to the C -compiler) includes debugging symbols in the build, resulting in larger -binaries than are necessary. Override it on the configure command -line like this: - - $ CFLAGS="-Os" ./configure - -to produce a smaller installation footprint. - -Other SQLite compilation parameters can also be set using CFLAGS. For -example: - - $ CFLAGS="-Os -DSQLITE_OMIT_TRIGGERS" ./configure - diff --git a/autoconf/README.txt b/autoconf/README.txt new file mode 100644 index 0000000..2d6db4f --- /dev/null +++ b/autoconf/README.txt @@ -0,0 +1,113 @@ +This package contains: + + * the SQLite library amalgamation source code file: sqlite3.c + * the sqlite3.h and sqlite3ext.h header files that define the C-language + interface to the sqlite3.c library file + * the shell.c file used to build the sqlite3 command-line shell program + * autoconf/automake installation infrastucture for building on POSIX + compliant systems + * a Makefile.msc and sqlite3.rc for building with Microsoft Visual C++ on + Windows + +SUMMARY OF HOW TO BUILD +======================= + + Unix: ./configure; make + Windows: nmake /f Makefile.msc + +BUILDING ON POSIX +================= + +The generic installation instructions for autoconf/automake are found +in the INSTALL file. + +The following SQLite specific boolean options are supported: + + --enable-readline use readline in shell tool [default=yes] + --enable-threadsafe build a thread-safe library [default=yes] + --enable-dynamic-extensions support loadable extensions [default=yes] + +The default value for the CFLAGS variable (options passed to the C +compiler) includes debugging symbols in the build, resulting in larger +binaries than are necessary. Override it on the configure command +line like this: + + $ CFLAGS="-Os" ./configure + +to produce a smaller installation footprint. + +Other SQLite compilation parameters can also be set using CFLAGS. For +example: + + $ CFLAGS="-Os -DSQLITE_THREADSAFE=0" ./configure + + +BUILDING WITH MICROSOFT VISUAL C++ +================================== + +To compile for Windows using Microsoft Visual C++: + + $ nmake /f Makefile.msc + +Using Microsoft Visual C++ 2005 (or later) is recommended. Several Windows +platform variants may be built by adding additional macros to the NMAKE +command line. + +Building for WinRT 8.0 +---------------------- + + FOR_WINRT=1 + +Using Microsoft Visual C++ 2012 (or later) is required. When using the +above, something like the following macro will need to be added to the +NMAKE command line as well: + + "NSDKLIBPATH=%WindowsSdkDir%\..\8.0\lib\win8\um\x86" + +Building for WinRT 8.1 +---------------------- + + FOR_WINRT=1 + +Using Microsoft Visual C++ 2013 (or later) is required. When using the +above, something like the following macro will need to be added to the +NMAKE command line as well: + + "NSDKLIBPATH=%WindowsSdkDir%\..\8.1\lib\winv6.3\um\x86" + +Building for UWP 10.0 +--------------------- + + FOR_WINRT=1 FOR_UWP=1 + +Using Microsoft Visual C++ 2015 (or later) is required. When using the +above, something like the following macros will need to be added to the +NMAKE command line as well: + + "NSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86" + "PSDKLIBPATH=%WindowsSdkDir%\..\10\lib\10.0.10586.0\um\x86" + "NUCRTLIBPATH=%UniversalCRTSdkDir%\..\10\lib\10.0.10586.0\ucrt\x86" + +Building for the Windows 10 SDK +------------------------------- + + FOR_WIN10=1 + +Using Microsoft Visual C++ 2015 (or later) is required. When using the +above, no other macros should be needed on the NMAKE command line. + +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://www.sqlite.org/compile.html). For example, the +following will work: + + "OPTS=-DSQLITE_ENABLE_STAT4=1 -DSQLITE_ENABLE_JSON1=1" + +However, the following will not compile unless the amalgamation was built +with it enabled: + + "OPTS=-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1" diff --git a/autoconf/config.guess b/autoconf/config.guess deleted file mode 100755 index d622a44..0000000 --- a/autoconf/config.guess +++ /dev/null @@ -1,1530 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. - -timestamp='2012-02-10' - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-gnu - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/autoconf/config.sub b/autoconf/config.sub deleted file mode 100755 index c894da4..0000000 --- a/autoconf/config.sub +++ /dev/null @@ -1,1773 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. - -timestamp='2012-02-10' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Please send patches to . Submit a context -# diff and a properly formatted GNU ChangeLog entry. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 \ - | ns16k | ns32k \ - | open8 \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze) - basic_machine=microblaze-xilinx - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i386-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 46b6563..9492530 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -4,11 +4,13 @@ # # --enable-threadsafe # --enable-readline +# --enable-editline +# --enable-static-shell # --enable-dynamic-extensions # AC_PREREQ(2.61) -AC_INIT(sqlite, 3.7.5, http://www.sqlite.org) +AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org) AC_CONFIG_SRCDIR([sqlite3.c]) # Use automake. @@ -18,7 +20,6 @@ AC_SYS_LARGEFILE # Check for required programs. AC_PROG_CC -AC_PROG_RANLIB AC_PROG_LIBTOOL AC_PROG_MKDIR_P @@ -30,12 +31,29 @@ AC_CONFIG_FILES([Makefile sqlite3.pc]) AC_SUBST(BUILD_CFLAGS) #----------------------------------------------------------------------- +# --enable-editline # --enable-readline # +AC_ARG_ENABLE(editline, [AS_HELP_STRING( + [--enable-editline], + [use BSD libedit])], + [], [enable_editline=yes]) AC_ARG_ENABLE(readline, [AS_HELP_STRING( [--enable-readline], - [use readline in shell tool (yes, no) [default=yes]])], - [], [enable_readline=yes]) + [use readline])], + [], [enable_readline=no]) +if test x"$enable_editline" != xno ; then + sLIBS=$LIBS + LIBS="" + AC_SEARCH_LIBS([readline],[edit],[enable_readline=no],[enable_editline=no]) + READLINE_LIBS=$LIBS + if test x"$LIBS" != "x"; then + AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline) + else + unset ac_cv_search_readline + fi + LIBS=$sLIBS +fi if test x"$enable_readline" != xno ; then sLIBS=$LIBS LIBS="" @@ -58,6 +76,7 @@ THREADSAFE_FLAGS=-DSQLITE_THREADSAFE=0 if test x"$enable_threadsafe" != "xno"; then THREADSAFE_FLAGS="-D_REENTRANT=1 -DSQLITE_THREADSAFE=1" AC_SEARCH_LIBS(pthread_create, pthread) + AC_SEARCH_LIBS(pthread_mutexattr_init, pthread) fi AC_SUBST(THREADSAFE_FLAGS) #----------------------------------------------------------------------- @@ -78,6 +97,46 @@ AC_MSG_RESULT($enable_dynamic_extensions) AC_SUBST(DYNAMIC_EXTENSION_FLAGS) #----------------------------------------------------------------------- +#----------------------------------------------------------------------- +# --enable-fts5 +# +AC_ARG_ENABLE(fts5, [AS_HELP_STRING( + [--enable-fts5], [include fts5 support [default=no]])], + [], [enable_fts5=no]) +if test x"$enable_fts5" == "xyes"; then + AC_SEARCH_LIBS(log, m) + FTS5_FLAGS=-DSQLITE_ENABLE_FTS5 +fi +AC_SUBST(FTS5_FLAGS) +#----------------------------------------------------------------------- + +#----------------------------------------------------------------------- +# --enable-json1 +# +AC_ARG_ENABLE(json1, [AS_HELP_STRING( + [--enable-json1], [include json1 support [default=no]])], + [], [enable_json1=no]) +if test x"$enable_json1" == "xyes"; then + JSON1_FLAGS=-DSQLITE_ENABLE_JSON1 +fi +AC_SUBST(JSON1_FLAGS) +#----------------------------------------------------------------------- + +#----------------------------------------------------------------------- +# --enable-static-shell +# +AC_ARG_ENABLE(static-shell, [AS_HELP_STRING( + [--enable-static-shell], + [statically link libsqlite3 into shell tool [default=yes]])], + [], [enable_static_shell=yes]) +if test x"$enable_static_shell" == "xyes"; then + EXTRA_SHELL_OBJ=sqlite3.$OBJEXT +else + EXTRA_SHELL_OBJ=libsqlite3.la +fi +AC_SUBST(EXTRA_SHELL_OBJ) +#----------------------------------------------------------------------- + AC_CHECK_FUNCS(posix_fallocate) #----------------------------------------------------------------------- diff --git a/autoconf/depcomp b/autoconf/depcomp deleted file mode 100755 index 25a39e6..0000000 --- a/autoconf/depcomp +++ /dev/null @@ -1,708 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2012-03-27.16; # UTC - -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by 'PROGRAMS ARGS'. - object Object file output by 'PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputting dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -# A tabulation character. -tab=' ' -# A newline character. -nl=' -' - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -cygpath_u="cygpath -u -f -" -if test "$depmode" = msvcmsys; then - # This is just like msvisualcpp but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvisualcpp -fi - -if test "$depmode" = msvc7msys; then - # This is just like msvc7 but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvc7 -fi - -if test "$depmode" = xlc; then - # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations. - gccflag=-qmakedep=gcc,-MF - depmode=gcc -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the "deleted header file" problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' "$nl" < "$tmpdepfile" | -## Some versions of gcc put a space before the ':'. On the theory -## that the space means something, we add a space to the output as -## well. hp depmode also adds that space, but also prefixes the VPATH -## to the object. Take care to not repeat it in the output. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like '#:fec' to the end of the - # dependency line. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr "$nl" ' ' >> "$depfile" - echo >> "$depfile" - - # The second pass generates a dummy entry for each header file. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -xlc) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts '$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.u - tmpdepfile2=$base.u - tmpdepfile3=$dir.libs/$base.u - "$@" -Wc,-M - else - tmpdepfile1=$dir$base.u - tmpdepfile2=$dir$base.u - tmpdepfile3=$dir$base.u - "$@" -M - fi - stat=$? - - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - # Each line is of the form 'foo.o: dependent.h'. - # Do two passes, one to just change these to - # '$object: dependent.h' and one to simply 'dependent.h:'. - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -icc) - # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. - # However on - # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c - # ICC 7.0 will fill foo.d with something like - # foo.o: sub/foo.c - # foo.o: sub/foo.h - # which is wrong. We want - # sub/foo.o: sub/foo.c - # sub/foo.o: sub/foo.h - # sub/foo.c: - # sub/foo.h: - # ICC 7.1 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using '\': - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - # tcc 0.9.26 (FIXME still under development at the moment of writing) - # will emit a similar output, but also prepend the continuation lines - # with horizontal tabulation characters. - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form 'foo.o: dependent.h', - # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. - # Do two passes, one to just change these to - # '$object: dependent.h' and one to simply 'dependent.h:'. - sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ - < "$tmpdepfile" > "$depfile" - sed ' - s/[ '"$tab"'][ '"$tab"']*/ /g - s/^ *// - s/ *\\*$// - s/^[^:]*: *// - /^$/d - /:$/d - s/$/ :/ - ' < "$tmpdepfile" >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" - # Add 'dependent.h:' lines. - sed -ne '2,${ - s/^ *// - s/ \\*$// - s/$/:/ - p - }' "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in 'foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - # With Tru64 cc, shared objects can also be used to make a - # static library. This mechanism is used in libtool 1.4 series to - # handle both shared and static libraries in a single compilation. - # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. - # - # With libtool 1.5 this exception was removed, and libtool now - # generates 2 separate objects for the 2 libraries. These two - # compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 - tmpdepfile2=$dir$base.o.d # libtool 1.5 - tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 - tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.o.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - tmpdepfile4=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -msvc7) - if test "$libtool" = yes; then - showIncludes=-Wc,-showIncludes - else - showIncludes=-showIncludes - fi - "$@" $showIncludes > "$tmpdepfile" - stat=$? - grep -v '^Note: including file: ' "$tmpdepfile" - if test "$stat" = 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The first sed program below extracts the file names and escapes - # backslashes for cygpath. The second sed program outputs the file - # name when reading, but also accumulates all include files in the - # hold buffer in order to output them again at the end. This only - # works with sed implementations that can handle large buffers. - sed < "$tmpdepfile" -n ' -/^Note: including file: *\(.*\)/ { - s//\1/ - s/\\/\\\\/g - p -}' | $cygpath_u | sort -u | sed -n ' -s/ /\\ /g -s/\(.*\)/'"$tab"'\1 \\/p -s/.\(.*\) \\/\1:/ -H -$ { - s/.*/'"$tab"'/ - G - p -}' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvc7msys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for ':' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. - "$@" $dashmflag | - sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' "$nl" < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no eat=no - for arg - do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - if test $eat = yes; then - eat=no - continue - fi - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -arch) - eat=yes ;; - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix=`echo "$object" | sed 's/^.*\././'` - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - # makedepend may prepend the VPATH from the source file name to the object. - # No need to regex-escape $object, excess matching of '.' is harmless. - sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E | - sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - IFS=" " - for arg - do - case "$arg" in - -o) - shift - ;; - $object) - shift - ;; - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E 2>/dev/null | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" - echo "$tab" >> "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvcmsys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/autoconf/install-sh b/autoconf/install-sh deleted file mode 100755 index a9244eb..0000000 --- a/autoconf/install-sh +++ /dev/null @@ -1,527 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2011-01-19.21; # 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. - -nl=' -' -IFS=" "" $nl" - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi - -# 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_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -no_target_directory= - -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 the last 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. - -s $stripprog installed files. - -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 -" - -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 - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) dst_arg=$2 - # Protect names problematic for `test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) no_target_directory=true;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -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 - 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=$? - 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; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # 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 - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/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-writeable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or 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 - - eval "$initialize_posix_glob" - - oIFS=$IFS - IFS=/ - $posix_glob set -f - set fnord $dstdir - shift - $posix_glob 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=$dstdir/_inst.$$_ - rmtmp=$dstdir/_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 && $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` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # 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 -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$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 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/autoconf/ltmain.sh b/autoconf/ltmain.sh deleted file mode 100644 index 6a2f116..0000000 --- a/autoconf/ltmain.sh +++ /dev/null @@ -1,9655 +0,0 @@ - -# libtool (GNU libtool) 2.4.2 -# Written by Gordon Matzigkeit , 1996 - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, -# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# GNU Libtool is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, -# or obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -# Usage: $progname [OPTION]... [MODE-ARG]... -# -# Provide generalized library-building support services. -# -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --no-quiet, --no-silent -# print informational messages (default) -# --no-warn don't display warning messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print more informational messages than default -# --no-verbose don't print the extra informational messages -# --version print version information -# -h, --help, --help-all print short, long, or detailed help message -# -# MODE must be one of the following: -# -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory -# -# MODE-ARGS vary depending on the MODE. When passed as first option, -# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. -# Try `$progname --help --mode=MODE' for a more detailed description of MODE. -# -# When reporting a bug, please describe a test case to reproduce it and -# include the following information: -# -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 -# automake: $automake_version -# autoconf: $autoconf_version -# -# Report bugs to . -# GNU libtool home page: . -# General help using GNU software: . - -PROGRAM=libtool -PACKAGE=libtool -VERSION=2.4.2 -TIMESTAMP="" -package_revision=1.3337 - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - -# NLS nuisances: We save the old values to restore during execute mode. -lt_user_locale= -lt_safe_locale= -for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test \"\${$lt_var+set}\" = set; then - save_$lt_var=\$$lt_var - $lt_var=C - export $lt_var - lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" - lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" - fi" -done -LC_ALL=C -LANGUAGE=C -export LANGUAGE LC_ALL - -$lt_unset CDPATH - - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" - - - -: ${CP="cp -f"} -test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} -: ${Xsed="$SED -e 1s/^X//"} - -# Global variables: -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -exit_status=$EXIT_SUCCESS - -# Make sure IFS has a sensible default -lt_nl=' -' -IFS=" $lt_nl" - -dirname="s,/[^/]*$,," -basename="s,^.*/,," - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} # func_dirname may be replaced by extended shell implementation - - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "${1}" | $SED "$basename"` -} # func_basename may be replaced by extended shell implementation - - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi - func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` -} # func_dirname_and_basename may be replaced by extended shell implementation - - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; - esac -} # func_stripname may be replaced by extended shell implementation - - -# These SED scripts presuppose an absolute path with a trailing slash. -pathcar='s,^/\([^/]*\).*$,\1,' -pathcdr='s,^/[^/]*,,' -removedotparts=':dotsl - s@/\./@/@g - t dotsl - s,/\.$,/,' -collapseslashes='s@/\{1,\}@/@g' -finalslash='s,/*$,/,' - -# func_normal_abspath PATH -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -# value returned in "$func_normal_abspath_result" -func_normal_abspath () -{ - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` - while :; do - # Processed it all yet? - if test "$func_normal_abspath_tpath" = / ; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result" ; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - -# func_relative_path SRCDIR DSTDIR -# generates a relative path from SRCDIR to DSTDIR, with a trailing -# slash if non-empty, suitable for immediately appending a filename -# without needing to append a separator. -# value returned in "$func_relative_path_result" -func_relative_path () -{ - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=${func_dirname_result} - if test "x$func_relative_path_tlibdir" = x ; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test "x$func_stripname_result" != x ; then - func_relative_path_result=${func_relative_path_result}/${func_stripname_result} - fi - - # Normalisation. If bindir is libdir, return empty string, - # else relative path ending with a slash; either way, target - # file name can be directly appended. - if test ! -z "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result/" - func_relative_path_result=$func_stripname_result - fi -} - -# The name of this program: -func_dirname_and_basename "$progpath" -progname=$func_basename_result - -# Make sure we have an absolute path for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=$func_dirname_result - progdir=`cd "$progdir" && pwd` - progpath="$progdir/$progname" - ;; - *) - save_IFS="$IFS" - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS="$save_IFS" - test -x "$progdir/$progname" && break - done - IFS="$save_IFS" - test -n "$progdir" || progdir=`pwd` - progpath="$progdir/$progname" - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -Xsed="${SED}"' -e 1s/^X//' -sed_quote_subst='s/\([`"$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' - -# Sed substitution that converts a w32 file name or path -# which contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-`\' parameter expansions in output of double_quote_subst that were -# `\'-ed in input to the same. If an odd number of `\' preceded a '$' -# in input to double_quote_subst, that '$' was protected from expansion. -# Since each input `\' is now two `\'s, look for any number of runs of -# four `\'s followed by two `\'s and then a '$'. `\' that '$'. -bs='\\' -bs2='\\\\' -bs4='\\\\\\\\' -dollar='\$' -sed_double_backslash="\ - s/$bs4/&\\ -/g - s/^$bs2$dollar/$bs&/ - s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g - s/\n//g" - -# Standard options: -opt_dry_run=false -opt_help=false -opt_quiet=false -opt_verbose=false -opt_warning=: - -# func_echo arg... -# Echo program name prefixed message, along with the current mode -# name if it has been set yet. -func_echo () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }$*" -} - -# func_verbose arg... -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $opt_verbose && func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} - -# func_echo_all arg... -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - -# func_error arg... -# Echo program name prefixed message to standard error. -func_error () -{ - $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 -} - -# func_warning arg... -# Echo program name prefixed warning message to standard error. -func_warning () -{ - $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 - - # bash bug again: - : -} - -# func_fatal_error arg... -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - func_error ${1+"$@"} - exit $EXIT_FAILURE -} - -# func_fatal_help arg... -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - func_error ${1+"$@"} - func_fatal_error "$help" -} -help="Try \`$progname --help' for more information." ## default - - -# func_grep expression filename -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_mkdir_p directory-path -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - my_directory_path="$1" - my_dir_list= - - if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then - - # Protect directory names starting with `-' - case $my_directory_path in - -*) my_directory_path="./$my_directory_path" ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$my_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - my_dir_list="$my_directory_path:$my_dir_list" - - # If the last portion added has no slash in it, the list is done - case $my_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` - done - my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` - - save_mkdir_p_IFS="$IFS"; IFS=':' - for my_dir in $my_dir_list; do - IFS="$save_mkdir_p_IFS" - # mkdir can fail with a `File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$my_dir" 2>/dev/null || : - done - IFS="$save_mkdir_p_IFS" - - # Bail out if we (or some other process) failed to create a directory. - test -d "$my_directory_path" || \ - func_fatal_error "Failed to create \`$1'" - fi -} - - -# func_mktempdir [string] -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, STRING is the basename for that directory. -func_mktempdir () -{ - my_template="${TMPDIR-/tmp}/${1-$progname}" - - if test "$opt_dry_run" = ":"; then - # Return a directory name, but don't create it in dry-run mode - my_tmpdir="${my_template}-$$" - else - - # If mktemp works, use that first and foremost - my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` - - if test ! -d "$my_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - my_tmpdir="${my_template}-${RANDOM-0}$$" - - save_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$my_tmpdir" - umask $save_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$my_tmpdir" || \ - func_fatal_error "cannot create temporary directory \`$my_tmpdir'" - fi - - $ECHO "$my_tmpdir" -} - - -# func_quote_for_eval arg -# Aesthetically quote ARG to be evaled later. -# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT -# is double-quoted, suitable for a subsequent eval, whereas -# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters -# which are still active within double quotes backslashified. -func_quote_for_eval () -{ - case $1 in - *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; - *) - func_quote_for_eval_unquoted_result="$1" ;; - esac - - case $func_quote_for_eval_unquoted_result in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and and variable - # expansion for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" - ;; - *) - func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" - esac -} - - -# func_quote_for_expand arg -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - case $1 in - *[\\\`\"]*) - my_arg=`$ECHO "$1" | $SED \ - -e "$double_quote_subst" -e "$sed_double_backslash"` ;; - *) - my_arg="$1" ;; - esac - - case $my_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - my_arg="\"$my_arg\"" - ;; - esac - - func_quote_for_expand_result="$my_arg" -} - - -# func_show_eval cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - my_cmd="$1" - my_fail_exp="${2-:}" - - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - if ${opt_dry_run-false}; then :; else - eval "$my_cmd" - my_status=$? - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi -} - - -# func_show_eval_locale cmd [fail_exp] -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - my_cmd="$1" - my_fail_exp="${2-:}" - - ${opt_silent-false} || { - func_quote_for_expand "$my_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - if ${opt_dry_run-false}; then :; else - eval "$lt_user_locale - $my_cmd" - my_status=$? - eval "$lt_safe_locale" - if test "$my_status" -eq 0; then :; else - eval "(exit $my_status); $my_fail_exp" - fi - fi -} - -# func_tr_sh -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_version -# Echo version message to standard output and exit. -func_version () -{ - $opt_debug - - $SED -n '/(C)/!b go - :more - /\./!{ - N - s/\n# / / - b more - } - :go - /^# '$PROGRAM' (GNU /,/# warranty; / { - s/^# // - s/^# *$// - s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ - p - }' < "$progpath" - exit $? -} - -# func_usage -# Echo short help message to standard output and exit. -func_usage () -{ - $opt_debug - - $SED -n '/^# Usage:/,/^# *.*--help/ { - s/^# // - s/^# *$// - s/\$progname/'$progname'/ - p - }' < "$progpath" - echo - $ECHO "run \`$progname --help | more' for full usage" - exit $? -} - -# func_help [NOEXIT] -# Echo long help message to standard output and exit, -# unless 'noexit' is passed as argument. -func_help () -{ - $opt_debug - - $SED -n '/^# Usage:/,/# Report bugs to/ { - :print - s/^# // - s/^# *$// - s*\$progname*'$progname'* - s*\$host*'"$host"'* - s*\$SHELL*'"$SHELL"'* - s*\$LTCC*'"$LTCC"'* - s*\$LTCFLAGS*'"$LTCFLAGS"'* - s*\$LD*'"$LD"'* - s/\$with_gnu_ld/'"$with_gnu_ld"'/ - s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ - s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ - p - d - } - /^# .* home page:/b print - /^# General help using/b print - ' < "$progpath" - ret=$? - if test -z "$1"; then - exit $ret - fi -} - -# func_missing_arg argname -# Echo program name prefixed message to standard error and set global -# exit_cmd. -func_missing_arg () -{ - $opt_debug - - func_error "missing argument for $1." - exit_cmd=exit -} - - -# func_split_short_opt shortopt -# Set func_split_short_opt_name and func_split_short_opt_arg shell -# variables after splitting SHORTOPT after the 2nd character. -func_split_short_opt () -{ - my_sed_short_opt='1s/^\(..\).*$/\1/;q' - my_sed_short_rest='1s/^..\(.*\)$/\1/;q' - - func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` - func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` -} # func_split_short_opt may be replaced by extended shell implementation - - -# func_split_long_opt longopt -# Set func_split_long_opt_name and func_split_long_opt_arg shell -# variables after splitting LONGOPT at the `=' sign. -func_split_long_opt () -{ - my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' - my_sed_long_arg='1s/^--[^=]*=//' - - func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` - func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` -} # func_split_long_opt may be replaced by extended shell implementation - -exit_cmd=: - - - - - -magic="%%%MAGIC variable%%%" -magic_exe="%%%MAGIC EXE variable%%%" - -# Global variables. -nonopt= -preserve_args= -lo2o="s/\\.lo\$/.${objext}/" -o2lo="s/\\.${objext}\$/.lo/" -extracted_archives= -extracted_serial=0 - -# If this variable is set in any of the actions, the command in it -# will be execed at the end. This prevents here-documents from being -# left over by shells. -exec_cmd= - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "${1}=\$${1}\${2}" -} # func_append may be replaced by extended shell implementation - -# func_append_quoted var value -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -func_append_quoted () -{ - func_quote_for_eval "${2}" - eval "${1}=\$${1}\\ \$func_quote_for_eval_result" -} # func_append_quoted may be replaced by extended shell implementation - - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "${@}"` -} # func_arith may be replaced by extended shell implementation - - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` -} # func_len may be replaced by extended shell implementation - - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` -} # func_lo2o may be replaced by extended shell implementation - - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` -} # func_xform may be replaced by extended shell implementation - - -# func_fatal_configuration arg... -# Echo program name prefixed message to standard error, followed by -# a configuration failure hint, and exit. -func_fatal_configuration () -{ - func_error ${1+"$@"} - func_error "See the $PACKAGE documentation for more information." - func_fatal_error "Fatal configuration error." -} - - -# func_config -# Display the configuration for all the tags in this script. -func_config () -{ - re_begincf='^# ### BEGIN LIBTOOL' - re_endcf='^# ### END LIBTOOL' - - # Default configuration. - $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" - - # Now print the configurations for the tags. - for tagname in $taglist; do - $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" - done - - exit $? -} - -# func_features -# Display the features supported by this script. -func_features () -{ - echo "host: $host" - if test "$build_libtool_libs" = yes; then - echo "enable shared libraries" - else - echo "disable shared libraries" - fi - if test "$build_old_libs" = yes; then - echo "enable static libraries" - else - echo "disable static libraries" - fi - - exit $? -} - -# func_enable_tag tagname -# Verify that TAGNAME is valid, and either flag an error and exit, or -# enable the TAGNAME tag. We also add TAGNAME to the global $taglist -# variable here. -func_enable_tag () -{ - # Global variable: - tagname="$1" - - re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" - re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" - sed_extractcf="/$re_begincf/,/$re_endcf/p" - - # Validate tagname. - case $tagname in - *[!-_A-Za-z0-9,/]*) - func_fatal_error "invalid tag name: $tagname" - ;; - esac - - # Don't test for the "default" C tag, as we know it's - # there but not specially marked. - case $tagname in - CC) ;; - *) - if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then - taglist="$taglist $tagname" - - # Evaluate the configuration. Be careful to quote the path - # and the sed script, to avoid splitting on whitespace, but - # also don't use non-portable quotes within backquotes within - # quotes we have to do it in 2 steps: - extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` - eval "$extractedcf" - else - func_error "ignoring unknown tag $tagname" - fi - ;; - esac -} - -# func_check_version_match -# Ensure that we are using m4 macros, and libtool script from the same -# release of libtool. -func_check_version_match () -{ - if test "$package_revision" != "$macro_revision"; then - if test "$VERSION" != "$macro_version"; then - if test -z "$macro_version"; then - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from an older release. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, but the -$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. -$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION -$progname: and run autoconf again. -_LT_EOF - fi - else - cat >&2 <<_LT_EOF -$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, -$progname: but the definition of this LT_INIT comes from revision $macro_revision. -$progname: You should recreate aclocal.m4 with macros from revision $package_revision -$progname: of $PACKAGE $VERSION and run autoconf again. -_LT_EOF - fi - - exit $EXIT_MISMATCH - fi -} - - -# Shorthand for --mode=foo, only valid as the first argument -case $1 in -clean|clea|cle|cl) - shift; set dummy --mode clean ${1+"$@"}; shift - ;; -compile|compil|compi|comp|com|co|c) - shift; set dummy --mode compile ${1+"$@"}; shift - ;; -execute|execut|execu|exec|exe|ex|e) - shift; set dummy --mode execute ${1+"$@"}; shift - ;; -finish|finis|fini|fin|fi|f) - shift; set dummy --mode finish ${1+"$@"}; shift - ;; -install|instal|insta|inst|ins|in|i) - shift; set dummy --mode install ${1+"$@"}; shift - ;; -link|lin|li|l) - shift; set dummy --mode link ${1+"$@"}; shift - ;; -uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) - shift; set dummy --mode uninstall ${1+"$@"}; shift - ;; -esac - - - -# Option defaults: -opt_debug=: -opt_dry_run=false -opt_config=false -opt_preserve_dup_deps=false -opt_features=false -opt_finish=false -opt_help=false -opt_help_all=false -opt_silent=: -opt_warning=: -opt_verbose=: -opt_silent=false -opt_verbose=false - - -# Parse options once, thoroughly. This comes as soon as possible in the -# script to make things like `--version' happen as quickly as we can. -{ - # this just eases exit handling - while test $# -gt 0; do - opt="$1" - shift - case $opt in - --debug|-x) opt_debug='set -x' - func_echo "enabling shell trace mode" - $opt_debug - ;; - --dry-run|--dryrun|-n) - opt_dry_run=: - ;; - --config) - opt_config=: -func_config - ;; - --dlopen|-dlopen) - optarg="$1" - opt_dlopen="${opt_dlopen+$opt_dlopen -}$optarg" - shift - ;; - --preserve-dup-deps) - opt_preserve_dup_deps=: - ;; - --features) - opt_features=: -func_features - ;; - --finish) - opt_finish=: -set dummy --mode finish ${1+"$@"}; shift - ;; - --help) - opt_help=: - ;; - --help-all) - opt_help_all=: -opt_help=': help-all' - ;; - --mode) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_mode="$optarg" -case $optarg in - # Valid mode arguments: - clean|compile|execute|finish|install|link|relink|uninstall) ;; - - # Catch anything else as an error - *) func_error "invalid argument for $opt" - exit_cmd=exit - break - ;; -esac - shift - ;; - --no-silent|--no-quiet) - opt_silent=false -func_append preserve_args " $opt" - ;; - --no-warning|--no-warn) - opt_warning=false -func_append preserve_args " $opt" - ;; - --no-verbose) - opt_verbose=false -func_append preserve_args " $opt" - ;; - --silent|--quiet) - opt_silent=: -func_append preserve_args " $opt" - opt_verbose=false - ;; - --verbose|-v) - opt_verbose=: -func_append preserve_args " $opt" -opt_silent=false - ;; - --tag) - test $# = 0 && func_missing_arg $opt && break - optarg="$1" - opt_tag="$optarg" -func_append preserve_args " $opt $optarg" -func_enable_tag "$optarg" - shift - ;; - - -\?|-h) func_usage ;; - --help) func_help ;; - --version) func_version ;; - - # Separate optargs to long options: - --*=*) - func_split_long_opt "$opt" - set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-n*|-v*) - func_split_short_opt "$opt" - set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognized option \`$opt'" ;; - *) set dummy "$opt" ${1+"$@"}; shift; break ;; - esac - done - - # Validate options: - - # save first non-option argument - if test "$#" -gt 0; then - nonopt="$opt" - shift - fi - - # preserve --debug - test "$opt_debug" = : || func_append preserve_args " --debug" - - case $host in - *cygwin* | *mingw* | *pw32* | *cegcc*) - # don't eliminate duplications in $postdeps and $predeps - opt_duplicate_compiler_generated_deps=: - ;; - *) - opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps - ;; - esac - - $opt_help || { - # Sanity checks first: - func_check_version_match - - if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then - func_fatal_configuration "not configured to build any kind of library" - fi - - # Darwin sucks - eval std_shrext=\"$shrext_cmds\" - - # Only execute mode is allowed to have -dlopen flags. - if test -n "$opt_dlopen" && test "$opt_mode" != execute; then - func_error "unrecognized option \`-dlopen'" - $ECHO "$help" 1>&2 - exit $EXIT_FAILURE - fi - - # Change the help message to a mode-specific one. - generic_help="$help" - help="Try \`$progname --help --mode=$opt_mode' for more information." - } - - - # Bail if the options were screwed - $exit_cmd $EXIT_FAILURE -} - - - - -## ----------- ## -## Main. ## -## ----------- ## - -# func_lalib_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_lalib_p () -{ - test -f "$1" && - $SED -e 4q "$1" 2>/dev/null \ - | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 -} - -# func_lalib_unsafe_p file -# True iff FILE is a libtool `.la' library or `.lo' object file. -# This function implements the same check as func_lalib_p without -# resorting to external programs. To this end, it redirects stdin and -# closes it afterwards, without saving the original file descriptor. -# As a safety measure, use it only where a negative result would be -# fatal anyway. Works if `file' does not exist. -func_lalib_unsafe_p () -{ - lalib_p=no - if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then - for lalib_p_l in 1 2 3 4 - do - read lalib_p_line - case "$lalib_p_line" in - \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; - esac - done - exec 0<&5 5<&- - fi - test "$lalib_p" = yes -} - -# func_ltwrapper_script_p file -# True iff FILE is a libtool wrapper script -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_script_p () -{ - func_lalib_p "$1" -} - -# func_ltwrapper_executable_p file -# True iff FILE is a libtool wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_executable_p () -{ - func_ltwrapper_exec_suffix= - case $1 in - *.exe) ;; - *) func_ltwrapper_exec_suffix=.exe ;; - esac - $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 -} - -# func_ltwrapper_scriptname file -# Assumes file is an ltwrapper_executable -# uses $file to determine the appropriate filename for a -# temporary ltwrapper_script. -func_ltwrapper_scriptname () -{ - func_dirname_and_basename "$1" "" "." - func_stripname '' '.exe' "$func_basename_result" - func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" -} - -# func_ltwrapper_p file -# True iff FILE is a libtool wrapper script or wrapper executable -# This function is only a basic sanity check; it will hardly flush out -# determined imposters. -func_ltwrapper_p () -{ - func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" -} - - -# func_execute_cmds commands fail_cmd -# Execute tilde-delimited COMMANDS. -# If FAIL_CMD is given, eval that upon failure. -# FAIL_CMD may read-access the current command in variable CMD! -func_execute_cmds () -{ - $opt_debug - save_ifs=$IFS; IFS='~' - for cmd in $1; do - IFS=$save_ifs - eval cmd=\"$cmd\" - func_show_eval "$cmd" "${2-:}" - done - IFS=$save_ifs -} - - -# func_source file -# Source FILE, adding directory component if necessary. -# Note that it is not necessary on cygwin/mingw to append a dot to -# FILE even if both FILE and FILE.exe exist: automatic-append-.exe -# behavior happens only for exec(3), not for open(2)! Also, sourcing -# `FILE.' does not work on cygwin managed mounts. -func_source () -{ - $opt_debug - case $1 in - */* | *\\*) . "$1" ;; - *) . "./$1" ;; - esac -} - - -# func_resolve_sysroot PATH -# Replace a leading = in PATH with a sysroot. Store the result into -# func_resolve_sysroot_result -func_resolve_sysroot () -{ - func_resolve_sysroot_result=$1 - case $func_resolve_sysroot_result in - =*) - func_stripname '=' '' "$func_resolve_sysroot_result" - func_resolve_sysroot_result=$lt_sysroot$func_stripname_result - ;; - esac -} - -# func_replace_sysroot PATH -# If PATH begins with the sysroot, replace it with = and -# store the result into func_replace_sysroot_result. -func_replace_sysroot () -{ - case "$lt_sysroot:$1" in - ?*:"$lt_sysroot"*) - func_stripname "$lt_sysroot" '' "$1" - func_replace_sysroot_result="=$func_stripname_result" - ;; - *) - # Including no sysroot. - func_replace_sysroot_result=$1 - ;; - esac -} - -# func_infer_tag arg -# Infer tagged configuration to use if any are available and -# if one wasn't chosen via the "--tag" command line option. -# Only attempt this if the compiler in the base compile -# command doesn't match the default compiler. -# arg is usually of the form 'gcc ...' -func_infer_tag () -{ - $opt_debug - if test -n "$available_tags" && test -z "$tagname"; then - CC_quoted= - for arg in $CC; do - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case $@ in - # Blanks in the command may have been stripped by the calling shell, - # but not from the CC environment variable when configure was run. - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; - # Blanks at the start of $base_compile will cause this to fail - # if we don't check for them as well. - *) - for z in $available_tags; do - if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then - # Evaluate the configuration. - eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" - CC_quoted= - for arg in $CC; do - # Double-quote args containing other shell metacharacters. - func_append_quoted CC_quoted "$arg" - done - CC_expanded=`func_echo_all $CC` - CC_quoted_expanded=`func_echo_all $CC_quoted` - case "$@ " in - " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ - " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) - # The compiler in the base compile command matches - # the one in the tagged configuration. - # Assume this is the tagged configuration we want. - tagname=$z - break - ;; - esac - fi - done - # If $tagname still isn't set, then no tagged configuration - # was found and let the user know that the "--tag" command - # line option must be used. - if test -z "$tagname"; then - func_echo "unable to infer tagged configuration" - func_fatal_error "specify a tag with \`--tag'" -# else -# func_verbose "using $tagname tagged configuration" - fi - ;; - esac - fi -} - - - -# func_write_libtool_object output_name pic_name nonpic_name -# Create a libtool object file (analogous to a ".la" file), -# but don't create it if we're doing a dry run. -func_write_libtool_object () -{ - write_libobj=${1} - if test "$build_libtool_libs" = yes; then - write_lobj=\'${2}\' - else - write_lobj=none - fi - - if test "$build_old_libs" = yes; then - write_oldobj=\'${3}\' - else - write_oldobj=none - fi - - $opt_dry_run || { - cat >${write_libobj}T </dev/null` - if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then - func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | - $SED -e "$lt_sed_naive_backslashify"` - else - func_convert_core_file_wine_to_w32_result= - fi - fi -} -# end: func_convert_core_file_wine_to_w32 - - -# func_convert_core_path_wine_to_w32 ARG -# Helper function used by path conversion functions when $build is *nix, and -# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly -# configured wine environment available, with the winepath program in $build's -# $PATH. Assumes ARG has no leading or trailing path separator characters. -# -# ARG is path to be converted from $build format to win32. -# Result is available in $func_convert_core_path_wine_to_w32_result. -# Unconvertible file (directory) names in ARG are skipped; if no directory names -# are convertible, then the result may be empty. -func_convert_core_path_wine_to_w32 () -{ - $opt_debug - # unfortunately, winepath doesn't convert paths, only file names - func_convert_core_path_wine_to_w32_result="" - if test -n "$1"; then - oldIFS=$IFS - IFS=: - for func_convert_core_path_wine_to_w32_f in $1; do - IFS=$oldIFS - func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" - if test -n "$func_convert_core_file_wine_to_w32_result" ; then - if test -z "$func_convert_core_path_wine_to_w32_result"; then - func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" - else - func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" - fi - fi - done - IFS=$oldIFS - fi -} -# end: func_convert_core_path_wine_to_w32 - - -# func_cygpath ARGS... -# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when -# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) -# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or -# (2), returns the Cygwin file name or path in func_cygpath_result (input -# file name or path is assumed to be in w32 format, as previously converted -# from $build's *nix or MSYS format). In case (3), returns the w32 file name -# or path in func_cygpath_result (input file name or path is assumed to be in -# Cygwin format). Returns an empty string on error. -# -# ARGS are passed to cygpath, with the last one being the file name or path to -# be converted. -# -# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH -# environment variable; do not put it in $PATH. -func_cygpath () -{ - $opt_debug - if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then - func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` - if test "$?" -ne 0; then - # on failure, ensure result is empty - func_cygpath_result= - fi - else - func_cygpath_result= - func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" - fi -} -#end: func_cygpath - - -# func_convert_core_msys_to_w32 ARG -# Convert file name or path ARG from MSYS format to w32 format. Return -# result in func_convert_core_msys_to_w32_result. -func_convert_core_msys_to_w32 () -{ - $opt_debug - # awkward: cmd appends spaces to result - func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | - $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` -} -#end: func_convert_core_msys_to_w32 - - -# func_convert_file_check ARG1 ARG2 -# Verify that ARG1 (a file name in $build format) was converted to $host -# format in ARG2. Otherwise, emit an error message, but continue (resetting -# func_to_host_file_result to ARG1). -func_convert_file_check () -{ - $opt_debug - if test -z "$2" && test -n "$1" ; then - func_error "Could not determine host file name corresponding to" - func_error " \`$1'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback: - func_to_host_file_result="$1" - fi -} -# end func_convert_file_check - - -# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH -# Verify that FROM_PATH (a path in $build format) was converted to $host -# format in TO_PATH. Otherwise, emit an error message, but continue, resetting -# func_to_host_file_result to a simplistic fallback value (see below). -func_convert_path_check () -{ - $opt_debug - if test -z "$4" && test -n "$3"; then - func_error "Could not determine the host path corresponding to" - func_error " \`$3'" - func_error "Continuing, but uninstalled executables may not work." - # Fallback. This is a deliberately simplistic "conversion" and - # should not be "improved". See libtool.info. - if test "x$1" != "x$2"; then - lt_replace_pathsep_chars="s|$1|$2|g" - func_to_host_path_result=`echo "$3" | - $SED -e "$lt_replace_pathsep_chars"` - else - func_to_host_path_result="$3" - fi - fi -} -# end func_convert_path_check - - -# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG -# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT -# and appending REPL if ORIG matches BACKPAT. -func_convert_path_front_back_pathsep () -{ - $opt_debug - case $4 in - $1 ) func_to_host_path_result="$3$func_to_host_path_result" - ;; - esac - case $4 in - $2 ) func_append func_to_host_path_result "$3" - ;; - esac -} -# end func_convert_path_front_back_pathsep - - -################################################## -# $build to $host FILE NAME CONVERSION FUNCTIONS # -################################################## -# invoked via `$to_host_file_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# Result will be available in $func_to_host_file_result. - - -# func_to_host_file ARG -# Converts the file name ARG from $build format to $host format. Return result -# in func_to_host_file_result. -func_to_host_file () -{ - $opt_debug - $to_host_file_cmd "$1" -} -# end func_to_host_file - - -# func_to_tool_file ARG LAZY -# converts the file name ARG from $build format to toolchain format. Return -# result in func_to_tool_file_result. If the conversion in use is listed -# in (the comma separated) LAZY, no conversion takes place. -func_to_tool_file () -{ - $opt_debug - case ,$2, in - *,"$to_tool_file_cmd",*) - func_to_tool_file_result=$1 - ;; - *) - $to_tool_file_cmd "$1" - func_to_tool_file_result=$func_to_host_file_result - ;; - esac -} -# end func_to_tool_file - - -# func_convert_file_noop ARG -# Copy ARG to func_to_host_file_result. -func_convert_file_noop () -{ - func_to_host_file_result="$1" -} -# end func_convert_file_noop - - -# func_convert_file_msys_to_w32 ARG -# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_file_result. -func_convert_file_msys_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_to_host_file_result="$func_convert_core_msys_to_w32_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_w32 - - -# func_convert_file_cygwin_to_w32 ARG -# Convert file name ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_file_cygwin_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - # because $build is cygwin, we call "the" cygpath in $PATH; no need to use - # LT_CYGPATH in this case. - func_to_host_file_result=`cygpath -m "$1"` - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_cygwin_to_w32 - - -# func_convert_file_nix_to_w32 ARG -# Convert file name ARG from *nix to w32 format. Requires a wine environment -# and a working winepath. Returns result in func_to_host_file_result. -func_convert_file_nix_to_w32 () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_file_wine_to_w32 "$1" - func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_w32 - - -# func_convert_file_msys_to_cygwin ARG -# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_file_msys_to_cygwin () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - func_convert_core_msys_to_w32 "$1" - func_cygpath -u "$func_convert_core_msys_to_w32_result" - func_to_host_file_result="$func_cygpath_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_msys_to_cygwin - - -# func_convert_file_nix_to_cygwin ARG -# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed -# in a wine environment, working winepath, and LT_CYGPATH set. Returns result -# in func_to_host_file_result. -func_convert_file_nix_to_cygwin () -{ - $opt_debug - func_to_host_file_result="$1" - if test -n "$1"; then - # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. - func_convert_core_file_wine_to_w32 "$1" - func_cygpath -u "$func_convert_core_file_wine_to_w32_result" - func_to_host_file_result="$func_cygpath_result" - fi - func_convert_file_check "$1" "$func_to_host_file_result" -} -# end func_convert_file_nix_to_cygwin - - -############################################# -# $build to $host PATH CONVERSION FUNCTIONS # -############################################# -# invoked via `$to_host_path_cmd ARG' -# -# In each case, ARG is the path to be converted from $build to $host format. -# The result will be available in $func_to_host_path_result. -# -# Path separators are also converted from $build format to $host format. If -# ARG begins or ends with a path separator character, it is preserved (but -# converted to $host format) on output. -# -# All path conversion functions are named using the following convention: -# file name conversion function : func_convert_file_X_to_Y () -# path conversion function : func_convert_path_X_to_Y () -# where, for any given $build/$host combination the 'X_to_Y' value is the -# same. If conversion functions are added for new $build/$host combinations, -# the two new functions must follow this pattern, or func_init_to_host_path_cmd -# will break. - - -# func_init_to_host_path_cmd -# Ensures that function "pointer" variable $to_host_path_cmd is set to the -# appropriate value, based on the value of $to_host_file_cmd. -to_host_path_cmd= -func_init_to_host_path_cmd () -{ - $opt_debug - if test -z "$to_host_path_cmd"; then - func_stripname 'func_convert_file_' '' "$to_host_file_cmd" - to_host_path_cmd="func_convert_path_${func_stripname_result}" - fi -} - - -# func_to_host_path ARG -# Converts the path ARG from $build format to $host format. Return result -# in func_to_host_path_result. -func_to_host_path () -{ - $opt_debug - func_init_to_host_path_cmd - $to_host_path_cmd "$1" -} -# end func_to_host_path - - -# func_convert_path_noop ARG -# Copy ARG to func_to_host_path_result. -func_convert_path_noop () -{ - func_to_host_path_result="$1" -} -# end func_convert_path_noop - - -# func_convert_path_msys_to_w32 ARG -# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic -# conversion to w32 is not available inside the cwrapper. Returns result in -# func_to_host_path_result. -func_convert_path_msys_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # Remove leading and trailing path separator characters from ARG. MSYS - # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; - # and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_msys_to_w32_result" - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_msys_to_w32 - - -# func_convert_path_cygwin_to_w32 ARG -# Convert path ARG from Cygwin to w32 format. Returns result in -# func_to_host_file_result. -func_convert_path_cygwin_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_cygwin_to_w32 - - -# func_convert_path_nix_to_w32 ARG -# Convert path ARG from *nix to w32 format. Requires a wine environment and -# a working winepath. Returns result in func_to_host_file_result. -func_convert_path_nix_to_w32 () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" - func_convert_path_check : ";" \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" - fi -} -# end func_convert_path_nix_to_w32 - - -# func_convert_path_msys_to_cygwin ARG -# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. -# Returns result in func_to_host_file_result. -func_convert_path_msys_to_cygwin () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # See func_convert_path_msys_to_w32: - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_msys_to_w32_result" - func_to_host_path_result="$func_cygpath_result" - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_msys_to_cygwin - - -# func_convert_path_nix_to_cygwin ARG -# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a -# a wine environment, working winepath, and LT_CYGPATH set. Returns result in -# func_to_host_file_result. -func_convert_path_nix_to_cygwin () -{ - $opt_debug - func_to_host_path_result="$1" - if test -n "$1"; then - # Remove leading and trailing path separator characters from - # ARG. msys behavior is inconsistent here, cygpath turns them - # into '.;' and ';.', and winepath ignores them completely. - func_stripname : : "$1" - func_to_host_path_tmp1=$func_stripname_result - func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" - func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" - func_to_host_path_result="$func_cygpath_result" - func_convert_path_check : : \ - "$func_to_host_path_tmp1" "$func_to_host_path_result" - func_convert_path_front_back_pathsep ":*" "*:" : "$1" - fi -} -# end func_convert_path_nix_to_cygwin - - -# func_mode_compile arg... -func_mode_compile () -{ - $opt_debug - # Get the compilation command and the source file. - base_compile= - srcfile="$nonopt" # always keep a non-empty value in "srcfile" - suppress_opt=yes - suppress_output= - arg_mode=normal - libobj= - later= - pie_flag= - - for arg - do - case $arg_mode in - arg ) - # do not "continue". Instead, add this to base_compile - lastarg="$arg" - arg_mode=normal - ;; - - target ) - libobj="$arg" - arg_mode=normal - continue - ;; - - normal ) - # Accept any command-line options. - case $arg in - -o) - test -n "$libobj" && \ - func_fatal_error "you cannot specify \`-o' more than once" - arg_mode=target - continue - ;; - - -pie | -fpie | -fPIE) - func_append pie_flag " $arg" - continue - ;; - - -shared | -static | -prefer-pic | -prefer-non-pic) - func_append later " $arg" - continue - ;; - - -no-suppress) - suppress_opt=no - continue - ;; - - -Xcompiler) - arg_mode=arg # the next one goes into the "base_compile" arg list - continue # The current "srcfile" will either be retained or - ;; # replaced later. I would guess that would be a bug. - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - lastarg= - save_ifs="$IFS"; IFS=',' - for arg in $args; do - IFS="$save_ifs" - func_append_quoted lastarg "$arg" - done - IFS="$save_ifs" - func_stripname ' ' '' "$lastarg" - lastarg=$func_stripname_result - - # Add the arguments to base_compile. - func_append base_compile " $lastarg" - continue - ;; - - *) - # Accept the current argument as the source file. - # The previous "srcfile" becomes the current argument. - # - lastarg="$srcfile" - srcfile="$arg" - ;; - esac # case $arg - ;; - esac # case $arg_mode - - # Aesthetically quote the previous argument. - func_append_quoted base_compile "$lastarg" - done # for arg - - case $arg_mode in - arg) - func_fatal_error "you must specify an argument for -Xcompile" - ;; - target) - func_fatal_error "you must specify a target with \`-o'" - ;; - *) - # Get the name of the library object. - test -z "$libobj" && { - func_basename "$srcfile" - libobj="$func_basename_result" - } - ;; - esac - - # Recognize several different file suffixes. - # If the user specifies -o file.o, it is replaced with file.lo - case $libobj in - *.[cCFSifmso] | \ - *.ada | *.adb | *.ads | *.asm | \ - *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ - *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) - func_xform "$libobj" - libobj=$func_xform_result - ;; - esac - - case $libobj in - *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; - *) - func_fatal_error "cannot determine name of library object from \`$libobj'" - ;; - esac - - func_infer_tag $base_compile - - for arg in $later; do - case $arg in - -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" - build_old_libs=no - continue - ;; - - -static) - build_libtool_libs=no - build_old_libs=yes - continue - ;; - - -prefer-pic) - pic_mode=yes - continue - ;; - - -prefer-non-pic) - pic_mode=no - continue - ;; - esac - done - - func_quote_for_eval "$libobj" - test "X$libobj" != "X$func_quote_for_eval_result" \ - && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ - && func_warning "libobj name \`$libobj' may not contain shell special characters." - func_dirname_and_basename "$obj" "/" "" - objname="$func_basename_result" - xdir="$func_dirname_result" - lobj=${xdir}$objdir/$objname - - test -z "$base_compile" && \ - func_fatal_help "you must specify a compilation command" - - # Delete any leftover library objects. - if test "$build_old_libs" = yes; then - removelist="$obj $lobj $libobj ${libobj}T" - else - removelist="$lobj $libobj ${libobj}T" - fi - - # On Cygwin there's no "real" PIC flag so we must build both object types - case $host_os in - cygwin* | mingw* | pw32* | os2* | cegcc*) - pic_mode=default - ;; - esac - if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then - # non-PIC code in shared libraries is not supported - pic_mode=default - fi - - # Calculate the filename of the output object if compiler does - # not support -o with -c - if test "$compiler_c_o" = no; then - output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} - lockfile="$output_obj.lock" - else - output_obj= - need_locks=no - lockfile= - fi - - # Lock this critical section if it is needed - # We use this script file to make the link, it avoids creating a new file - if test "$need_locks" = yes; then - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - elif test "$need_locks" = warn; then - if test -f "$lockfile"; then - $ECHO "\ -*** ERROR, $lockfile exists and contains: -`cat $lockfile 2>/dev/null` - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - func_append removelist " $output_obj" - $ECHO "$srcfile" > "$lockfile" - fi - - $opt_dry_run || $RM $removelist - func_append removelist " $lockfile" - trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 - - func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 - srcfile=$func_to_tool_file_result - func_quote_for_eval "$srcfile" - qsrcfile=$func_quote_for_eval_result - - # Only build a PIC object if we are building libtool libraries. - if test "$build_libtool_libs" = yes; then - # Without this assignment, base_compile gets emptied. - fbsd_hideous_sh_bug=$base_compile - - if test "$pic_mode" != no; then - command="$base_compile $qsrcfile $pic_flag" - else - # Don't build PIC code - command="$base_compile $qsrcfile" - fi - - func_mkdir_p "$xdir$objdir" - - if test -z "$output_obj"; then - # Place PIC objects in $objdir - func_append command " -o $lobj" - fi - - func_show_eval_locale "$command" \ - 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' - - if test "$need_locks" = warn && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed, then go on to compile the next one - if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then - func_show_eval '$MV "$output_obj" "$lobj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - - # Allow error messages only from the first compilation. - if test "$suppress_opt" = yes; then - suppress_output=' >/dev/null 2>&1' - fi - fi - - # Only build a position-dependent object if we build old libraries. - if test "$build_old_libs" = yes; then - if test "$pic_mode" != yes; then - # Don't build PIC code - command="$base_compile $qsrcfile$pie_flag" - else - command="$base_compile $qsrcfile $pic_flag" - fi - if test "$compiler_c_o" = yes; then - func_append command " -o $obj" - fi - - # Suppress compiler output if we already did a PIC compilation. - func_append command "$suppress_output" - func_show_eval_locale "$command" \ - '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' - - if test "$need_locks" = warn && - test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then - $ECHO "\ -*** ERROR, $lockfile contains: -`cat $lockfile 2>/dev/null` - -but it should contain: -$srcfile - -This indicates that another process is trying to use the same -temporary object file, and libtool could not work around it because -your compiler does not support \`-c' and \`-o' together. If you -repeat this compilation, it may succeed, by chance, but you had better -avoid parallel builds (make -j) in this platform, or get a better -compiler." - - $opt_dry_run || $RM $removelist - exit $EXIT_FAILURE - fi - - # Just move the object if needed - if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then - func_show_eval '$MV "$output_obj" "$obj"' \ - 'error=$?; $opt_dry_run || $RM $removelist; exit $error' - fi - fi - - $opt_dry_run || { - func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" - - # Unlock the critical section if it was locked - if test "$need_locks" != no; then - removelist=$lockfile - $RM "$lockfile" - fi - } - - exit $EXIT_SUCCESS -} - -$opt_help || { - test "$opt_mode" = compile && func_mode_compile ${1+"$@"} -} - -func_mode_help () -{ - # We need to display help for each of the modes. - case $opt_mode in - "") - # Generic help is extracted from the usage comments - # at the start of this file. - func_help - ;; - - clean) - $ECHO \ -"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... - -Remove files from the build directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, object or program, all the files associated -with it are deleted. Otherwise, only FILE itself is deleted using RM." - ;; - - compile) - $ECHO \ -"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE - -Compile a source file into a libtool library object. - -This mode accepts the following additional options: - - -o OUTPUT-FILE set the output file name to OUTPUT-FILE - -no-suppress do not suppress compiler output for multiple passes - -prefer-pic try to build PIC objects only - -prefer-non-pic try to build non-PIC objects only - -shared do not build a \`.o' file suitable for static linking - -static only build a \`.o' file suitable for static linking - -Wc,FLAG pass FLAG directly to the compiler - -COMPILE-COMMAND is a command to be used in creating a \`standard' object file -from the given SOURCEFILE. - -The output file name is determined by removing the directory component from -SOURCEFILE, then substituting the C source code suffix \`.c' with the -library object suffix, \`.lo'." - ;; - - execute) - $ECHO \ -"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... - -Automatically set library path, then run a program. - -This mode accepts the following additional options: - - -dlopen FILE add the directory containing FILE to the library path - -This mode sets the library path environment variable according to \`-dlopen' -flags. - -If any of the ARGS are libtool executable wrappers, then they are translated -into their corresponding uninstalled binary, and any of their required library -directories are added to the library path. - -Then, COMMAND is executed, with ARGS as arguments." - ;; - - finish) - $ECHO \ -"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... - -Complete the installation of libtool libraries. - -Each LIBDIR is a directory that contains libtool libraries. - -The commands that this mode executes may require superuser privileges. Use -the \`--dry-run' option if you just want to see what would be executed." - ;; - - install) - $ECHO \ -"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... - -Install executables or libraries. - -INSTALL-COMMAND is the installation command. The first component should be -either the \`install' or \`cp' program. - -The following components of INSTALL-COMMAND are treated specially: - - -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation - -The rest of the components are interpreted as arguments to that command (only -BSD-compatible install options are recognized)." - ;; - - link) - $ECHO \ -"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... - -Link object files or libraries together to form another library, or to -create an executable program. - -LINK-COMMAND is a command using the C compiler that you would use to create -a program from several object files. - -The following components of LINK-COMMAND are treated specially: - - -all-static do not do any dynamic linking at all - -avoid-version do not add a version suffix if possible - -bindir BINDIR specify path to binaries directory (for systems where - libraries must be found in the PATH setting at runtime) - -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime - -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols - -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) - -export-symbols SYMFILE - try to export only the symbols listed in SYMFILE - -export-symbols-regex REGEX - try to export only the symbols matching REGEX - -LLIBDIR search LIBDIR for required installed libraries - -lNAME OUTPUT-FILE requires the installed library libNAME - -module build a library that can dlopened - -no-fast-install disable the fast-install mode - -no-install link a not-installable executable - -no-undefined declare that a library does not refer to external symbols - -o OUTPUT-FILE create OUTPUT-FILE from the specified objects - -objectlist FILE Use a list of object files found in FILE to specify objects - -precious-files-regex REGEX - don't remove output files matching REGEX - -release RELEASE specify package release information - -rpath LIBDIR the created library will eventually be installed in LIBDIR - -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries - -shared only do dynamic linking of libtool libraries - -shrext SUFFIX override the standard shared library file extension - -static do not do any dynamic linking of uninstalled libtool libraries - -static-libtool-libs - do not do any dynamic linking of libtool libraries - -version-info CURRENT[:REVISION[:AGE]] - specify library version info [each variable defaults to 0] - -weak LIBNAME declare that the target provides the LIBNAME interface - -Wc,FLAG - -Xcompiler FLAG pass linker-specific FLAG directly to the compiler - -Wl,FLAG - -Xlinker FLAG pass linker-specific FLAG directly to the linker - -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) - -All other options (arguments beginning with \`-') are ignored. - -Every other argument is treated as a filename. Files ending in \`.la' are -treated as uninstalled libtool libraries, other files are standard or library -object files. - -If the OUTPUT-FILE ends in \`.la', then a libtool library is created, -only library objects (\`.lo' files) may be specified, and \`-rpath' is -required, except when creating a convenience library. - -If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created -using \`ar' and \`ranlib', or on Windows using \`lib'. - -If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file -is created, otherwise an executable program is created." - ;; - - uninstall) - $ECHO \ -"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... - -Remove libraries from an installation directory. - -RM is the name of the program to use to delete files associated with each FILE -(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed -to RM. - -If FILE is a libtool library, all the files associated with it are deleted. -Otherwise, only FILE itself is deleted using RM." - ;; - - *) - func_fatal_help "invalid operation mode \`$opt_mode'" - ;; - esac - - echo - $ECHO "Try \`$progname --help' for more information about other modes." -} - -# Now that we've collected a possible --mode arg, show help if necessary -if $opt_help; then - if test "$opt_help" = :; then - func_mode_help - else - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - func_mode_help - done - } | sed -n '1p; 2,$s/^Usage:/ or: /p' - { - func_help noexit - for opt_mode in compile link execute install finish uninstall clean; do - echo - func_mode_help - done - } | - sed '1d - /^When reporting/,/^Report/{ - H - d - } - $x - /information about other modes/d - /more detailed .*MODE/d - s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' - fi - exit $? -fi - - -# func_mode_execute arg... -func_mode_execute () -{ - $opt_debug - # The first argument is the command name. - cmd="$nonopt" - test -z "$cmd" && \ - func_fatal_help "you must specify a COMMAND" - - # Handle -dlopen flags immediately. - for file in $opt_dlopen; do - test -f "$file" \ - || func_fatal_help "\`$file' is not a file" - - dir= - case $file in - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$lib' is not a valid libtool archive" - - # Read the libtool library. - dlname= - library_names= - func_source "$file" - - # Skip this library if it cannot be dlopened. - if test -z "$dlname"; then - # Warn if it was a shared library. - test -n "$library_names" && \ - func_warning "\`$file' was not linked with \`-export-dynamic'" - continue - fi - - func_dirname "$file" "" "." - dir="$func_dirname_result" - - if test -f "$dir/$objdir/$dlname"; then - func_append dir "/$objdir" - else - if test ! -f "$dir/$dlname"; then - func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" - fi - fi - ;; - - *.lo) - # Just add the directory containing the .lo file. - func_dirname "$file" "" "." - dir="$func_dirname_result" - ;; - - *) - func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" - continue - ;; - esac - - # Get the absolute pathname. - absdir=`cd "$dir" && pwd` - test -n "$absdir" && dir="$absdir" - - # Now add the directory to shlibpath_var. - if eval "test -z \"\$$shlibpath_var\""; then - eval "$shlibpath_var=\"\$dir\"" - else - eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" - fi - done - - # This variable tells wrapper scripts just to set shlibpath_var - # rather than running their programs. - libtool_execute_magic="$magic" - - # Check if any of the arguments is a wrapper script. - args= - for file - do - case $file in - -* | *.la | *.lo ) ;; - *) - # Do a test to see if this is really a libtool program. - if func_ltwrapper_script_p "$file"; then - func_source "$file" - # Transform arg to wrapped name. - file="$progdir/$program" - elif func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - func_source "$func_ltwrapper_scriptname_result" - # Transform arg to wrapped name. - file="$progdir/$program" - fi - ;; - esac - # Quote arguments (to preserve shell metacharacters). - func_append_quoted args "$file" - done - - if test "X$opt_dry_run" = Xfalse; then - if test -n "$shlibpath_var"; then - # Export the shlibpath_var. - eval "export $shlibpath_var" - fi - - # Restore saved environment variables - for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES - do - eval "if test \"\${save_$lt_var+set}\" = set; then - $lt_var=\$save_$lt_var; export $lt_var - else - $lt_unset $lt_var - fi" - done - - # Now prepare to actually exec the command. - exec_cmd="\$cmd$args" - else - # Display what would be done. - if test -n "$shlibpath_var"; then - eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" - echo "export $shlibpath_var" - fi - $ECHO "$cmd$args" - exit $EXIT_SUCCESS - fi -} - -test "$opt_mode" = execute && func_mode_execute ${1+"$@"} - - -# func_mode_finish arg... -func_mode_finish () -{ - $opt_debug - libs= - libdirs= - admincmds= - - for opt in "$nonopt" ${1+"$@"} - do - if test -d "$opt"; then - func_append libdirs " $opt" - - elif test -f "$opt"; then - if func_lalib_unsafe_p "$opt"; then - func_append libs " $opt" - else - func_warning "\`$opt' is not a valid libtool archive" - fi - - else - func_fatal_error "invalid argument \`$opt'" - fi - done - - if test -n "$libs"; then - if test -n "$lt_sysroot"; then - sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` - sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" - else - sysroot_cmd= - fi - - # Remove sysroot references - if $opt_dry_run; then - for lib in $libs; do - echo "removing references to $lt_sysroot and \`=' prefixes from $lib" - done - else - tmpdir=`func_mktempdir` - for lib in $libs; do - sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ - > $tmpdir/tmp-la - mv -f $tmpdir/tmp-la $lib - done - ${RM}r "$tmpdir" - fi - fi - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - for libdir in $libdirs; do - if test -n "$finish_cmds"; then - # Do each command in the finish commands. - func_execute_cmds "$finish_cmds" 'admincmds="$admincmds -'"$cmd"'"' - fi - if test -n "$finish_eval"; then - # Do the single finish_eval. - eval cmds=\"$finish_eval\" - $opt_dry_run || eval "$cmds" || func_append admincmds " - $cmds" - fi - done - fi - - # Exit here if they wanted silent mode. - $opt_silent && exit $EXIT_SUCCESS - - if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then - echo "----------------------------------------------------------------------" - echo "Libraries have been installed in:" - for libdir in $libdirs; do - $ECHO " $libdir" - done - echo - echo "If you ever happen to want to link against installed libraries" - echo "in a given directory, LIBDIR, you must either use libtool, and" - echo "specify the full pathname of the library, or use the \`-LLIBDIR'" - echo "flag during linking and do at least one of the following:" - if test -n "$shlibpath_var"; then - echo " - add LIBDIR to the \`$shlibpath_var' environment variable" - echo " during execution" - fi - if test -n "$runpath_var"; then - echo " - add LIBDIR to the \`$runpath_var' environment variable" - echo " during linking" - fi - if test -n "$hardcode_libdir_flag_spec"; then - libdir=LIBDIR - eval flag=\"$hardcode_libdir_flag_spec\" - - $ECHO " - use the \`$flag' linker flag" - fi - if test -n "$admincmds"; then - $ECHO " - have your system administrator run these commands:$admincmds" - fi - if test -f /etc/ld.so.conf; then - echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" - fi - echo - - echo "See any operating system documentation about shared libraries for" - case $host in - solaris2.[6789]|solaris2.1[0-9]) - echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" - echo "pages." - ;; - *) - echo "more information, such as the ld(1) and ld.so(8) manual pages." - ;; - esac - echo "----------------------------------------------------------------------" - fi - exit $EXIT_SUCCESS -} - -test "$opt_mode" = finish && func_mode_finish ${1+"$@"} - - -# func_mode_install arg... -func_mode_install () -{ - $opt_debug - # There may be an optional sh(1) argument at the beginning of - # install_prog (especially on Windows NT). - if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || - # Allow the use of GNU shtool's install command. - case $nonopt in *shtool*) :;; *) false;; esac; then - # Aesthetically quote it. - func_quote_for_eval "$nonopt" - install_prog="$func_quote_for_eval_result " - arg=$1 - shift - else - install_prog= - arg=$nonopt - fi - - # The real first argument should be the name of the installation program. - # Aesthetically quote it. - func_quote_for_eval "$arg" - func_append install_prog "$func_quote_for_eval_result" - install_shared_prog=$install_prog - case " $install_prog " in - *[\\\ /]cp\ *) install_cp=: ;; - *) install_cp=false ;; - esac - - # We need to accept at least all the BSD install flags. - dest= - files= - opts= - prev= - install_type= - isdir=no - stripme= - no_mode=: - for arg - do - arg2= - if test -n "$dest"; then - func_append files " $dest" - dest=$arg - continue - fi - - case $arg in - -d) isdir=yes ;; - -f) - if $install_cp; then :; else - prev=$arg - fi - ;; - -g | -m | -o) - prev=$arg - ;; - -s) - stripme=" -s" - continue - ;; - -*) - ;; - *) - # If the previous option needed an argument, then skip it. - if test -n "$prev"; then - if test "x$prev" = x-m && test -n "$install_override_mode"; then - arg2=$install_override_mode - no_mode=false - fi - prev= - else - dest=$arg - continue - fi - ;; - esac - - # Aesthetically quote the argument. - func_quote_for_eval "$arg" - func_append install_prog " $func_quote_for_eval_result" - if test -n "$arg2"; then - func_quote_for_eval "$arg2" - fi - func_append install_shared_prog " $func_quote_for_eval_result" - done - - test -z "$install_prog" && \ - func_fatal_help "you must specify an install program" - - test -n "$prev" && \ - func_fatal_help "the \`$prev' option requires an argument" - - if test -n "$install_override_mode" && $no_mode; then - if $install_cp; then :; else - func_quote_for_eval "$install_override_mode" - func_append install_shared_prog " -m $func_quote_for_eval_result" - fi - fi - - if test -z "$files"; then - if test -z "$dest"; then - func_fatal_help "no file or destination specified" - else - func_fatal_help "you must specify a destination" - fi - fi - - # Strip any trailing slash from the destination. - func_stripname '' '/' "$dest" - dest=$func_stripname_result - - # Check to see that the destination is a directory. - test -d "$dest" && isdir=yes - if test "$isdir" = yes; then - destdir="$dest" - destname= - else - func_dirname_and_basename "$dest" "" "." - destdir="$func_dirname_result" - destname="$func_basename_result" - - # Not a directory, so check to see that there is only one file specified. - set dummy $files; shift - test "$#" -gt 1 && \ - func_fatal_help "\`$dest' is not a directory" - fi - case $destdir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - for file in $files; do - case $file in - *.lo) ;; - *) - func_fatal_help "\`$destdir' must be an absolute directory name" - ;; - esac - done - ;; - esac - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - staticlibs= - future_libdirs= - current_libdirs= - for file in $files; do - - # Do each installation. - case $file in - *.$libext) - # Do the static libraries later. - func_append staticlibs " $file" - ;; - - *.la) - func_resolve_sysroot "$file" - file=$func_resolve_sysroot_result - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$file" \ - || func_fatal_help "\`$file' is not a valid libtool archive" - - library_names= - old_library= - relink_command= - func_source "$file" - - # Add the libdir to current_libdirs if it is the destination. - if test "X$destdir" = "X$libdir"; then - case "$current_libdirs " in - *" $libdir "*) ;; - *) func_append current_libdirs " $libdir" ;; - esac - else - # Note the libdir as a future libdir. - case "$future_libdirs " in - *" $libdir "*) ;; - *) func_append future_libdirs " $libdir" ;; - esac - fi - - func_dirname "$file" "/" "" - dir="$func_dirname_result" - func_append dir "$objdir" - - if test -n "$relink_command"; then - # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` - - # Don't allow the user to place us outside of our expected - # location b/c this prevents finding dependent libraries that - # are installed to the same prefix. - # At present, this check doesn't affect windows .dll's that - # are installed into $libdir/../bin (currently, that works fine) - # but it's something to keep an eye on. - test "$inst_prefix_dir" = "$destdir" && \ - func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" - - if test -n "$inst_prefix_dir"; then - # Stick the inst_prefix_dir data into the link command. - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` - else - relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` - fi - - func_warning "relinking \`$file'" - func_show_eval "$relink_command" \ - 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' - fi - - # See the names of the shared library. - set dummy $library_names; shift - if test -n "$1"; then - realname="$1" - shift - - srcname="$realname" - test -n "$relink_command" && srcname="$realname"T - - # Install the shared library and build the symlinks. - func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ - 'exit $?' - tstripme="$stripme" - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - case $realname in - *.dll.a) - tstripme="" - ;; - esac - ;; - esac - if test -n "$tstripme" && test -n "$striplib"; then - func_show_eval "$striplib $destdir/$realname" 'exit $?' - fi - - if test "$#" -gt 0; then - # Delete the old symlinks, and create new ones. - # Try `ln -sf' first, because the `ln' binary might depend on - # the symlink we replace! Solaris /bin/ln does not understand -f, - # so we also need to try rm && ln -s. - for linkname - do - test "$linkname" != "$realname" \ - && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" - done - fi - - # Do each command in the postinstall commands. - lib="$destdir/$realname" - func_execute_cmds "$postinstall_cmds" 'exit $?' - fi - - # Install the pseudo-library for information purposes. - func_basename "$file" - name="$func_basename_result" - instname="$dir/$name"i - func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' - - # Maybe install the static library, too. - test -n "$old_library" && func_append staticlibs " $dir/$old_library" - ;; - - *.lo) - # Install (i.e. copy) a libtool object. - - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" - fi - - # Deduce the name of the destination old-style object file. - case $destfile in - *.lo) - func_lo2o "$destfile" - staticdest=$func_lo2o_result - ;; - *.$objext) - staticdest="$destfile" - destfile= - ;; - *) - func_fatal_help "cannot copy a libtool object to \`$destfile'" - ;; - esac - - # Install the libtool object if requested. - test -n "$destfile" && \ - func_show_eval "$install_prog $file $destfile" 'exit $?' - - # Install the old object if enabled. - if test "$build_old_libs" = yes; then - # Deduce the name of the old-style object file. - func_lo2o "$file" - staticobj=$func_lo2o_result - func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' - fi - exit $EXIT_SUCCESS - ;; - - *) - # Figure out destination file name, if it wasn't already specified. - if test -n "$destname"; then - destfile="$destdir/$destname" - else - func_basename "$file" - destfile="$func_basename_result" - destfile="$destdir/$destfile" - fi - - # If the file is missing, and there is a .exe on the end, strip it - # because it is most likely a libtool script we actually want to - # install - stripped_ext="" - case $file in - *.exe) - if test ! -f "$file"; then - func_stripname '' '.exe' "$file" - file=$func_stripname_result - stripped_ext=".exe" - fi - ;; - esac - - # Do a test to see if this is really a libtool program. - case $host in - *cygwin* | *mingw*) - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - wrapper=$func_ltwrapper_scriptname_result - else - func_stripname '' '.exe' "$file" - wrapper=$func_stripname_result - fi - ;; - *) - wrapper=$file - ;; - esac - if func_ltwrapper_script_p "$wrapper"; then - notinst_deplibs= - relink_command= - - func_source "$wrapper" - - # Check the variables that should have been set. - test -z "$generated_by_libtool_version" && \ - func_fatal_error "invalid libtool wrapper script \`$wrapper'" - - finalize=yes - for lib in $notinst_deplibs; do - # Check to see that each library is installed. - libdir= - if test -f "$lib"; then - func_source "$lib" - fi - libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test - if test -n "$libdir" && test ! -f "$libfile"; then - func_warning "\`$lib' has not been installed in \`$libdir'" - finalize=no - fi - done - - relink_command= - func_source "$wrapper" - - outputname= - if test "$fast_install" = no && test -n "$relink_command"; then - $opt_dry_run || { - if test "$finalize" = yes; then - tmpdir=`func_mktempdir` - func_basename "$file$stripped_ext" - file="$func_basename_result" - outputname="$tmpdir/$file" - # Replace the output file specification. - relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` - - $opt_silent || { - func_quote_for_expand "$relink_command" - eval "func_echo $func_quote_for_expand_result" - } - if eval "$relink_command"; then : - else - func_error "error: relink \`$file' with the above command before installing it" - $opt_dry_run || ${RM}r "$tmpdir" - continue - fi - file="$outputname" - else - func_warning "cannot relink \`$file'" - fi - } - else - # Install the binary that we compiled earlier. - file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` - fi - fi - - # remove .exe since cygwin /usr/bin/install will append another - # one anyway - case $install_prog,$host in - */usr/bin/install*,*cygwin*) - case $file:$destfile in - *.exe:*.exe) - # this is ok - ;; - *.exe:*) - destfile=$destfile.exe - ;; - *:*.exe) - func_stripname '' '.exe' "$destfile" - destfile=$func_stripname_result - ;; - esac - ;; - esac - func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' - $opt_dry_run || if test -n "$outputname"; then - ${RM}r "$tmpdir" - fi - ;; - esac - done - - for file in $staticlibs; do - func_basename "$file" - name="$func_basename_result" - - # Set up the ranlib parameters. - oldlib="$destdir/$name" - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - - func_show_eval "$install_prog \$file \$oldlib" 'exit $?' - - if test -n "$stripme" && test -n "$old_striplib"; then - func_show_eval "$old_striplib $tool_oldlib" 'exit $?' - fi - - # Do each command in the postinstall commands. - func_execute_cmds "$old_postinstall_cmds" 'exit $?' - done - - test -n "$future_libdirs" && \ - func_warning "remember to run \`$progname --finish$future_libdirs'" - - if test -n "$current_libdirs"; then - # Maybe just do a dry run. - $opt_dry_run && current_libdirs=" -n$current_libdirs" - exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' - else - exit $EXIT_SUCCESS - fi -} - -test "$opt_mode" = install && func_mode_install ${1+"$@"} - - -# func_generate_dlsyms outputname originator pic_p -# Extract symbols from dlprefiles and create ${outputname}S.o with -# a dlpreopen symbol table. -func_generate_dlsyms () -{ - $opt_debug - my_outputname="$1" - my_originator="$2" - my_pic_p="${3-no}" - my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` - my_dlsyms= - - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - if test -n "$NM" && test -n "$global_symbol_pipe"; then - my_dlsyms="${my_outputname}S.c" - else - func_error "not configured to extract global symbols from dlpreopened files" - fi - fi - - if test -n "$my_dlsyms"; then - case $my_dlsyms in - "") ;; - *.c) - # Discover the nlist of each of the dlfiles. - nlist="$output_objdir/${my_outputname}.nm" - - func_show_eval "$RM $nlist ${nlist}S ${nlist}T" - - # Parse the name list into a source file. - func_verbose "creating $output_objdir/$my_dlsyms" - - $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ -/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ -/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ - -#ifdef __cplusplus -extern \"C\" { -#endif - -#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) -#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" -#endif - -/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) -/* DATA imports from DLLs on WIN32 con't be const, because runtime - relocations are performed -- see ld's documentation on pseudo-relocs. */ -# define LT_DLSYM_CONST -#elif defined(__osf__) -/* This system does not cope well with relocations in const data. */ -# define LT_DLSYM_CONST -#else -# define LT_DLSYM_CONST const -#endif - -/* External symbol declarations for the compiler. */\ -" - - if test "$dlself" = yes; then - func_verbose "generating symbol list for \`$output'" - - $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" - - # Add our own program objects to the symbol list. - progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` - for progfile in $progfiles; do - func_to_tool_file "$progfile" func_convert_file_msys_to_w32 - func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" - $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" - done - - if test -n "$exclude_expsyms"; then - $opt_dry_run || { - eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - if test -n "$export_symbols_regex"; then - $opt_dry_run || { - eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - } - fi - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - export_symbols="$output_objdir/$outputname.exp" - $opt_dry_run || { - $RM $export_symbols - eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' - ;; - esac - } - else - $opt_dry_run || { - eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' - eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' - eval '$MV "$nlist"T "$nlist"' - case $host in - *cygwin* | *mingw* | *cegcc* ) - eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' - eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' - ;; - esac - } - fi - fi - - for dlprefile in $dlprefiles; do - func_verbose "extracting global C symbols from \`$dlprefile'" - func_basename "$dlprefile" - name="$func_basename_result" - case $host in - *cygwin* | *mingw* | *cegcc* ) - # if an import library, we need to obtain dlname - if func_win32_import_lib_p "$dlprefile"; then - func_tr_sh "$dlprefile" - eval "curr_lafile=\$libfile_$func_tr_sh_result" - dlprefile_dlbasename="" - if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then - # Use subshell, to avoid clobbering current variable values - dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` - if test -n "$dlprefile_dlname" ; then - func_basename "$dlprefile_dlname" - dlprefile_dlbasename="$func_basename_result" - else - # no lafile. user explicitly requested -dlpreopen . - $sharedlib_from_linklib_cmd "$dlprefile" - dlprefile_dlbasename=$sharedlib_from_linklib_result - fi - fi - $opt_dry_run || { - if test -n "$dlprefile_dlbasename" ; then - eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' - else - func_warning "Could not compute DLL name from $name" - eval '$ECHO ": $name " >> "$nlist"' - fi - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | - $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" - } - else # not an import lib - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - fi - ;; - *) - $opt_dry_run || { - eval '$ECHO ": $name " >> "$nlist"' - func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 - eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" - } - ;; - esac - done - - $opt_dry_run || { - # Make sure we have at least an empty file. - test -f "$nlist" || : > "$nlist" - - if test -n "$exclude_expsyms"; then - $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T - $MV "$nlist"T "$nlist" - fi - - # Try sorting and uniquifying the output. - if $GREP -v "^: " < "$nlist" | - if sort -k 3 /dev/null 2>&1; then - sort -k 3 - else - sort +2 - fi | - uniq > "$nlist"S; then - : - else - $GREP -v "^: " < "$nlist" > "$nlist"S - fi - - if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' - else - echo '/* NONE */' >> "$output_objdir/$my_dlsyms" - fi - - echo >> "$output_objdir/$my_dlsyms" "\ - -/* The mapping between symbol names and symbols. */ -typedef struct { - const char *name; - void *address; -} lt_dlsymlist; -extern LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[]; -LT_DLSYM_CONST lt_dlsymlist -lt_${my_prefix}_LTX_preloaded_symbols[] = -{\ - { \"$my_originator\", (void *) 0 }," - - case $need_lib_prefix in - no) - eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - *) - eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" - ;; - esac - echo >> "$output_objdir/$my_dlsyms" "\ - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt_${my_prefix}_LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif\ -" - } # !$opt_dry_run - - pic_flag_for_symtable= - case "$compile_command " in - *" -static "*) ;; - *) - case $host in - # compiling the symbol table file with pic_flag works around - # a FreeBSD bug that causes programs to crash when -lm is - # linked before any other PIC object. But we must not use - # pic_flag when linking with -static. The problem exists in - # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. - *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) - pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; - *-*-hpux*) - pic_flag_for_symtable=" $pic_flag" ;; - *) - if test "X$my_pic_p" != Xno; then - pic_flag_for_symtable=" $pic_flag" - fi - ;; - esac - ;; - esac - symtab_cflags= - for arg in $LTCFLAGS; do - case $arg in - -pie | -fpie | -fPIE) ;; - *) func_append symtab_cflags " $arg" ;; - esac - done - - # Now compile the dynamic symbol file. - func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' - - # Clean up the generated files. - func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' - - # Transform the symbol file into the correct name. - symfileobj="$output_objdir/${my_outputname}S.$objext" - case $host in - *cygwin* | *mingw* | *cegcc* ) - if test -f "$output_objdir/$my_outputname.def"; then - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - else - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - fi - ;; - *) - compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` - ;; - esac - ;; - *) - func_fatal_error "unknown suffix for \`$my_dlsyms'" - ;; - esac - else - # We keep going just in case the user didn't refer to - # lt_preloaded_symbols. The linker will fail if global_symbol_pipe - # really was required. - - # Nullify the symbol file. - compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` - finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` - fi -} - -# func_win32_libid arg -# return the library type of file 'arg' -# -# Need a lot of goo to handle *both* DLLs and import libs -# Has to be a shell function in order to 'eat' the argument -# that is supplied when $file_magic_command is called. -# Despite the name, also deal with 64 bit binaries. -func_win32_libid () -{ - $opt_debug - win32_libid_type="unknown" - win32_fileres=`file -L $1 2>/dev/null` - case $win32_fileres in - *ar\ archive\ import\ library*) # definitely import - win32_libid_type="x86 archive import" - ;; - *ar\ archive*) # could be an import, or static - # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. - if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then - func_to_tool_file "$1" func_convert_file_msys_to_w32 - win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | - $SED -n -e ' - 1,100{ - / I /{ - s,.*,import, - p - q - } - }'` - case $win32_nmres in - import*) win32_libid_type="x86 archive import";; - *) win32_libid_type="x86 archive static";; - esac - fi - ;; - *DLL*) - win32_libid_type="x86 DLL" - ;; - *executable*) # but shell scripts are "executable" too... - case $win32_fileres in - *MS\ Windows\ PE\ Intel*) - win32_libid_type="x86 DLL" - ;; - esac - ;; - esac - $ECHO "$win32_libid_type" -} - -# func_cygming_dll_for_implib ARG -# -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib () -{ - $opt_debug - sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` -} - -# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs -# -# The is the core of a fallback implementation of a -# platform-specific function to extract the name of the -# DLL associated with the specified import library LIBNAME. -# -# SECTION_NAME is either .idata$6 or .idata$7, depending -# on the platform and compiler that created the implib. -# -# Echos the name of the DLL associated with the -# specified import library. -func_cygming_dll_for_implib_fallback_core () -{ - $opt_debug - match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` - $OBJDUMP -s --section "$1" "$2" 2>/dev/null | - $SED '/^Contents of section '"$match_literal"':/{ - # Place marker at beginning of archive member dllname section - s/.*/====MARK====/ - p - d - } - # These lines can sometimes be longer than 43 characters, but - # are always uninteresting - /:[ ]*file format pe[i]\{,1\}-/d - /^In archive [^:]*:/d - # Ensure marker is printed - /^====MARK====/p - # Remove all lines with less than 43 characters - /^.\{43\}/!d - # From remaining lines, remove first 43 characters - s/^.\{43\}//' | - $SED -n ' - # Join marker and all lines until next marker into a single line - /^====MARK====/ b para - H - $ b para - b - :para - x - s/\n//g - # Remove the marker - s/^====MARK====// - # Remove trailing dots and whitespace - s/[\. \t]*$// - # Print - /./p' | - # we now have a list, one entry per line, of the stringified - # contents of the appropriate section of all members of the - # archive which possess that section. Heuristic: eliminate - # all those which have a first or second character that is - # a '.' (that is, objdump's representation of an unprintable - # character.) This should work for all archives with less than - # 0x302f exports -- but will fail for DLLs whose name actually - # begins with a literal '.' or a single character followed by - # a '.'. - # - # Of those that remain, print the first one. - $SED -e '/^\./d;/^.\./d;q' -} - -# func_cygming_gnu_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is a GNU/binutils-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_gnu_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` - test -n "$func_cygming_gnu_implib_tmp" -} - -# func_cygming_ms_implib_p ARG -# This predicate returns with zero status (TRUE) if -# ARG is an MS-style import library. Returns -# with nonzero status (FALSE) otherwise. -func_cygming_ms_implib_p () -{ - $opt_debug - func_to_tool_file "$1" func_convert_file_msys_to_w32 - func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` - test -n "$func_cygming_ms_implib_tmp" -} - -# func_cygming_dll_for_implib_fallback ARG -# Platform-specific function to extract the -# name of the DLL associated with the specified -# import library ARG. -# -# This fallback implementation is for use when $DLLTOOL -# does not support the --identify-strict option. -# Invoked by eval'ing the libtool variable -# $sharedlib_from_linklib_cmd -# Result is available in the variable -# $sharedlib_from_linklib_result -func_cygming_dll_for_implib_fallback () -{ - $opt_debug - if func_cygming_gnu_implib_p "$1" ; then - # binutils import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` - elif func_cygming_ms_implib_p "$1" ; then - # ms-generated import library - sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` - else - # unknown - sharedlib_from_linklib_result="" - fi -} - - -# func_extract_an_archive dir oldlib -func_extract_an_archive () -{ - $opt_debug - f_ex_an_ar_dir="$1"; shift - f_ex_an_ar_oldlib="$1" - if test "$lock_old_archive_extraction" = yes; then - lockfile=$f_ex_an_ar_oldlib.lock - until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do - func_echo "Waiting for $lockfile to be removed" - sleep 2 - done - fi - func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ - 'stat=$?; rm -f "$lockfile"; exit $stat' - if test "$lock_old_archive_extraction" = yes; then - $opt_dry_run || rm -f "$lockfile" - fi - if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then - : - else - func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" - fi -} - - -# func_extract_archives gentop oldlib ... -func_extract_archives () -{ - $opt_debug - my_gentop="$1"; shift - my_oldlibs=${1+"$@"} - my_oldobjs="" - my_xlib="" - my_xabs="" - my_xdir="" - - for my_xlib in $my_oldlibs; do - # Extract the objects. - case $my_xlib in - [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; - *) my_xabs=`pwd`"/$my_xlib" ;; - esac - func_basename "$my_xlib" - my_xlib="$func_basename_result" - my_xlib_u=$my_xlib - while :; do - case " $extracted_archives " in - *" $my_xlib_u "*) - func_arith $extracted_serial + 1 - extracted_serial=$func_arith_result - my_xlib_u=lt$extracted_serial-$my_xlib ;; - *) break ;; - esac - done - extracted_archives="$extracted_archives $my_xlib_u" - my_xdir="$my_gentop/$my_xlib_u" - - func_mkdir_p "$my_xdir" - - case $host in - *-darwin*) - func_verbose "Extracting $my_xabs" - # Do not bother doing anything if just a dry run - $opt_dry_run || { - darwin_orig_dir=`pwd` - cd $my_xdir || exit $? - darwin_archive=$my_xabs - darwin_curdir=`pwd` - darwin_base_archive=`basename "$darwin_archive"` - darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` - if test -n "$darwin_arches"; then - darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` - darwin_arch= - func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" - for darwin_arch in $darwin_arches ; do - func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" - $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" - cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" - func_extract_an_archive "`pwd`" "${darwin_base_archive}" - cd "$darwin_curdir" - $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" - done # $darwin_arches - ## Okay now we've a bunch of thin objects, gotta fatten them up :) - darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` - darwin_file= - darwin_files= - for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` - $LIPO -create -output "$darwin_file" $darwin_files - done # $darwin_filelist - $RM -rf unfat-$$ - cd "$darwin_orig_dir" - else - cd $darwin_orig_dir - func_extract_an_archive "$my_xdir" "$my_xabs" - fi # $darwin_arches - } # !$opt_dry_run - ;; - *) - func_extract_an_archive "$my_xdir" "$my_xabs" - ;; - esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` - done - - func_extract_archives_result="$my_oldobjs" -} - - -# func_emit_wrapper [arg=no] -# -# Emit a libtool wrapper script on stdout. -# Don't directly open a file because we may want to -# incorporate the script contents within a cygwin/mingw -# wrapper executable. Must ONLY be called from within -# func_mode_link because it depends on a number of variables -# set therein. -# -# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR -# variable will take. If 'yes', then the emitted script -# will assume that the directory in which it is stored is -# the $objdir directory. This is a cygwin/mingw-specific -# behavior. -func_emit_wrapper () -{ - func_emit_wrapper_arg1=${1-no} - - $ECHO "\ -#! $SHELL - -# $output - temporary wrapper script for $objdir/$outputname -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION -# -# The $output program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='$sed_quote_subst' - -# Be Bourne compatible -if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command=\"$relink_command\" - -# This environment variable determines our operation mode. -if test \"\$libtool_install_magic\" = \"$magic\"; then - # install mode needs the following variables: - generated_by_libtool_version='$macro_version' - notinst_deplibs='$notinst_deplibs' -else - # When we are sourced in execute mode, \$file and \$ECHO are already set. - if test \"\$libtool_execute_magic\" != \"$magic\"; then - file=\"\$0\"" - - qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` - $ECHO "\ - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -\$1 -_LTECHO_EOF' -} - ECHO=\"$qECHO\" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ which is used only on -# windows platforms, and (c) all begin with the string "--lt-" -# (application programs are unlikely to have options which match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's $0 value, followed by "$@". -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=\$0 - shift - for lt_opt - do - case \"\$lt_opt\" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` - test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. - lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` - cat \"\$lt_dump_D/\$lt_dump_F\" - exit 0 - ;; - --lt-*) - \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n \"\$lt_option_debug\"; then - echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" - lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2* | *-cegcc*) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $ECHO "\ - if test -n \"\$lt_option_debug\"; then - \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 - func_lt_dump_args \${1+\"\$@\"} 1>&2 - fi - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $ECHO "\ - \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from \$@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case \" \$* \" in - *\\ --lt-*) - for lt_wr_arg - do - case \$lt_wr_arg in - --lt-*) ;; - *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; - esac - shift - done ;; - esac - func_exec_program_core \${1+\"\$@\"} -} - - # Parse options - func_parse_lt_options \"\$0\" \${1+\"\$@\"} - - # Find the directory that this script lives in. - thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` - test \"x\$thisdir\" = \"x\$file\" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` - while test -n \"\$file\"; do - destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` - - # If there was a directory component, then change thisdir. - if test \"x\$destdir\" != \"x\$file\"; then - case \"\$destdir\" in - [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; - *) thisdir=\"\$thisdir/\$destdir\" ;; - esac - fi - - file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 - if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then - # special case for '.' - if test \"\$thisdir\" = \".\"; then - thisdir=\`pwd\` - fi - # remove .libs from thisdir - case \"\$thisdir\" in - *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; - $objdir ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=\`cd \"\$thisdir\" && pwd\` - test -n \"\$absdir\" && thisdir=\"\$absdir\" -" - - if test "$fast_install" = yes; then - $ECHO "\ - program=lt-'$outputname'$exeext - progdir=\"\$thisdir/$objdir\" - - if test ! -f \"\$progdir/\$program\" || - { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ - test \"X\$file\" != \"X\$progdir/\$program\"; }; then - - file=\"\$\$-\$program\" - - if test ! -d \"\$progdir\"; then - $MKDIR \"\$progdir\" - else - $RM \"\$progdir/\$file\" - fi" - - $ECHO "\ - - # relink executable if necessary - if test -n \"\$relink_command\"; then - if relink_command_output=\`eval \$relink_command 2>&1\`; then : - else - $ECHO \"\$relink_command_output\" >&2 - $RM \"\$progdir/\$file\" - exit 1 - fi - fi - - $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || - { $RM \"\$progdir/\$program\"; - $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } - $RM \"\$progdir/\$file\" - fi" - else - $ECHO "\ - program='$outputname' - progdir=\"\$thisdir/$objdir\" -" - fi - - $ECHO "\ - - if test -f \"\$progdir/\$program\"; then" - - # fixup the dll searchpath if we need to. - # - # Fix the DLL searchpath if we need to. Do this before prepending - # to shlibpath, because on Windows, both are PATH and uninstalled - # libraries must come first. - if test -n "$dllsearchpath"; then - $ECHO "\ - # Add the dll search path components to the executable PATH - PATH=$dllsearchpath:\$PATH -" - fi - - # Export our shlibpath_var if we have one. - if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then - $ECHO "\ - # Add our own library path to $shlibpath_var - $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" - - # Some systems cannot cope with colon-terminated $shlibpath_var - # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` - - export $shlibpath_var -" - fi - - $ECHO "\ - if test \"\$libtool_execute_magic\" != \"$magic\"; then - # Run the actual program with our arguments. - func_exec_program \${1+\"\$@\"} - fi - else - # The program doesn't exist. - \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 - \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 - \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 - exit 1 - fi -fi\ -" -} - - -# func_emit_cwrapperexe_src -# emit the source code for a wrapper executable on stdout -# Must ONLY be called from within func_mode_link because -# it depends on a number of variable set therein. -func_emit_cwrapperexe_src () -{ - cat < -#include -#ifdef _MSC_VER -# include -# include -# include -#else -# include -# include -# ifdef __CYGWIN__ -# include -# endif -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -/* declarations of non-ANSI functions */ -#if defined(__MINGW32__) -# ifdef __STRICT_ANSI__ -int _putenv (const char *); -# endif -#elif defined(__CYGWIN__) -# ifdef __STRICT_ANSI__ -char *realpath (const char *, char *); -int putenv (char *); -int setenv (const char *, const char *, int); -# endif -/* #elif defined (other platforms) ... */ -#endif - -/* portability defines, excluding path handling macros */ -#if defined(_MSC_VER) -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -# define S_IXUSR _S_IEXEC -# ifndef _INTPTR_T_DEFINED -# define _INTPTR_T_DEFINED -# define intptr_t int -# endif -#elif defined(__MINGW32__) -# define setmode _setmode -# define stat _stat -# define chmod _chmod -# define getcwd _getcwd -# define putenv _putenv -#elif defined(__CYGWIN__) -# define HAVE_SETENV -# define FOPEN_WB "wb" -/* #elif defined (other platforms) ... */ -#endif - -#if defined(PATH_MAX) -# define LT_PATHMAX PATH_MAX -#elif defined(MAXPATHLEN) -# define LT_PATHMAX MAXPATHLEN -#else -# define LT_PATHMAX 1024 -#endif - -#ifndef S_IXOTH -# define S_IXOTH 0 -#endif -#ifndef S_IXGRP -# define S_IXGRP 0 -#endif - -/* path handling portability macros */ -#ifndef DIR_SEPARATOR -# define DIR_SEPARATOR '/' -# define PATH_SEPARATOR ':' -#endif - -#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ - defined (__OS2__) -# define HAVE_DOS_BASED_FILE_SYSTEM -# define FOPEN_WB "wb" -# ifndef DIR_SEPARATOR_2 -# define DIR_SEPARATOR_2 '\\' -# endif -# ifndef PATH_SEPARATOR_2 -# define PATH_SEPARATOR_2 ';' -# endif -#endif - -#ifndef DIR_SEPARATOR_2 -# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) -#else /* DIR_SEPARATOR_2 */ -# define IS_DIR_SEPARATOR(ch) \ - (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) -#endif /* DIR_SEPARATOR_2 */ - -#ifndef PATH_SEPARATOR_2 -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) -#else /* PATH_SEPARATOR_2 */ -# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) -#endif /* PATH_SEPARATOR_2 */ - -#ifndef FOPEN_WB -# define FOPEN_WB "w" -#endif -#ifndef _O_BINARY -# define _O_BINARY 0 -#endif - -#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) -#define XFREE(stale) do { \ - if (stale) { free ((void *) stale); stale = 0; } \ -} while (0) - -#if defined(LT_DEBUGWRAPPER) -static int lt_debug = 1; -#else -static int lt_debug = 0; -#endif - -const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ - -void *xmalloc (size_t num); -char *xstrdup (const char *string); -const char *base_name (const char *name); -char *find_executable (const char *wrapper); -char *chase_symlinks (const char *pathspec); -int make_executable (const char *path); -int check_executable (const char *path); -char *strendzap (char *str, const char *pat); -void lt_debugprintf (const char *file, int line, const char *fmt, ...); -void lt_fatal (const char *file, int line, const char *message, ...); -static const char *nonnull (const char *s); -static const char *nonempty (const char *s); -void lt_setenv (const char *name, const char *value); -char *lt_extend_str (const char *orig_value, const char *add, int to_end); -void lt_update_exe_path (const char *name, const char *value); -void lt_update_lib_path (const char *name, const char *value); -char **prepare_spawn (char **argv); -void lt_dump_script (FILE *f); -EOF - - cat <= 0) - && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - return 1; - else - return 0; -} - -int -make_executable (const char *path) -{ - int rval = 0; - struct stat st; - - lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", - nonempty (path)); - if ((!path) || (!*path)) - return 0; - - if (stat (path, &st) >= 0) - { - rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); - } - return rval; -} - -/* Searches for the full path of the wrapper. Returns - newly allocated full path name if found, NULL otherwise - Does not chase symlinks, even on platforms that support them. -*/ -char * -find_executable (const char *wrapper) -{ - int has_slash = 0; - const char *p; - const char *p_next; - /* static buffer for getcwd */ - char tmp[LT_PATHMAX + 1]; - int tmp_len; - char *concat_name; - - lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", - nonempty (wrapper)); - - if ((wrapper == NULL) || (*wrapper == '\0')) - return NULL; - - /* Absolute path? */ -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - else - { -#endif - if (IS_DIR_SEPARATOR (wrapper[0])) - { - concat_name = xstrdup (wrapper); - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - } -#endif - - for (p = wrapper; *p; p++) - if (*p == '/') - { - has_slash = 1; - break; - } - if (!has_slash) - { - /* no slashes; search PATH */ - const char *path = getenv ("PATH"); - if (path != NULL) - { - for (p = path; *p; p = p_next) - { - const char *q; - size_t p_len; - for (q = p; *q; q++) - if (IS_PATH_SEPARATOR (*q)) - break; - p_len = q - p; - p_next = (*q == '\0' ? q : q + 1); - if (p_len == 0) - { - /* empty path: current directory */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = - XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - } - else - { - concat_name = - XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, p, p_len); - concat_name[p_len] = '/'; - strcpy (concat_name + p_len + 1, wrapper); - } - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - } - } - /* not found in PATH; assume curdir */ - } - /* Relative path | not found in path: prepend cwd */ - if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", - nonnull (strerror (errno))); - tmp_len = strlen (tmp); - concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); - memcpy (concat_name, tmp, tmp_len); - concat_name[tmp_len] = '/'; - strcpy (concat_name + tmp_len + 1, wrapper); - - if (check_executable (concat_name)) - return concat_name; - XFREE (concat_name); - return NULL; -} - -char * -chase_symlinks (const char *pathspec) -{ -#ifndef S_ISLNK - return xstrdup (pathspec); -#else - char buf[LT_PATHMAX]; - struct stat s; - char *tmp_pathspec = xstrdup (pathspec); - char *p; - int has_symlinks = 0; - while (strlen (tmp_pathspec) && !has_symlinks) - { - lt_debugprintf (__FILE__, __LINE__, - "checking path component for symlinks: %s\n", - tmp_pathspec); - if (lstat (tmp_pathspec, &s) == 0) - { - if (S_ISLNK (s.st_mode) != 0) - { - has_symlinks = 1; - break; - } - - /* search backwards for last DIR_SEPARATOR */ - p = tmp_pathspec + strlen (tmp_pathspec) - 1; - while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - p--; - if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) - { - /* no more DIR_SEPARATORS left */ - break; - } - *p = '\0'; - } - else - { - lt_fatal (__FILE__, __LINE__, - "error accessing file \"%s\": %s", - tmp_pathspec, nonnull (strerror (errno))); - } - } - XFREE (tmp_pathspec); - - if (!has_symlinks) - { - return xstrdup (pathspec); - } - - tmp_pathspec = realpath (pathspec, buf); - if (tmp_pathspec == 0) - { - lt_fatal (__FILE__, __LINE__, - "could not follow symlinks for %s", pathspec); - } - return xstrdup (tmp_pathspec); -#endif -} - -char * -strendzap (char *str, const char *pat) -{ - size_t len, patlen; - - assert (str != NULL); - assert (pat != NULL); - - len = strlen (str); - patlen = strlen (pat); - - if (patlen <= len) - { - str += len - patlen; - if (strcmp (str, pat) == 0) - *str = '\0'; - } - return str; -} - -void -lt_debugprintf (const char *file, int line, const char *fmt, ...) -{ - va_list args; - if (lt_debug) - { - (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); - } -} - -static void -lt_error_core (int exit_status, const char *file, - int line, const char *mode, - const char *message, va_list ap) -{ - fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); - vfprintf (stderr, message, ap); - fprintf (stderr, ".\n"); - - if (exit_status >= 0) - exit (exit_status); -} - -void -lt_fatal (const char *file, int line, const char *message, ...) -{ - va_list ap; - va_start (ap, message); - lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); - va_end (ap); -} - -static const char * -nonnull (const char *s) -{ - return s ? s : "(null)"; -} - -static const char * -nonempty (const char *s) -{ - return (s && !*s) ? "(empty)" : nonnull (s); -} - -void -lt_setenv (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_setenv) setting '%s' to '%s'\n", - nonnull (name), nonnull (value)); - { -#ifdef HAVE_SETENV - /* always make a copy, for consistency with !HAVE_SETENV */ - char *str = xstrdup (value); - setenv (name, str, 1); -#else - int len = strlen (name) + 1 + strlen (value) + 1; - char *str = XMALLOC (char, len); - sprintf (str, "%s=%s", name, value); - if (putenv (str) != EXIT_SUCCESS) - { - XFREE (str); - } -#endif - } -} - -char * -lt_extend_str (const char *orig_value, const char *add, int to_end) -{ - char *new_value; - if (orig_value && *orig_value) - { - int orig_value_len = strlen (orig_value); - int add_len = strlen (add); - new_value = XMALLOC (char, add_len + orig_value_len + 1); - if (to_end) - { - strcpy (new_value, orig_value); - strcpy (new_value + orig_value_len, add); - } - else - { - strcpy (new_value, add); - strcpy (new_value + add_len, orig_value); - } - } - else - { - new_value = xstrdup (add); - } - return new_value; -} - -void -lt_update_exe_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - /* some systems can't cope with a ':'-terminated path #' */ - int len = strlen (new_value); - while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) - { - new_value[len-1] = '\0'; - } - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -void -lt_update_lib_path (const char *name, const char *value) -{ - lt_debugprintf (__FILE__, __LINE__, - "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", - nonnull (name), nonnull (value)); - - if (name && *name && value && *value) - { - char *new_value = lt_extend_str (getenv (name), value, 0); - lt_setenv (name, new_value); - XFREE (new_value); - } -} - -EOF - case $host_os in - mingw*) - cat <<"EOF" - -/* Prepares an argument vector before calling spawn(). - Note that spawn() does not by itself call the command interpreter - (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : - ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&v); - v.dwPlatformId == VER_PLATFORM_WIN32_NT; - }) ? "cmd.exe" : "command.com"). - Instead it simply concatenates the arguments, separated by ' ', and calls - CreateProcess(). We must quote the arguments since Win32 CreateProcess() - interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a - special way: - - Space and tab are interpreted as delimiters. They are not treated as - delimiters if they are surrounded by double quotes: "...". - - Unescaped double quotes are removed from the input. Their only effect is - that within double quotes, space and tab are treated like normal - characters. - - Backslashes not followed by double quotes are not special. - - But 2*n+1 backslashes followed by a double quote become - n backslashes followed by a double quote (n >= 0): - \" -> " - \\\" -> \" - \\\\\" -> \\" - */ -#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" -char ** -prepare_spawn (char **argv) -{ - size_t argc; - char **new_argv; - size_t i; - - /* Count number of arguments. */ - for (argc = 0; argv[argc] != NULL; argc++) - ; - - /* Allocate new argument vector. */ - new_argv = XMALLOC (char *, argc + 1); - - /* Put quoted arguments into the new argument vector. */ - for (i = 0; i < argc; i++) - { - const char *string = argv[i]; - - if (string[0] == '\0') - new_argv[i] = xstrdup ("\"\""); - else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) - { - int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); - size_t length; - unsigned int backslashes; - const char *s; - char *quoted_string; - char *p; - - length = 0; - backslashes = 0; - if (quote_around) - length++; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - length += backslashes + 1; - length++; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - length += backslashes + 1; - - quoted_string = XMALLOC (char, length + 1); - - p = quoted_string; - backslashes = 0; - if (quote_around) - *p++ = '"'; - for (s = string; *s != '\0'; s++) - { - char c = *s; - if (c == '"') - { - unsigned int j; - for (j = backslashes + 1; j > 0; j--) - *p++ = '\\'; - } - *p++ = c; - if (c == '\\') - backslashes++; - else - backslashes = 0; - } - if (quote_around) - { - unsigned int j; - for (j = backslashes; j > 0; j--) - *p++ = '\\'; - *p++ = '"'; - } - *p = '\0'; - - new_argv[i] = quoted_string; - } - else - new_argv[i] = (char *) string; - } - new_argv[argc] = NULL; - - return new_argv; -} -EOF - ;; - esac - - cat <<"EOF" -void lt_dump_script (FILE* f) -{ -EOF - func_emit_wrapper yes | - $SED -n -e ' -s/^\(.\{79\}\)\(..*\)/\1\ -\2/ -h -s/\([\\"]\)/\\\1/g -s/$/\\n/ -s/\([^\n]*\).*/ fputs ("\1", f);/p -g -D' - cat <<"EOF" -} -EOF -} -# end: func_emit_cwrapperexe_src - -# func_win32_import_lib_p ARG -# True if ARG is an import lib, as indicated by $file_magic_cmd -func_win32_import_lib_p () -{ - $opt_debug - case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in - *import*) : ;; - *) false ;; - esac -} - -# func_mode_link arg... -func_mode_link () -{ - $opt_debug - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - # It is impossible to link a dll without this setting, and - # we shouldn't force the makefile maintainer to figure out - # which system we are compiling for in order to pass an extra - # flag for every libtool invocation. - # allow_undefined=no - - # FIXME: Unfortunately, there are problems with the above when trying - # to make a dll which has undefined symbols, in which case not - # even a static library is built. For now, we need to specify - # -no-undefined on the libtool link line when we can be certain - # that all symbols are satisfied, otherwise we get a static library. - allow_undefined=yes - ;; - *) - allow_undefined=yes - ;; - esac - libtool_args=$nonopt - base_compile="$nonopt $@" - compile_command=$nonopt - finalize_command=$nonopt - - compile_rpath= - finalize_rpath= - compile_shlibpath= - finalize_shlibpath= - convenience= - old_convenience= - deplibs= - old_deplibs= - compiler_flags= - linker_flags= - dllsearchpath= - lib_search_path=`pwd` - inst_prefix_dir= - new_inherited_linker_flags= - - avoid_version=no - bindir= - dlfiles= - dlprefiles= - dlself=no - export_dynamic=no - export_symbols= - export_symbols_regex= - generated= - libobjs= - ltlibs= - module=no - no_install=no - objs= - non_pic_objects= - precious_files_regex= - prefer_static_libs=no - preload=no - prev= - prevarg= - release= - rpath= - xrpath= - perm_rpath= - temp_rpath= - thread_safe=no - vinfo= - vinfo_number=no - weak_libs= - single_module="${wl}-single_module" - func_infer_tag $base_compile - - # We need to know -static, to get the right output filenames. - for arg - do - case $arg in - -shared) - test "$build_libtool_libs" != yes && \ - func_fatal_configuration "can not build a shared library" - build_old_libs=no - break - ;; - -all-static | -static | -static-libtool-libs) - case $arg in - -all-static) - if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then - func_warning "complete static linking is impossible in this configuration" - fi - if test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - -static) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=built - ;; - -static-libtool-libs) - if test -z "$pic_flag" && test -n "$link_static_flag"; then - dlopen_self=$dlopen_self_static - fi - prefer_static_libs=yes - ;; - esac - build_libtool_libs=no - build_old_libs=yes - break - ;; - esac - done - - # See if our shared archives depend on static archives. - test -n "$old_archive_from_new_cmds" && build_old_libs=yes - - # Go through the arguments, transforming them on the way. - while test "$#" -gt 0; do - arg="$1" - shift - func_quote_for_eval "$arg" - qarg=$func_quote_for_eval_unquoted_result - func_append libtool_args " $func_quote_for_eval_result" - - # If the previous option needs an argument, assign it. - if test -n "$prev"; then - case $prev in - output) - func_append compile_command " @OUTPUT@" - func_append finalize_command " @OUTPUT@" - ;; - esac - - case $prev in - bindir) - bindir="$arg" - prev= - continue - ;; - dlfiles|dlprefiles) - if test "$preload" = no; then - # Add the symbol object into the linking commands. - func_append compile_command " @SYMFILE@" - func_append finalize_command " @SYMFILE@" - preload=yes - fi - case $arg in - *.la | *.lo) ;; # We handle these cases below. - force) - if test "$dlself" = no; then - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - self) - if test "$prev" = dlprefiles; then - dlself=yes - elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then - dlself=yes - else - dlself=needless - export_dynamic=yes - fi - prev= - continue - ;; - *) - if test "$prev" = dlfiles; then - func_append dlfiles " $arg" - else - func_append dlprefiles " $arg" - fi - prev= - continue - ;; - esac - ;; - expsyms) - export_symbols="$arg" - test -f "$arg" \ - || func_fatal_error "symbol file \`$arg' does not exist" - prev= - continue - ;; - expsyms_regex) - export_symbols_regex="$arg" - prev= - continue - ;; - framework) - case $host in - *-*-darwin*) - case "$deplibs " in - *" $qarg.ltframework "*) ;; - *) func_append deplibs " $qarg.ltframework" # this is fixed later - ;; - esac - ;; - esac - prev= - continue - ;; - inst_prefix) - inst_prefix_dir="$arg" - prev= - continue - ;; - objectlist) - if test -f "$arg"; then - save_arg=$arg - moreargs= - for fil in `cat "$save_arg"` - do -# func_append moreargs " $fil" - arg=$fil - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "\`$arg' is not a valid libtool object" - fi - fi - done - else - func_fatal_error "link input file \`$arg' does not exist" - fi - arg=$save_arg - prev= - continue - ;; - precious_regex) - precious_files_regex="$arg" - prev= - continue - ;; - release) - release="-$arg" - prev= - continue - ;; - rpath | xrpath) - # We need an absolute path. - case $arg in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - if test "$prev" = rpath; then - case "$rpath " in - *" $arg "*) ;; - *) func_append rpath " $arg" ;; - esac - else - case "$xrpath " in - *" $arg "*) ;; - *) func_append xrpath " $arg" ;; - esac - fi - prev= - continue - ;; - shrext) - shrext_cmds="$arg" - prev= - continue - ;; - weak) - func_append weak_libs " $arg" - prev= - continue - ;; - xcclinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xcompiler) - func_append compiler_flags " $qarg" - prev= - func_append compile_command " $qarg" - func_append finalize_command " $qarg" - continue - ;; - xlinker) - func_append linker_flags " $qarg" - func_append compiler_flags " $wl$qarg" - prev= - func_append compile_command " $wl$qarg" - func_append finalize_command " $wl$qarg" - continue - ;; - *) - eval "$prev=\"\$arg\"" - prev= - continue - ;; - esac - fi # test -n "$prev" - - prevarg="$arg" - - case $arg in - -all-static) - if test -n "$link_static_flag"; then - # See comment for -static flag below, for more details. - func_append compile_command " $link_static_flag" - func_append finalize_command " $link_static_flag" - fi - continue - ;; - - -allow-undefined) - # FIXME: remove this flag sometime in the future. - func_fatal_error "\`-allow-undefined' must not be used because it is the default" - ;; - - -avoid-version) - avoid_version=yes - continue - ;; - - -bindir) - prev=bindir - continue - ;; - - -dlopen) - prev=dlfiles - continue - ;; - - -dlpreopen) - prev=dlprefiles - continue - ;; - - -export-dynamic) - export_dynamic=yes - continue - ;; - - -export-symbols | -export-symbols-regex) - if test -n "$export_symbols" || test -n "$export_symbols_regex"; then - func_fatal_error "more than one -exported-symbols argument is not allowed" - fi - if test "X$arg" = "X-export-symbols"; then - prev=expsyms - else - prev=expsyms_regex - fi - continue - ;; - - -framework) - prev=framework - continue - ;; - - -inst-prefix-dir) - prev=inst_prefix - continue - ;; - - # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* - # so, if we see these flags be careful not to treat them like -L - -L[A-Z][A-Z]*:*) - case $with_gcc/$host in - no/*-*-irix* | /*-*-irix*) - func_append compile_command " $arg" - func_append finalize_command " $arg" - ;; - esac - continue - ;; - - -L*) - func_stripname "-L" '' "$arg" - if test -z "$func_stripname_result"; then - if test "$#" -gt 0; then - func_fatal_error "require no space between \`-L' and \`$1'" - else - func_fatal_error "need path for \`-L' option" - fi - fi - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - *) - absdir=`cd "$dir" && pwd` - test -z "$absdir" && \ - func_fatal_error "cannot determine absolute directory name of \`$dir'" - dir="$absdir" - ;; - esac - case "$deplibs " in - *" -L$dir "* | *" $arg "*) - # Will only happen for absolute or sysroot arguments - ;; - *) - # Preserve sysroot, but never include relative directories - case $dir in - [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; - *) func_append deplibs " -L$dir" ;; - esac - func_append lib_search_path " $dir" - ;; - esac - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$dir:"*) ;; - ::) dllsearchpath=$dir;; - *) func_append dllsearchpath ":$dir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - continue - ;; - - -l*) - if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) - # These systems don't actually have a C or math library (as such) - continue - ;; - *-*-os2*) - # These systems don't actually have a C library (as such) - test "X$arg" = "X-lc" && continue - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C and math libraries are in the System framework - func_append deplibs " System.ltframework" - continue - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - test "X$arg" = "X-lc" && continue - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - test "X$arg" = "X-lc" && continue - ;; - esac - elif test "X$arg" = "X-lc_r"; then - case $host in - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc_r directly, use -pthread flag. - continue - ;; - esac - fi - func_append deplibs " $arg" - continue - ;; - - -module) - module=yes - continue - ;; - - # Tru64 UNIX uses -model [arg] to determine the layout of C++ - # classes, name mangling, and exception handling. - # Darwin uses the -arch flag to determine output architecture. - -model|-arch|-isysroot|--sysroot) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - prev=xcompiler - continue - ;; - - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - func_append compiler_flags " $arg" - func_append compile_command " $arg" - func_append finalize_command " $arg" - case "$new_inherited_linker_flags " in - *" $arg "*) ;; - * ) func_append new_inherited_linker_flags " $arg" ;; - esac - continue - ;; - - -multi_module) - single_module="${wl}-multi_module" - continue - ;; - - -no-fast-install) - fast_install=no - continue - ;; - - -no-install) - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) - # The PATH hackery in wrapper scripts is required on Windows - # and Darwin in order for the loader to find any dlls it needs. - func_warning "\`-no-install' is ignored for $host" - func_warning "assuming \`-no-fast-install' instead" - fast_install=no - ;; - *) no_install=yes ;; - esac - continue - ;; - - -no-undefined) - allow_undefined=no - continue - ;; - - -objectlist) - prev=objectlist - continue - ;; - - -o) prev=output ;; - - -precious-files-regex) - prev=precious_regex - continue - ;; - - -release) - prev=release - continue - ;; - - -rpath) - prev=rpath - continue - ;; - - -R) - prev=xrpath - continue - ;; - - -R*) - func_stripname '-R' '' "$arg" - dir=$func_stripname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) ;; - =*) - func_stripname '=' '' "$dir" - dir=$lt_sysroot$func_stripname_result - ;; - *) - func_fatal_error "only absolute run-paths are allowed" - ;; - esac - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - continue - ;; - - -shared) - # The effects of -shared are defined in a previous loop. - continue - ;; - - -shrext) - prev=shrext - continue - ;; - - -static | -static-libtool-libs) - # The effects of -static are defined in a previous loop. - # We used to do the same as -all-static on platforms that - # didn't have a PIC flag, but the assumption that the effects - # would be equivalent was wrong. It would break on at least - # Digital Unix and AIX. - continue - ;; - - -thread-safe) - thread_safe=yes - continue - ;; - - -version-info) - prev=vinfo - continue - ;; - - -version-number) - prev=vinfo - vinfo_number=yes - continue - ;; - - -weak) - prev=weak - continue - ;; - - -Wc,*) - func_stripname '-Wc,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $func_quote_for_eval_result" - func_append compiler_flags " $func_quote_for_eval_result" - done - IFS="$save_ifs" - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Wl,*) - func_stripname '-Wl,' '' "$arg" - args=$func_stripname_result - arg= - save_ifs="$IFS"; IFS=',' - for flag in $args; do - IFS="$save_ifs" - func_quote_for_eval "$flag" - func_append arg " $wl$func_quote_for_eval_result" - func_append compiler_flags " $wl$func_quote_for_eval_result" - func_append linker_flags " $func_quote_for_eval_result" - done - IFS="$save_ifs" - func_stripname ' ' '' "$arg" - arg=$func_stripname_result - ;; - - -Xcompiler) - prev=xcompiler - continue - ;; - - -Xlinker) - prev=xlinker - continue - ;; - - -XCClinker) - prev=xcclinker - continue - ;; - - # -msg_* for osf cc - -msg_*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - - # Flags to be passed through unchanged, with rationale: - # -64, -mips[0-9] enable 64-bit mode for the SGI compiler - # -r[0-9][0-9]* specify processor for the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler - # +DA*, +DD* enable 64-bit mode for the HP compiler - # -q* compiler args for the IBM compiler - # -m*, -t[45]*, -txscale* architecture-specific flags for GCC - # -F/path path to uninstalled frameworks, gcc on darwin - # -p, -pg, --coverage, -fprofile-* profiling flags for GCC - # @file GCC response files - # -tp=* Portland pgcc target processor selection - # --sysroot=* for sysroot support - # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization - -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-flto*|-fwhopr*|-fuse-linker-plugin) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - func_append compile_command " $arg" - func_append finalize_command " $arg" - func_append compiler_flags " $arg" - continue - ;; - - # Some other compiler flag. - -* | +*) - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - - *.$objext) - # A standard object. - func_append objs " $arg" - ;; - - *.lo) - # A libtool-controlled object. - - # Check to see that this really is a libtool object. - if func_lalib_unsafe_p "$arg"; then - pic_object= - non_pic_object= - - # Read the .lo file - func_source "$arg" - - if test -z "$pic_object" || - test -z "$non_pic_object" || - test "$pic_object" = none && - test "$non_pic_object" = none; then - func_fatal_error "cannot find name of object for \`$arg'" - fi - - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - if test "$pic_object" != none; then - # Prepend the subdirectory the object is found in. - pic_object="$xdir$pic_object" - - if test "$prev" = dlfiles; then - if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then - func_append dlfiles " $pic_object" - prev= - continue - else - # If libtool objects are unsupported, then we need to preload. - prev=dlprefiles - fi - fi - - # CHECK ME: I think I busted this. -Ossama - if test "$prev" = dlprefiles; then - # Preload the old-style object. - func_append dlprefiles " $pic_object" - prev= - fi - - # A PIC object. - func_append libobjs " $pic_object" - arg="$pic_object" - fi - - # Non-PIC object. - if test "$non_pic_object" != none; then - # Prepend the subdirectory the object is found in. - non_pic_object="$xdir$non_pic_object" - - # A standard non-PIC object - func_append non_pic_objects " $non_pic_object" - if test -z "$pic_object" || test "$pic_object" = none ; then - arg="$non_pic_object" - fi - else - # If the PIC object exists, use it instead. - # $xdir was prepended to $pic_object above. - non_pic_object="$pic_object" - func_append non_pic_objects " $non_pic_object" - fi - else - # Only an error if not doing a dry-run. - if $opt_dry_run; then - # Extract subdirectory from the argument. - func_dirname "$arg" "/" "" - xdir="$func_dirname_result" - - func_lo2o "$arg" - pic_object=$xdir$objdir/$func_lo2o_result - non_pic_object=$xdir$func_lo2o_result - func_append libobjs " $pic_object" - func_append non_pic_objects " $non_pic_object" - else - func_fatal_error "\`$arg' is not a valid libtool object" - fi - fi - ;; - - *.$libext) - # An archive. - func_append deplibs " $arg" - func_append old_deplibs " $arg" - continue - ;; - - *.la) - # A libtool-controlled library. - - func_resolve_sysroot "$arg" - if test "$prev" = dlfiles; then - # This library was specified with -dlopen. - func_append dlfiles " $func_resolve_sysroot_result" - prev= - elif test "$prev" = dlprefiles; then - # The library was specified with -dlpreopen. - func_append dlprefiles " $func_resolve_sysroot_result" - prev= - else - func_append deplibs " $func_resolve_sysroot_result" - fi - continue - ;; - - # Some other compiler argument. - *) - # Unknown arguments in both finalize_command and compile_command need - # to be aesthetically quoted because they are evaled later. - func_quote_for_eval "$arg" - arg="$func_quote_for_eval_result" - ;; - esac # arg - - # Now actually substitute the argument into the commands. - if test -n "$arg"; then - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - done # argument parsing loop - - test -n "$prev" && \ - func_fatal_help "the \`$prevarg' option requires an argument" - - if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then - eval arg=\"$export_dynamic_flag_spec\" - func_append compile_command " $arg" - func_append finalize_command " $arg" - fi - - oldlibs= - # calculate the name of the file, without its directory - func_basename "$output" - outputname="$func_basename_result" - libobjs_save="$libobjs" - - if test -n "$shlibpath_var"; then - # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` - else - shlib_search_path= - fi - eval sys_lib_search_path=\"$sys_lib_search_path_spec\" - eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" - - func_dirname "$output" "/" "" - output_objdir="$func_dirname_result$objdir" - func_to_tool_file "$output_objdir/" - tool_output_objdir=$func_to_tool_file_result - # Create the object directory. - func_mkdir_p "$output_objdir" - - # Determine the type of output - case $output in - "") - func_fatal_help "you must specify an output file" - ;; - *.$libext) linkmode=oldlib ;; - *.lo | *.$objext) linkmode=obj ;; - *.la) linkmode=lib ;; - *) linkmode=prog ;; # Anything else should be a program. - esac - - specialdeplibs= - - libs= - # Find all interdependent deplibs by searching for libraries - # that are linked more than once (e.g. -la -lb -la) - for deplib in $deplibs; do - if $opt_preserve_dup_deps ; then - case "$libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append libs " $deplib" - done - - if test "$linkmode" = lib; then - libs="$predeps $libs $compiler_lib_search_path $postdeps" - - # Compute libraries that are listed more than once in $predeps - # $postdeps and mark them as special (i.e., whose duplicates are - # not to be eliminated). - pre_post_deps= - if $opt_duplicate_compiler_generated_deps; then - for pre_post_dep in $predeps $postdeps; do - case "$pre_post_deps " in - *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; - esac - func_append pre_post_deps " $pre_post_dep" - done - fi - pre_post_deps= - fi - - deplibs= - newdependency_libs= - newlib_search_path= - need_relink=no # whether we're linking any uninstalled libtool libraries - notinst_deplibs= # not-installed libtool libraries - notinst_path= # paths that contain not-installed libtool libraries - - case $linkmode in - lib) - passes="conv dlpreopen link" - for file in $dlfiles $dlprefiles; do - case $file in - *.la) ;; - *) - func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" - ;; - esac - done - ;; - prog) - compile_deplibs= - finalize_deplibs= - alldeplibs=no - newdlfiles= - newdlprefiles= - passes="conv scan dlopen dlpreopen link" - ;; - *) passes="conv" - ;; - esac - - for pass in $passes; do - # The preopen pass in lib mode reverses $deplibs; put it back here - # so that -L comes before libs that need it for instance... - if test "$linkmode,$pass" = "lib,link"; then - ## FIXME: Find the place where the list is rebuilt in the wrong - ## order, and fix it there properly - tmp_deplibs= - for deplib in $deplibs; do - tmp_deplibs="$deplib $tmp_deplibs" - done - deplibs="$tmp_deplibs" - fi - - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan"; then - libs="$deplibs" - deplibs= - fi - if test "$linkmode" = prog; then - case $pass in - dlopen) libs="$dlfiles" ;; - dlpreopen) libs="$dlprefiles" ;; - link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; - esac - fi - if test "$linkmode,$pass" = "lib,dlpreopen"; then - # Collect and forward deplibs of preopened libtool libs - for lib in $dlprefiles; do - # Ignore non-libtool-libs - dependency_libs= - func_resolve_sysroot "$lib" - case $lib in - *.la) func_source "$func_resolve_sysroot_result" ;; - esac - - # Collect preopened libtool deplibs, except any this library - # has declared as weak libs - for deplib in $dependency_libs; do - func_basename "$deplib" - deplib_base=$func_basename_result - case " $weak_libs " in - *" $deplib_base "*) ;; - *) func_append deplibs " $deplib" ;; - esac - done - done - libs="$dlprefiles" - fi - if test "$pass" = dlopen; then - # Collect dlpreopened libraries - save_deplibs="$deplibs" - deplibs= - fi - - for deplib in $libs; do - lib= - found=no - case $deplib in - -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ - |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append compiler_flags " $deplib" - if test "$linkmode" = lib ; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -l*) - if test "$linkmode" != lib && test "$linkmode" != prog; then - func_warning "\`-l' is ignored for archives/objects" - continue - fi - func_stripname '-l' '' "$deplib" - name=$func_stripname_result - if test "$linkmode" = lib; then - searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" - else - searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" - fi - for searchdir in $searchdirs; do - for search_ext in .la $std_shrext .so .a; do - # Search the libtool library - lib="$searchdir/lib${name}${search_ext}" - if test -f "$lib"; then - if test "$search_ext" = ".la"; then - found=yes - else - found=no - fi - break 2 - fi - done - done - if test "$found" != yes; then - # deplib doesn't seem to be a libtool library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - else # deplib is a libtool library - # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, - # We need to do some special things here, and not later. - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $deplib "*) - if func_lalib_p "$lib"; then - library_names= - old_library= - func_source "$lib" - for l in $old_library $library_names; do - ll="$l" - done - if test "X$ll" = "X$old_library" ; then # only static version available - found=no - func_dirname "$lib" "" "." - ladir="$func_dirname_result" - lib=$ladir/$old_library - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" - fi - continue - fi - fi - ;; - *) ;; - esac - fi - fi - ;; # -l - *.ltframework) - if test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - deplibs="$deplib $deplibs" - if test "$linkmode" = lib ; then - case "$new_inherited_linker_flags " in - *" $deplib "*) ;; - * ) func_append new_inherited_linker_flags " $deplib" ;; - esac - fi - fi - continue - ;; - -L*) - case $linkmode in - lib) - deplibs="$deplib $deplibs" - test "$pass" = conv && continue - newdependency_libs="$deplib $newdependency_libs" - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - prog) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - if test "$pass" = scan; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - *) - func_warning "\`-L' is ignored for archives/objects" - ;; - esac # linkmode - continue - ;; # -L - -R*) - if test "$pass" = link; then - func_stripname '-R' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - dir=$func_resolve_sysroot_result - # Make sure the xrpath contains only unique directories. - case "$xrpath " in - *" $dir "*) ;; - *) func_append xrpath " $dir" ;; - esac - fi - deplibs="$deplib $deplibs" - continue - ;; - *.la) - func_resolve_sysroot "$deplib" - lib=$func_resolve_sysroot_result - ;; - *.$libext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi - case $linkmode in - lib) - # Linking convenience modules into shared libraries is allowed, - # but linking other static libraries is non-portable. - case " $dlpreconveniencelibs " in - *" $deplib "*) ;; - *) - valid_a_lib=no - case $deplibs_check_method in - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ - | $EGREP "$match_pattern_regex" > /dev/null; then - valid_a_lib=yes - fi - ;; - pass_all) - valid_a_lib=yes - ;; - esac - if test "$valid_a_lib" != yes; then - echo - $ECHO "*** Warning: Trying to link with static lib archive $deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because the file extensions .$libext of this argument makes me believe" - echo "*** that it is just a static archive that I should not use here." - else - echo - $ECHO "*** Warning: Linking the shared library $output against the" - $ECHO "*** static library $deplib is not portable!" - deplibs="$deplib $deplibs" - fi - ;; - esac - continue - ;; - prog) - if test "$pass" != link; then - deplibs="$deplib $deplibs" - else - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - fi - continue - ;; - esac # linkmode - ;; # *.$libext - *.lo | *.$objext) - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - elif test "$linkmode" = prog; then - if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then - # If there is no dlopen support or we're linking statically, - # we need to preload. - func_append newdlprefiles " $deplib" - compile_deplibs="$deplib $compile_deplibs" - finalize_deplibs="$deplib $finalize_deplibs" - else - func_append newdlfiles " $deplib" - fi - fi - continue - ;; - %DEPLIBS%) - alldeplibs=yes - continue - ;; - esac # case $deplib - - if test "$found" = yes || test -f "$lib"; then : - else - func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" - fi - - # Check to see that this really is a libtool archive. - func_lalib_unsafe_p "$lib" \ - || func_fatal_error "\`$lib' is not a valid libtool archive" - - func_dirname "$lib" "" "." - ladir="$func_dirname_result" - - dlname= - dlopen= - dlpreopen= - libdir= - library_names= - old_library= - inherited_linker_flags= - # If the library was installed with an old release of libtool, - # it will not redefine variables installed, or shouldnotlink - installed=yes - shouldnotlink=no - avoidtemprpath= - - - # Read the .la file - func_source "$lib" - - # Convert "-framework foo" to "foo.ltframework" - if test -n "$inherited_linker_flags"; then - tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` - for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do - case " $new_inherited_linker_flags " in - *" $tmp_inherited_linker_flag "*) ;; - *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; - esac - done - fi - dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - if test "$linkmode,$pass" = "lib,link" || - test "$linkmode,$pass" = "prog,scan" || - { test "$linkmode" != prog && test "$linkmode" != lib; }; then - test -n "$dlopen" && func_append dlfiles " $dlopen" - test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" - fi - - if test "$pass" = conv; then - # Only check for convenience libraries - deplibs="$lib $deplibs" - if test -z "$libdir"; then - if test -z "$old_library"; then - func_fatal_error "cannot find name of link library for \`$lib'" - fi - # It is a libtool convenience library, so add in its objects. - func_append convenience " $ladir/$objdir/$old_library" - func_append old_convenience " $ladir/$objdir/$old_library" - elif test "$linkmode" != prog && test "$linkmode" != lib; then - func_fatal_error "\`$lib' is not a convenience library" - fi - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done - continue - fi # $pass = conv - - - # Get the name of the library we link against. - linklib= - if test -n "$old_library" && - { test "$prefer_static_libs" = yes || - test "$prefer_static_libs,$installed" = "built,no"; }; then - linklib=$old_library - else - for l in $old_library $library_names; do - linklib="$l" - done - fi - if test -z "$linklib"; then - func_fatal_error "cannot find name of link library for \`$lib'" - fi - - # This library was specified with -dlopen. - if test "$pass" = dlopen; then - if test -z "$libdir"; then - func_fatal_error "cannot -dlopen a convenience library: \`$lib'" - fi - if test -z "$dlname" || - test "$dlopen_support" != yes || - test "$build_libtool_libs" = no; then - # If there is no dlname, no dlopen support or we're linking - # statically, we need to preload. We also need to preload any - # dependent libraries so libltdl's deplib preloader doesn't - # bomb out in the load deplibs phase. - func_append dlprefiles " $lib $dependency_libs" - else - func_append newdlfiles " $lib" - fi - continue - fi # $pass = dlopen - - # We need an absolute path. - case $ladir in - [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; - *) - abs_ladir=`cd "$ladir" && pwd` - if test -z "$abs_ladir"; then - func_warning "cannot determine absolute directory name of \`$ladir'" - func_warning "passing it literally to the linker, although it might fail" - abs_ladir="$ladir" - fi - ;; - esac - func_basename "$lib" - laname="$func_basename_result" - - # Find the relevant object directory and library name. - if test "X$installed" = Xyes; then - if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then - #func_warning "library \`$lib' was moved." - dir="$ladir" - absdir="$abs_ladir" - libdir="$abs_ladir" - else - dir="$lt_sysroot$libdir" - absdir="$lt_sysroot$libdir" - fi - test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes - else - if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then - dir="$ladir" - absdir="$abs_ladir" - # Remove this search path later - func_append notinst_path " $abs_ladir" - else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" - # Remove this search path later - func_append notinst_path " $abs_ladir" - fi - fi # $installed = yes - func_stripname 'lib' '.la' "$laname" - name=$func_stripname_result - - # This library was specified with -dlpreopen. - if test "$pass" = dlpreopen; then - if test -z "$libdir" && test "$linkmode" = prog; then - func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" - fi - case "$host" in - # special handling for platforms with PE-DLLs. - *cygwin* | *mingw* | *cegcc* ) - # Linker will automatically link against shared library if both - # static and shared are present. Therefore, ensure we extract - # symbols from the import library if a shared library is present - # (otherwise, the dlopen module name will be incorrect). We do - # this by putting the import library name into $newdlprefiles. - # We recover the dlopen module name by 'saving' the la file - # name in a special purpose variable, and (later) extracting the - # dlname from the la file. - if test -n "$dlname"; then - func_tr_sh "$dir/$linklib" - eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" - func_append newdlprefiles " $dir/$linklib" - else - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - fi - ;; - * ) - # Prefer using a static library (so that no silly _DYNAMIC symbols - # are required to link). - if test -n "$old_library"; then - func_append newdlprefiles " $dir/$old_library" - # Keep a list of preopened convenience libraries to check - # that they are being used correctly in the link pass. - test -z "$libdir" && \ - func_append dlpreconveniencelibs " $dir/$old_library" - # Otherwise, use the dlname, so that lt_dlopen finds it. - elif test -n "$dlname"; then - func_append newdlprefiles " $dir/$dlname" - else - func_append newdlprefiles " $dir/$linklib" - fi - ;; - esac - fi # $pass = dlpreopen - - if test -z "$libdir"; then - # Link the convenience library - if test "$linkmode" = lib; then - deplibs="$dir/$old_library $deplibs" - elif test "$linkmode,$pass" = "prog,link"; then - compile_deplibs="$dir/$old_library $compile_deplibs" - finalize_deplibs="$dir/$old_library $finalize_deplibs" - else - deplibs="$lib $deplibs" # used for prog,scan pass - fi - continue - fi - - - if test "$linkmode" = prog && test "$pass" != link; then - func_append newlib_search_path " $ladir" - deplibs="$lib $deplibs" - - linkalldeplibs=no - if test "$link_all_deplibs" != no || test -z "$library_names" || - test "$build_libtool_libs" = no; then - linkalldeplibs=yes - fi - - tmp_libs= - for deplib in $dependency_libs; do - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result" - func_append newlib_search_path " $func_resolve_sysroot_result" - ;; - esac - # Need to link against all dependency_libs? - if test "$linkalldeplibs" = yes; then - deplibs="$deplib $deplibs" - else - # Need to hardcode shared library paths - # or/and link against static libraries - newdependency_libs="$deplib $newdependency_libs" - fi - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done # for deplib - continue - fi # $linkmode = prog... - - if test "$linkmode,$pass" = "prog,link"; then - if test -n "$library_names" && - { { test "$prefer_static_libs" = no || - test "$prefer_static_libs,$installed" = "built,yes"; } || - test -z "$old_library"; }; then - # We need to hardcode the library path - if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then - # Make sure the rpath contains only unique directories. - case "$temp_rpath:" in - *"$absdir:"*) ;; - *) func_append temp_rpath "$absdir:" ;; - esac - fi - - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi # $linkmode,$pass = prog,link... - - if test "$alldeplibs" = yes && - { test "$deplibs_check_method" = pass_all || - { test "$build_libtool_libs" = yes && - test -n "$library_names"; }; }; then - # We only need to search for static libraries - continue - fi - fi - - link_static=no # Whether the deplib will be linked statically - use_static_libs=$prefer_static_libs - if test "$use_static_libs" = built && test "$installed" = yes; then - use_static_libs=no - fi - if test -n "$library_names" && - { test "$use_static_libs" = no || test -z "$old_library"; }; then - case $host in - *cygwin* | *mingw* | *cegcc*) - # No point in relinking DLLs because paths are not encoded - func_append notinst_deplibs " $lib" - need_relink=no - ;; - *) - if test "$installed" = no; then - func_append notinst_deplibs " $lib" - need_relink=yes - fi - ;; - esac - # This is a shared library - - # Warn about portability, can't link against -module's on some - # systems (darwin). Don't bleat about dlopened modules though! - dlopenmodule="" - for dlpremoduletest in $dlprefiles; do - if test "X$dlpremoduletest" = "X$lib"; then - dlopenmodule="$dlpremoduletest" - break - fi - done - if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then - echo - if test "$linkmode" = prog; then - $ECHO "*** Warning: Linking the executable $output against the loadable module" - else - $ECHO "*** Warning: Linking the shared library $output against the loadable module" - fi - $ECHO "*** $linklib is not portable!" - fi - if test "$linkmode" = lib && - test "$hardcode_into_libs" = yes; then - # Hardcode the library path. - # Skip directories that are in the system default run-time - # search path. - case " $sys_lib_dlsearch_path " in - *" $absdir "*) ;; - *) - case "$compile_rpath " in - *" $absdir "*) ;; - *) func_append compile_rpath " $absdir" ;; - esac - ;; - esac - case " $sys_lib_dlsearch_path " in - *" $libdir "*) ;; - *) - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - ;; - esac - fi - - if test -n "$old_archive_from_expsyms_cmds"; then - # figure out the soname - set dummy $library_names - shift - realname="$1" - shift - libname=`eval "\\$ECHO \"$libname_spec\""` - # use dlname if we got it. it's perfectly good, no? - if test -n "$dlname"; then - soname="$dlname" - elif test -n "$soname_spec"; then - # bleh windows - case $host in - *cygwin* | mingw* | *cegcc*) - func_arith $current - $age - major=$func_arith_result - versuffix="-$major" - ;; - esac - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - - # Make a new name for the extract_expsyms_cmds to use - soroot="$soname" - func_basename "$soroot" - soname="$func_basename_result" - func_stripname 'lib' '.dll' "$soname" - newlib=libimp-$func_stripname_result.a - - # If the library has no export list, then create one now - if test -f "$output_objdir/$soname-def"; then : - else - func_verbose "extracting exported symbol list from \`$soname'" - func_execute_cmds "$extract_expsyms_cmds" 'exit $?' - fi - - # Create $newlib - if test -f "$output_objdir/$newlib"; then :; else - func_verbose "generating import library for \`$soname'" - func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' - fi - # make sure the library variables are pointing to the new library - dir=$output_objdir - linklib=$newlib - fi # test -n "$old_archive_from_expsyms_cmds" - - if test "$linkmode" = prog || test "$opt_mode" != relink; then - add_shlibpath= - add_dir= - add= - lib_linked=yes - case $hardcode_action in - immediate | unsupported) - if test "$hardcode_direct" = no; then - add="$dir/$linklib" - case $host in - *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; - *-*-sysv4*uw2*) add_dir="-L$dir" ;; - *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ - *-*-unixware7*) add_dir="-L$dir" ;; - *-*-darwin* ) - # if the lib is a (non-dlopened) module then we can not - # link against it, someone is ignoring the earlier warnings - if /usr/bin/file -L $add 2> /dev/null | - $GREP ": [^:]* bundle" >/dev/null ; then - if test "X$dlopenmodule" != "X$lib"; then - $ECHO "*** Warning: lib $linklib is a module, not a shared library" - if test -z "$old_library" ; then - echo - echo "*** And there doesn't seem to be a static archive available" - echo "*** The link will probably fail, sorry" - else - add="$dir/$old_library" - fi - elif test -n "$old_library"; then - add="$dir/$old_library" - fi - fi - esac - elif test "$hardcode_minus_L" = no; then - case $host in - *-*-sunos*) add_shlibpath="$dir" ;; - esac - add_dir="-L$dir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = no; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - relink) - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$dir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$absdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - add_shlibpath="$dir" - add="-l$name" - else - lib_linked=no - fi - ;; - *) lib_linked=no ;; - esac - - if test "$lib_linked" != yes; then - func_fatal_configuration "unsupported hardcode properties" - fi - - if test -n "$add_shlibpath"; then - case :$compile_shlibpath: in - *":$add_shlibpath:"*) ;; - *) func_append compile_shlibpath "$add_shlibpath:" ;; - esac - fi - if test "$linkmode" = prog; then - test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" - test -n "$add" && compile_deplibs="$add $compile_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - if test "$hardcode_direct" != yes && - test "$hardcode_minus_L" != yes && - test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - fi - fi - fi - - if test "$linkmode" = prog || test "$opt_mode" = relink; then - add_shlibpath= - add_dir= - add= - # Finalize command for both is simple: just hardcode it. - if test "$hardcode_direct" = yes && - test "$hardcode_direct_absolute" = no; then - add="$libdir/$linklib" - elif test "$hardcode_minus_L" = yes; then - add_dir="-L$libdir" - add="-l$name" - elif test "$hardcode_shlibpath_var" = yes; then - case :$finalize_shlibpath: in - *":$libdir:"*) ;; - *) func_append finalize_shlibpath "$libdir:" ;; - esac - add="-l$name" - elif test "$hardcode_automatic" = yes; then - if test -n "$inst_prefix_dir" && - test -f "$inst_prefix_dir$libdir/$linklib" ; then - add="$inst_prefix_dir$libdir/$linklib" - else - add="$libdir/$linklib" - fi - else - # We cannot seem to hardcode it, guess we'll fake it. - add_dir="-L$libdir" - # Try looking first in the location we're being installed to. - if test -n "$inst_prefix_dir"; then - case $libdir in - [\\/]*) - func_append add_dir " -L$inst_prefix_dir$libdir" - ;; - esac - fi - add="-l$name" - fi - - if test "$linkmode" = prog; then - test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" - test -n "$add" && finalize_deplibs="$add $finalize_deplibs" - else - test -n "$add_dir" && deplibs="$add_dir $deplibs" - test -n "$add" && deplibs="$add $deplibs" - fi - fi - elif test "$linkmode" = prog; then - # Here we assume that one of hardcode_direct or hardcode_minus_L - # is not unsupported. This is valid on all known static and - # shared platforms. - if test "$hardcode_direct" != unsupported; then - test -n "$old_library" && linklib="$old_library" - compile_deplibs="$dir/$linklib $compile_deplibs" - finalize_deplibs="$dir/$linklib $finalize_deplibs" - else - compile_deplibs="-l$name -L$dir $compile_deplibs" - finalize_deplibs="-l$name -L$dir $finalize_deplibs" - fi - elif test "$build_libtool_libs" = yes; then - # Not a shared library - if test "$deplibs_check_method" != pass_all; then - # We're trying link a shared library against a static one - # but the system doesn't support it. - - # Just print a warning and add the library to dependency_libs so - # that the program can be linked against the static library. - echo - $ECHO "*** Warning: This system can not link to static lib archive $lib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have." - if test "$module" = yes; then - echo "*** But as you try to build a module library, libtool will still create " - echo "*** a static module, that should work as long as the dlopening application" - echo "*** is linked with the -dlopen flag to resolve symbols at runtime." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - else - deplibs="$dir/$old_library $deplibs" - link_static=yes - fi - fi # link shared/static library? - - if test "$linkmode" = lib; then - if test -n "$dependency_libs" && - { test "$hardcode_into_libs" != yes || - test "$build_old_libs" = yes || - test "$link_static" = yes; }; then - # Extract -R from dependency_libs - temp_deplibs= - for libdir in $dependency_libs; do - case $libdir in - -R*) func_stripname '-R' '' "$libdir" - temp_xrpath=$func_stripname_result - case " $xrpath " in - *" $temp_xrpath "*) ;; - *) func_append xrpath " $temp_xrpath";; - esac;; - *) func_append temp_deplibs " $libdir";; - esac - done - dependency_libs="$temp_deplibs" - fi - - func_append newlib_search_path " $absdir" - # Link against this library - test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" - # ... and its dependency_libs - tmp_libs= - for deplib in $dependency_libs; do - newdependency_libs="$deplib $newdependency_libs" - case $deplib in - -L*) func_stripname '-L' '' "$deplib" - func_resolve_sysroot "$func_stripname_result";; - *) func_resolve_sysroot "$deplib" ;; - esac - if $opt_preserve_dup_deps ; then - case "$tmp_libs " in - *" $func_resolve_sysroot_result "*) - func_append specialdeplibs " $func_resolve_sysroot_result" ;; - esac - fi - func_append tmp_libs " $func_resolve_sysroot_result" - done - - if test "$link_all_deplibs" != no; then - # Add the search paths of all dependency libraries - for deplib in $dependency_libs; do - path= - case $deplib in - -L*) path="$deplib" ;; - *.la) - func_resolve_sysroot "$deplib" - deplib=$func_resolve_sysroot_result - func_dirname "$deplib" "" "." - dir=$func_dirname_result - # We need an absolute path. - case $dir in - [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; - *) - absdir=`cd "$dir" && pwd` - if test -z "$absdir"; then - func_warning "cannot determine absolute directory name of \`$dir'" - absdir="$dir" - fi - ;; - esac - if $GREP "^installed=no" $deplib > /dev/null; then - case $host in - *-*-darwin*) - depdepl= - eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` - if test -n "$deplibrary_names" ; then - for tmp in $deplibrary_names ; do - depdepl=$tmp - done - if test -f "$absdir/$objdir/$depdepl" ; then - depdepl="$absdir/$objdir/$depdepl" - darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - if test -z "$darwin_install_name"; then - darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` - fi - func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" - func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" - path= - fi - fi - ;; - *) - path="-L$absdir/$objdir" - ;; - esac - else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` - test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" - #test "$absdir" != "$libdir" && \ - # func_warning "\`$deplib' seems to be moved" - - path="-L$absdir" - fi - ;; - esac - case " $deplibs " in - *" $path "*) ;; - *) deplibs="$path $deplibs" ;; - esac - done - fi # link_all_deplibs != no - fi # linkmode = lib - done # for deplib in $libs - if test "$pass" = link; then - if test "$linkmode" = "prog"; then - compile_deplibs="$new_inherited_linker_flags $compile_deplibs" - finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" - else - compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - fi - fi - dependency_libs="$newdependency_libs" - if test "$pass" = dlpreopen; then - # Link the dlpreopened libraries before other libraries - for deplib in $save_deplibs; do - deplibs="$deplib $deplibs" - done - fi - if test "$pass" != dlopen; then - if test "$pass" != conv; then - # Make sure lib_search_path contains only unique directories. - lib_search_path= - for dir in $newlib_search_path; do - case "$lib_search_path " in - *" $dir "*) ;; - *) func_append lib_search_path " $dir" ;; - esac - done - newlib_search_path= - fi - - if test "$linkmode,$pass" != "prog,link"; then - vars="deplibs" - else - vars="compile_deplibs finalize_deplibs" - fi - for var in $vars dependency_libs; do - # Add libraries to $var in reverse order - eval tmp_libs=\"\$$var\" - new_libs= - for deplib in $tmp_libs; do - # FIXME: Pedantically, this is the right thing to do, so - # that some nasty dependency loop isn't accidentally - # broken: - #new_libs="$deplib $new_libs" - # Pragmatically, this seems to cause very few problems in - # practice: - case $deplib in - -L*) new_libs="$deplib $new_libs" ;; - -R*) ;; - *) - # And here is the reason: when a library appears more - # than once as an explicit dependence of a library, or - # is implicitly linked in more than once by the - # compiler, it is considered special, and multiple - # occurrences thereof are not removed. Compare this - # with having the same library being listed as a - # dependency of multiple other libraries: in this case, - # we know (pedantically, we assume) the library does not - # need to be listed more than once, so we keep only the - # last copy. This is not always right, but it is rare - # enough that we require users that really mean to play - # such unportable linking tricks to link the library - # using -Wl,-lname, so that libtool does not consider it - # for duplicate removal. - case " $specialdeplibs " in - *" $deplib "*) new_libs="$deplib $new_libs" ;; - *) - case " $new_libs " in - *" $deplib "*) ;; - *) new_libs="$deplib $new_libs" ;; - esac - ;; - esac - ;; - esac - done - tmp_libs= - for deplib in $new_libs; do - case $deplib in - -L*) - case " $tmp_libs " in - *" $deplib "*) ;; - *) func_append tmp_libs " $deplib" ;; - esac - ;; - *) func_append tmp_libs " $deplib" ;; - esac - done - eval $var=\"$tmp_libs\" - done # for var - fi - # Last step: remove runtime libs from dependency_libs - # (they stay in deplibs) - tmp_libs= - for i in $dependency_libs ; do - case " $predeps $postdeps $compiler_lib_search_path " in - *" $i "*) - i="" - ;; - esac - if test -n "$i" ; then - func_append tmp_libs " $i" - fi - done - dependency_libs=$tmp_libs - done # for pass - if test "$linkmode" = prog; then - dlfiles="$newdlfiles" - fi - if test "$linkmode" = prog || test "$linkmode" = lib; then - dlprefiles="$newdlprefiles" - fi - - case $linkmode in - oldlib) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for archives" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for archives" ;; - esac - - test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for archives" - - test -n "$xrpath" && \ - func_warning "\`-R' is ignored for archives" - - test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for archives" - - test -n "$release" && \ - func_warning "\`-release' is ignored for archives" - - test -n "$export_symbols$export_symbols_regex" && \ - func_warning "\`-export-symbols' is ignored for archives" - - # Now set the variables for building old libraries. - build_libtool_libs=no - oldlibs="$output" - func_append objs "$old_deplibs" - ;; - - lib) - # Make sure we only generate libraries of the form `libNAME.la'. - case $outputname in - lib*) - func_stripname 'lib' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - ;; - *) - test "$module" = no && \ - func_fatal_help "libtool library \`$output' must begin with \`lib'" - - if test "$need_lib_prefix" != no; then - # Add the "lib" prefix for modules if required - func_stripname '' '.la' "$outputname" - name=$func_stripname_result - eval shared_ext=\"$shrext_cmds\" - eval libname=\"$libname_spec\" - else - func_stripname '' '.la' "$outputname" - libname=$func_stripname_result - fi - ;; - esac - - if test -n "$objs"; then - if test "$deplibs_check_method" != pass_all; then - func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" - else - echo - $ECHO "*** Warning: Linking the shared library $output against the non-libtool" - $ECHO "*** objects $objs is not portable!" - func_append libobjs " $objs" - fi - fi - - test "$dlself" != no && \ - func_warning "\`-dlopen self' is ignored for libtool libraries" - - set dummy $rpath - shift - test "$#" -gt 1 && \ - func_warning "ignoring multiple \`-rpath's for a libtool library" - - install_libdir="$1" - - oldlibs= - if test -z "$rpath"; then - if test "$build_libtool_libs" = yes; then - # Building a libtool convenience library. - # Some compilers have problems with a `.al' extension so - # convenience libraries should have the same extension an - # archive normally would. - oldlibs="$output_objdir/$libname.$libext $oldlibs" - build_libtool_libs=convenience - build_old_libs=yes - fi - - test -n "$vinfo" && \ - func_warning "\`-version-info/-version-number' is ignored for convenience libraries" - - test -n "$release" && \ - func_warning "\`-release' is ignored for convenience libraries" - else - - # Parse the version information argument. - save_ifs="$IFS"; IFS=':' - set dummy $vinfo 0 0 0 - shift - IFS="$save_ifs" - - test -n "$7" && \ - func_fatal_help "too many parameters to \`-version-info'" - - # convert absolute version numbers to libtool ages - # this retains compatibility with .la files and attempts - # to make the code below a bit more comprehensible - - case $vinfo_number in - yes) - number_major="$1" - number_minor="$2" - number_revision="$3" - # - # There are really only two kinds -- those that - # use the current revision as the major version - # and those that subtract age and use age as - # a minor version. But, then there is irix - # which has an extra 1 added just for fun - # - case $version_type in - # correct linux to gnu/linux during the next big refactor - darwin|linux|osf|windows|none) - func_arith $number_major + $number_minor - current=$func_arith_result - age="$number_minor" - revision="$number_revision" - ;; - freebsd-aout|freebsd-elf|qnx|sunos) - current="$number_major" - revision="$number_minor" - age="0" - ;; - irix|nonstopux) - func_arith $number_major + $number_minor - current=$func_arith_result - age="$number_minor" - revision="$number_minor" - lt_irix_increment=no - ;; - esac - ;; - no) - current="$1" - revision="$2" - age="$3" - ;; - esac - - # Check that each of the things are valid numbers. - case $current in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "CURRENT \`$current' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - case $revision in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "REVISION \`$revision' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - case $age in - 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; - *) - func_error "AGE \`$age' must be a nonnegative integer" - func_fatal_error "\`$vinfo' is not valid version information" - ;; - esac - - if test "$age" -gt "$current"; then - func_error "AGE \`$age' is greater than the current interface number \`$current'" - func_fatal_error "\`$vinfo' is not valid version information" - fi - - # Calculate the version variables. - major= - versuffix= - verstring= - case $version_type in - none) ;; - - darwin) - # Like Linux, but with the current version available in - # verstring for coding it into the library header - func_arith $current - $age - major=.$func_arith_result - versuffix="$major.$age.$revision" - # Darwin ld doesn't like 0 for these options... - func_arith $current + 1 - minor_current=$func_arith_result - xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" - ;; - - freebsd-aout) - major=".$current" - versuffix=".$current.$revision"; - ;; - - freebsd-elf) - major=".$current" - versuffix=".$current" - ;; - - irix | nonstopux) - if test "X$lt_irix_increment" = "Xno"; then - func_arith $current - $age - else - func_arith $current - $age + 1 - fi - major=$func_arith_result - - case $version_type in - nonstopux) verstring_prefix=nonstopux ;; - *) verstring_prefix=sgi ;; - esac - verstring="$verstring_prefix$major.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$revision - while test "$loop" -ne 0; do - func_arith $revision - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring="$verstring_prefix$major.$iface:$verstring" - done - - # Before this point, $major must not contain `.'. - major=.$major - versuffix="$major.$revision" - ;; - - linux) # correct to gnu/linux during the next big refactor - func_arith $current - $age - major=.$func_arith_result - versuffix="$major.$age.$revision" - ;; - - osf) - func_arith $current - $age - major=.$func_arith_result - versuffix=".$current.$age.$revision" - verstring="$current.$age.$revision" - - # Add in all the interfaces that we are compatible with. - loop=$age - while test "$loop" -ne 0; do - func_arith $current - $loop - iface=$func_arith_result - func_arith $loop - 1 - loop=$func_arith_result - verstring="$verstring:${iface}.0" - done - - # Make executables depend on our current version. - func_append verstring ":${current}.0" - ;; - - qnx) - major=".$current" - versuffix=".$current" - ;; - - sunos) - major=".$current" - versuffix=".$current.$revision" - ;; - - windows) - # Use '-' rather than '.', since we only want one - # extension on DOS 8.3 filesystems. - func_arith $current - $age - major=$func_arith_result - versuffix="-$major" - ;; - - *) - func_fatal_configuration "unknown library version type \`$version_type'" - ;; - esac - - # Clear the version info if we defaulted, and they specified a release. - if test -z "$vinfo" && test -n "$release"; then - major= - case $version_type in - darwin) - # we can't check for "0.0" in archive_cmds due to quoting - # problems, so we reset it completely - verstring= - ;; - *) - verstring="0.0" - ;; - esac - if test "$need_version" = no; then - versuffix= - else - versuffix=".0.0" - fi - fi - - # Remove version info from name if versioning should be avoided - if test "$avoid_version" = yes && test "$need_version" = no; then - major= - versuffix= - verstring="" - fi - - # Check to see if the archive will have undefined symbols. - if test "$allow_undefined" = yes; then - if test "$allow_undefined_flag" = unsupported; then - func_warning "undefined symbols not allowed in $host shared libraries" - build_libtool_libs=no - build_old_libs=yes - fi - else - # Don't allow undefined symbols. - allow_undefined_flag="$no_undefined_flag" - fi - - fi - - func_generate_dlsyms "$libname" "$libname" "yes" - func_append libobjs " $symfileobj" - test "X$libobjs" = "X " && libobjs= - - if test "$opt_mode" != relink; then - # Remove our outputs, but don't remove object files since they - # may have been created when compiling PIC objects. - removelist= - tempremovelist=`$ECHO "$output_objdir/*"` - for p in $tempremovelist; do - case $p in - *.$objext | *.gcno) - ;; - $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) - if test "X$precious_files_regex" != "X"; then - if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 - then - continue - fi - fi - func_append removelist " $p" - ;; - *) ;; - esac - done - test -n "$removelist" && \ - func_show_eval "${RM}r \$removelist" - fi - - # Now set the variables for building old libraries. - if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then - func_append oldlibs " $output_objdir/$libname.$libext" - - # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` - fi - - # Eliminate all temporary directories. - #for path in $notinst_path; do - # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` - # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` - # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` - #done - - if test -n "$xrpath"; then - # If the user specified any rpath flags, then add them. - temp_xrpath= - for libdir in $xrpath; do - func_replace_sysroot "$libdir" - func_append temp_xrpath " -R$func_replace_sysroot_result" - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then - dependency_libs="$temp_xrpath $dependency_libs" - fi - fi - - # Make sure dlfiles contains only unique files that won't be dlpreopened - old_dlfiles="$dlfiles" - dlfiles= - for lib in $old_dlfiles; do - case " $dlprefiles $dlfiles " in - *" $lib "*) ;; - *) func_append dlfiles " $lib" ;; - esac - done - - # Make sure dlprefiles contains only unique files - old_dlprefiles="$dlprefiles" - dlprefiles= - for lib in $old_dlprefiles; do - case "$dlprefiles " in - *" $lib "*) ;; - *) func_append dlprefiles " $lib" ;; - esac - done - - if test "$build_libtool_libs" = yes; then - if test -n "$rpath"; then - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) - # these systems don't actually have a c library (as such)! - ;; - *-*-rhapsody* | *-*-darwin1.[012]) - # Rhapsody C library is in the System framework - func_append deplibs " System.ltframework" - ;; - *-*-netbsd*) - # Don't link with libc until the a.out ld.so is fixed. - ;; - *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) - # Do not include libc due to us having libc/libc_r. - ;; - *-*-sco3.2v5* | *-*-sco5v6*) - # Causes problems with __ctype - ;; - *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) - # Compiler inserts libc in the correct place for threads to work - ;; - *) - # Add libc to deplibs on all other systems if necessary. - if test "$build_libtool_need_lc" = "yes"; then - func_append deplibs " -lc" - fi - ;; - esac - fi - - # Transform deplibs into only deplibs that can be linked in shared. - name_save=$name - libname_save=$libname - release_save=$release - versuffix_save=$versuffix - major_save=$major - # I'm not sure if I'm treating the release correctly. I think - # release should show up in the -l (ie -lgmp5) so we don't want to - # add it in twice. Is that correct? - release="" - versuffix="" - major="" - newdeplibs= - droppeddeps=no - case $deplibs_check_method in - pass_all) - # Don't check for shared/static. Everything works. - # This might be a little naive. We might want to check - # whether the library exists or not. But this is on - # osf3 & osf4 and I'm not really sure... Just - # implementing what was already the behavior. - newdeplibs=$deplibs - ;; - test_compile) - # This code stresses the "libraries are programs" paradigm to its - # limits. Maybe even breaks it. We compile a program, linking it - # against the deplibs as a proxy for the library. Then we can check - # whether they linked in statically or dynamically with ldd. - $opt_dry_run || $RM conftest.c - cat > conftest.c </dev/null` - $nocaseglob - else - potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` - fi - for potent_lib in $potential_libs; do - # Follow soft links. - if ls -lLd "$potent_lib" 2>/dev/null | - $GREP " -> " >/dev/null; then - continue - fi - # The statement above tries to avoid entering an - # endless loop below, in case of cyclic links. - # We might still enter an endless loop, since a link - # loop can be closed while we follow links, - # but so what? - potlib="$potent_lib" - while test -h "$potlib" 2>/dev/null; do - potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` - case $potliblink in - [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; - esac - done - if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | - $SED -e 10q | - $EGREP "$file_magic_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $ECHO "*** with $libname but no candidates were found. (...for file magic test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a file magic. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - match_pattern*) - set dummy $deplibs_check_method; shift - match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - for a_deplib in $deplibs; do - case $a_deplib in - -l*) - func_stripname -l '' "$a_deplib" - name=$func_stripname_result - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - case " $predeps $postdeps " in - *" $a_deplib "*) - func_append newdeplibs " $a_deplib" - a_deplib="" - ;; - esac - fi - if test -n "$a_deplib" ; then - libname=`eval "\\$ECHO \"$libname_spec\""` - for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do - potential_libs=`ls $i/$libname[.-]* 2>/dev/null` - for potent_lib in $potential_libs; do - potlib="$potent_lib" # see symlink-check above in file_magic test - if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ - $EGREP "$match_pattern_regex" > /dev/null; then - func_append newdeplibs " $a_deplib" - a_deplib="" - break 2 - fi - done - done - fi - if test -n "$a_deplib" ; then - droppeddeps=yes - echo - $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - echo "*** I have the capability to make that library automatically link in when" - echo "*** you link to this library. But I can only do this if you have a" - echo "*** shared version of the library, which you do not appear to have" - echo "*** because I did check the linker path looking for a file starting" - if test -z "$potlib" ; then - $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" - else - $ECHO "*** with $libname and none of the candidates passed a file format test" - $ECHO "*** using a regex pattern. Last file checked: $potlib" - fi - fi - ;; - *) - # Add a -L argument. - func_append newdeplibs " $a_deplib" - ;; - esac - done # Gone through all deplibs. - ;; - none | unknown | *) - newdeplibs="" - tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` - if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then - for i in $predeps $postdeps ; do - # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` - done - fi - case $tmp_deplibs in - *[!\ \ ]*) - echo - if test "X$deplibs_check_method" = "Xnone"; then - echo "*** Warning: inter-library dependencies are not supported in this platform." - else - echo "*** Warning: inter-library dependencies are not known to be supported." - fi - echo "*** All declared inter-library dependencies are being dropped." - droppeddeps=yes - ;; - esac - ;; - esac - versuffix=$versuffix_save - major=$major_save - release=$release_save - libname=$libname_save - name=$name_save - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library with the System framework - newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - if test "$droppeddeps" = yes; then - if test "$module" = yes; then - echo - echo "*** Warning: libtool could not satisfy all declared inter-library" - $ECHO "*** dependencies of module $libname. Therefore, libtool will create" - echo "*** a static module, that should work as long as the dlopening" - echo "*** application is linked with the -dlopen flag." - if test -z "$global_symbol_pipe"; then - echo - echo "*** However, this would only work if libtool was able to extract symbol" - echo "*** lists from a program, using \`nm' or equivalent, but libtool could" - echo "*** not find such a program. So, this module is probably useless." - echo "*** \`nm' from GNU binutils and a full rebuild may help." - fi - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - else - echo "*** The inter-library dependencies that have been dropped here will be" - echo "*** automatically added whenever a program is linked with this library" - echo "*** or is declared to -dlopen it." - - if test "$allow_undefined" = no; then - echo - echo "*** Since this library must not contain undefined symbols," - echo "*** because either the platform does not support them or" - echo "*** it was explicitly requested with -no-undefined," - echo "*** libtool will only create a static version of it." - if test "$build_old_libs" = no; then - oldlibs="$output_objdir/$libname.$libext" - build_libtool_libs=module - build_old_libs=yes - else - build_libtool_libs=no - fi - fi - fi - fi - # Done checking deplibs! - deplibs=$newdeplibs - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - case $host in - *-*-darwin*) - newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - deplibs="$new_libs" - - # All the library-specific variables (install_libdir is set above). - library_names= - old_library= - dlname= - - # Test again, we may have decided not to build it any more - if test "$build_libtool_libs" = yes; then - # Remove ${wl} instances when linking with ld. - # FIXME: should test the right _cmds variable. - case $archive_cmds in - *\$LD\ *) wl= ;; - esac - if test "$hardcode_into_libs" = yes; then - # Hardcode the library paths - hardcode_libdirs= - dep_rpath= - rpath="$finalize_rpath" - test "$opt_mode" != relink && rpath="$compile_rpath$rpath" - for libdir in $rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - func_replace_sysroot "$libdir" - libdir=$func_replace_sysroot_result - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append dep_rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" - fi - if test -n "$runpath_var" && test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" - fi - test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" - fi - - shlibpath="$finalize_shlibpath" - test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" - if test -n "$shlibpath"; then - eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" - fi - - # Get the real and link names of the library. - eval shared_ext=\"$shrext_cmds\" - eval library_names=\"$library_names_spec\" - set dummy $library_names - shift - realname="$1" - shift - - if test -n "$soname_spec"; then - eval soname=\"$soname_spec\" - else - soname="$realname" - fi - if test -z "$dlname"; then - dlname=$soname - fi - - lib="$output_objdir/$realname" - linknames= - for link - do - func_append linknames " $link" - done - - # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` - test "X$libobjs" = "X " && libobjs= - - delfiles= - if test -n "$export_symbols" && test -n "$include_expsyms"; then - $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" - export_symbols="$output_objdir/$libname.uexp" - func_append delfiles " $export_symbols" - fi - - orig_export_symbols= - case $host_os in - cygwin* | mingw* | cegcc*) - if test -n "$export_symbols" && test -z "$export_symbols_regex"; then - # exporting using user supplied symfile - if test "x`$SED 1q $export_symbols`" != xEXPORTS; then - # and it's NOT already a .def file. Must figure out - # which of the given symbols are data symbols and tag - # them as such. So, trigger use of export_symbols_cmds. - # export_symbols gets reassigned inside the "prepare - # the list of exported symbols" if statement, so the - # include_expsyms logic still works. - orig_export_symbols="$export_symbols" - export_symbols= - always_export_symbols=yes - fi - fi - ;; - esac - - # Prepare the list of exported symbols - if test -z "$export_symbols"; then - if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $opt_dry_run || $RM $export_symbols - cmds=$export_symbols_cmds - save_ifs="$IFS"; IFS='~' - for cmd1 in $cmds; do - IFS="$save_ifs" - # Take the normal branch if the nm_file_list_spec branch - # doesn't work or if tool conversion is not needed. - case $nm_file_list_spec~$to_tool_file_cmd in - *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) - try_normal_branch=yes - eval cmd=\"$cmd1\" - func_len " $cmd" - len=$func_len_result - ;; - *) - try_normal_branch=no - ;; - esac - if test "$try_normal_branch" = yes \ - && { test "$len" -lt "$max_cmd_len" \ - || test "$max_cmd_len" -le -1; } - then - func_show_eval "$cmd" 'exit $?' - skipped_export=false - elif test -n "$nm_file_list_spec"; then - func_basename "$output" - output_la=$func_basename_result - save_libobjs=$libobjs - save_output=$output - output=${output_objdir}/${output_la}.nm - func_to_tool_file "$output" - libobjs=$nm_file_list_spec$func_to_tool_file_result - func_append delfiles " $output" - func_verbose "creating $NM input file list: $output" - for obj in $save_libobjs; do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > "$output" - eval cmd=\"$cmd1\" - func_show_eval "$cmd" 'exit $?' - output=$save_output - libobjs=$save_libobjs - skipped_export=false - else - # The command line is too long to execute in one step. - func_verbose "using reloadable object file for export list..." - skipped_export=: - # Break out early, otherwise skipped_export may be - # set to false by a later but shorter cmd. - break - fi - done - IFS="$save_ifs" - if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - fi - - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - - tmp_deplibs= - for test_deplib in $deplibs; do - case " $convenience " in - *" $test_deplib "*) ;; - *) - func_append tmp_deplibs " $test_deplib" - ;; - esac - done - deplibs="$tmp_deplibs" - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec" && - test "$compiler_needs_object" = yes && - test -z "$libobjs"; then - # extract the archives, so we have objects to list. - # TODO: could optimize this to just extract one archive. - whole_archive_flag_spec= - fi - if test -n "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - else - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - fi - - if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then - eval flag=\"$thread_safe_flag_spec\" - func_append linker_flags " $flag" - fi - - # Make a backup of the uninstalled library when relinking - if test "$opt_mode" = relink; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? - fi - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - eval test_cmds=\"$module_expsym_cmds\" - cmds=$module_expsym_cmds - else - eval test_cmds=\"$module_cmds\" - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - eval test_cmds=\"$archive_expsym_cmds\" - cmds=$archive_expsym_cmds - else - eval test_cmds=\"$archive_cmds\" - cmds=$archive_cmds - fi - fi - - if test "X$skipped_export" != "X:" && - func_len " $test_cmds" && - len=$func_len_result && - test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - : - else - # The command line is too long to link in one step, link piecewise - # or, if using GNU ld and skipped_export is not :, use a linker - # script. - - # Save the value of $output and $libobjs because we want to - # use them later. If we have whole_archive_flag_spec, we - # want to use save_libobjs as it was before - # whole_archive_flag_spec was expanded, because we can't - # assume the linker understands whole_archive_flag_spec. - # This may have to be revisited, in case too many - # convenience libraries get linked in and end up exceeding - # the spec. - if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then - save_libobjs=$libobjs - fi - save_output=$output - func_basename "$output" - output_la=$func_basename_result - - # Clear the reloadable object creation command queue and - # initialize k to one. - test_cmds= - concat_cmds= - objlist= - last_robj= - k=1 - - if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then - output=${output_objdir}/${output_la}.lnkscript - func_verbose "creating GNU ld script: $output" - echo 'INPUT (' > $output - for obj in $save_libobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - echo ')' >> $output - func_append delfiles " $output" - func_to_tool_file "$output" - output=$func_to_tool_file_result - elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then - output=${output_objdir}/${output_la}.lnk - func_verbose "creating linker input file list: $output" - : > $output - set x $save_libobjs - shift - firstobj= - if test "$compiler_needs_object" = yes; then - firstobj="$1 " - shift - fi - for obj - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" >> $output - done - func_append delfiles " $output" - func_to_tool_file "$output" - output=$firstobj\"$file_list_spec$func_to_tool_file_result\" - else - if test -n "$save_libobjs"; then - func_verbose "creating reloadable object files..." - output=$output_objdir/$output_la-${k}.$objext - eval test_cmds=\"$reload_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - - # Loop over the list of objects to be linked. - for obj in $save_libobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - if test "X$objlist" = X || - test "$len" -lt "$max_cmd_len"; then - func_append objlist " $obj" - else - # The command $test_cmds is almost too long, add a - # command to the queue. - if test "$k" -eq 1 ; then - # The first file doesn't have a previous command to add. - reload_objs=$objlist - eval concat_cmds=\"$reload_cmds\" - else - # All subsequent reloadable object files will link in - # the last one created. - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" - fi - last_robj=$output_objdir/$output_la-${k}.$objext - func_arith $k + 1 - k=$func_arith_result - output=$output_objdir/$output_la-${k}.$objext - objlist=" $obj" - func_len " $last_robj" - func_arith $len0 + $func_len_result - len=$func_arith_result - fi - done - # Handle the remaining objects by creating one last - # reloadable object file. All subsequent reloadable object - # files will link in the last one created. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - reload_objs="$objlist $last_robj" - eval concat_cmds=\"\${concat_cmds}$reload_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" - fi - func_append delfiles " $output" - - else - output= - fi - - if ${skipped_export-false}; then - func_verbose "generating symbol list for \`$libname.la'" - export_symbols="$output_objdir/$libname.exp" - $opt_dry_run || $RM $export_symbols - libobjs=$output - # Append the command to create the export file. - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" - if test -n "$last_robj"; then - eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" - fi - fi - - test -n "$save_libobjs" && - func_verbose "creating a temporary reloadable object file: $output" - - # Loop through the commands generated above and execute them. - save_ifs="$IFS"; IFS='~' - for cmd in $concat_cmds; do - IFS="$save_ifs" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - if test -n "$export_symbols_regex" && ${skipped_export-false}; then - func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' - func_show_eval '$MV "${export_symbols}T" "$export_symbols"' - fi - fi - - if ${skipped_export-false}; then - if test -n "$export_symbols" && test -n "$include_expsyms"; then - tmp_export_symbols="$export_symbols" - test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' - fi - - if test -n "$orig_export_symbols"; then - # The given exports_symbols file has to be filtered, so filter it. - func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" - # FIXME: $output_objdir/$libname.filter potentially contains lots of - # 's' commands which not all seds can handle. GNU sed should be fine - # though. Also, the filter scales superlinearly with the number of - # global variables. join(1) would be nice here, but unfortunately - # isn't a blessed tool. - $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter - func_append delfiles " $export_symbols $output_objdir/$libname.filter" - export_symbols=$output_objdir/$libname.def - $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols - fi - fi - - libobjs=$output - # Restore the value of output. - output=$save_output - - if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then - eval libobjs=\"\$libobjs $whole_archive_flag_spec\" - test "X$libobjs" = "X " && libobjs= - fi - # Expand the library linking commands again to reset the - # value of $libobjs for piecewise linking. - - # Do each of the archive commands. - if test "$module" = yes && test -n "$module_cmds" ; then - if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then - cmds=$module_expsym_cmds - else - cmds=$module_cmds - fi - else - if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then - cmds=$archive_expsym_cmds - else - cmds=$archive_cmds - fi - fi - fi - - if test -n "$delfiles"; then - # Append the command to remove temporary files to $cmds. - eval cmds=\"\$cmds~\$RM $delfiles\" - fi - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append libobjs " $func_extract_archives_result" - test "X$libobjs" = "X " && libobjs= - fi - - save_ifs="$IFS"; IFS='~' - for cmd in $cmds; do - IFS="$save_ifs" - eval cmd=\"$cmd\" - $opt_silent || { - func_quote_for_expand "$cmd" - eval "func_echo $func_quote_for_expand_result" - } - $opt_dry_run || eval "$cmd" || { - lt_exit=$? - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - ( cd "$output_objdir" && \ - $RM "${realname}T" && \ - $MV "${realname}U" "$realname" ) - fi - - exit $lt_exit - } - done - IFS="$save_ifs" - - # Restore the uninstalled library and exit - if test "$opt_mode" = relink; then - $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? - - if test -n "$convenience"; then - if test -z "$whole_archive_flag_spec"; then - func_show_eval '${RM}r "$gentop"' - fi - fi - - exit $EXIT_SUCCESS - fi - - # Create links to the real library. - for linkname in $linknames; do - if test "$realname" != "$linkname"; then - func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' - fi - done - - # If -module or -export-dynamic was specified, set the dlname. - if test "$module" = yes || test "$export_dynamic" = yes; then - # On all known operating systems, these are identical. - dlname="$soname" - fi - fi - ;; - - obj) - if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then - func_warning "\`-dlopen' is ignored for objects" - fi - - case " $deplibs" in - *\ -l* | *\ -L*) - func_warning "\`-l' and \`-L' are ignored for objects" ;; - esac - - test -n "$rpath" && \ - func_warning "\`-rpath' is ignored for objects" - - test -n "$xrpath" && \ - func_warning "\`-R' is ignored for objects" - - test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for objects" - - test -n "$release" && \ - func_warning "\`-release' is ignored for objects" - - case $output in - *.lo) - test -n "$objs$old_deplibs" && \ - func_fatal_error "cannot build library object \`$output' from non-libtool objects" - - libobj=$output - func_lo2o "$libobj" - obj=$func_lo2o_result - ;; - *) - libobj= - obj="$output" - ;; - esac - - # Delete the old objects. - $opt_dry_run || $RM $obj $libobj - - # Objects from convenience libraries. This assumes - # single-version convenience libraries. Whenever we create - # different ones for PIC/non-PIC, this we'll have to duplicate - # the extraction. - reload_conv_objs= - gentop= - # reload_cmds runs $LD directly, so let us get rid of - # -Wl from whole_archive_flag_spec and hope we can get by with - # turning comma into space.. - wl= - - if test -n "$convenience"; then - if test -n "$whole_archive_flag_spec"; then - eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` - else - gentop="$output_objdir/${obj}x" - func_append generated " $gentop" - - func_extract_archives $gentop $convenience - reload_conv_objs="$reload_objs $func_extract_archives_result" - fi - fi - - # If we're not building shared, we need to use non_pic_objs - test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" - - # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test - - output="$obj" - func_execute_cmds "$reload_cmds" 'exit $?' - - # Exit if we aren't doing a library object file. - if test -z "$libobj"; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - fi - - if test "$build_libtool_libs" != yes; then - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - # Create an invalid libtool object if no PIC, so that we don't - # accidentally link it into a program. - # $show "echo timestamp > $libobj" - # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? - exit $EXIT_SUCCESS - fi - - if test -n "$pic_flag" || test "$pic_mode" != default; then - # Only do commands if we really have different PIC objects. - reload_objs="$libobjs $reload_conv_objs" - output="$libobj" - func_execute_cmds "$reload_cmds" 'exit $?' - fi - - if test -n "$gentop"; then - func_show_eval '${RM}r "$gentop"' - fi - - exit $EXIT_SUCCESS - ;; - - prog) - case $host in - *cygwin*) func_stripname '' '.exe' "$output" - output=$func_stripname_result.exe;; - esac - test -n "$vinfo" && \ - func_warning "\`-version-info' is ignored for programs" - - test -n "$release" && \ - func_warning "\`-release' is ignored for programs" - - test "$preload" = yes \ - && test "$dlopen_support" = unknown \ - && test "$dlopen_self" = unknown \ - && test "$dlopen_self_static" = unknown && \ - func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." - - case $host in - *-*-rhapsody* | *-*-darwin1.[012]) - # On Rhapsody replace the C library is the System framework - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` - ;; - esac - - case $host in - *-*-darwin*) - # Don't allow lazy linking, it breaks C++ global constructors - # But is supposedly fixed on 10.4 or later (yay!). - if test "$tagname" = CXX ; then - case ${MACOSX_DEPLOYMENT_TARGET-10.0} in - 10.[0123]) - func_append compile_command " ${wl}-bind_at_load" - func_append finalize_command " ${wl}-bind_at_load" - ;; - esac - fi - # Time to change all our "foo.ltframework" stuff back to "-framework foo" - compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` - ;; - esac - - - # move library search paths that coincide with paths to not yet - # installed libraries to the beginning of the library search list - new_libs= - for path in $notinst_path; do - case " $new_libs " in - *" -L$path/$objdir "*) ;; - *) - case " $compile_deplibs " in - *" -L$path/$objdir "*) - func_append new_libs " -L$path/$objdir" ;; - esac - ;; - esac - done - for deplib in $compile_deplibs; do - case $deplib in - -L*) - case " $new_libs " in - *" $deplib "*) ;; - *) func_append new_libs " $deplib" ;; - esac - ;; - *) func_append new_libs " $deplib" ;; - esac - done - compile_deplibs="$new_libs" - - - func_append compile_command " $compile_deplibs" - func_append finalize_command " $finalize_deplibs" - - if test -n "$rpath$xrpath"; then - # If the user specified any rpath flags, then add them. - for libdir in $rpath $xrpath; do - # This is the magic to use -rpath. - case "$finalize_rpath " in - *" $libdir "*) ;; - *) func_append finalize_rpath " $libdir" ;; - esac - done - fi - - # Now hardcode the library paths - rpath= - hardcode_libdirs= - for libdir in $compile_rpath $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$perm_rpath " in - *" $libdir "*) ;; - *) func_append perm_rpath " $libdir" ;; - esac - fi - case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` - case :$dllsearchpath: in - *":$libdir:"*) ;; - ::) dllsearchpath=$libdir;; - *) func_append dllsearchpath ":$libdir";; - esac - case :$dllsearchpath: in - *":$testbindir:"*) ;; - ::) dllsearchpath=$testbindir;; - *) func_append dllsearchpath ":$testbindir";; - esac - ;; - esac - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - compile_rpath="$rpath" - - rpath= - hardcode_libdirs= - for libdir in $finalize_rpath; do - if test -n "$hardcode_libdir_flag_spec"; then - if test -n "$hardcode_libdir_separator"; then - if test -z "$hardcode_libdirs"; then - hardcode_libdirs="$libdir" - else - # Just accumulate the unique libdirs. - case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in - *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) - ;; - *) - func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" - ;; - esac - fi - else - eval flag=\"$hardcode_libdir_flag_spec\" - func_append rpath " $flag" - fi - elif test -n "$runpath_var"; then - case "$finalize_perm_rpath " in - *" $libdir "*) ;; - *) func_append finalize_perm_rpath " $libdir" ;; - esac - fi - done - # Substitute the hardcoded libdirs into the rpath. - if test -n "$hardcode_libdir_separator" && - test -n "$hardcode_libdirs"; then - libdir="$hardcode_libdirs" - eval rpath=\" $hardcode_libdir_flag_spec\" - fi - finalize_rpath="$rpath" - - if test -n "$libobjs" && test "$build_old_libs" = yes; then - # Transform all the library objects into standard objects. - compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` - fi - - func_generate_dlsyms "$outputname" "@PROGRAM@" "no" - - # template prelinking step - if test -n "$prelink_cmds"; then - func_execute_cmds "$prelink_cmds" 'exit $?' - fi - - wrappers_required=yes - case $host in - *cegcc* | *mingw32ce*) - # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. - wrappers_required=no - ;; - *cygwin* | *mingw* ) - if test "$build_libtool_libs" != yes; then - wrappers_required=no - fi - ;; - *) - if test "$need_relink" = no || test "$build_libtool_libs" != yes; then - wrappers_required=no - fi - ;; - esac - if test "$wrappers_required" = no; then - # Replace the output file specification. - compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - link_command="$compile_command$compile_rpath" - - # We have no uninstalled library dependencies, so finalize right now. - exit_status=0 - func_show_eval "$link_command" 'exit_status=$?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Delete the generated files. - if test -f "$output_objdir/${outputname}S.${objext}"; then - func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' - fi - - exit $exit_status - fi - - if test -n "$compile_shlibpath$finalize_shlibpath"; then - compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" - fi - if test -n "$finalize_shlibpath"; then - finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" - fi - - compile_var= - finalize_var= - if test -n "$runpath_var"; then - if test -n "$perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $perm_rpath; do - func_append rpath "$dir:" - done - compile_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - if test -n "$finalize_perm_rpath"; then - # We should set the runpath_var. - rpath= - for dir in $finalize_perm_rpath; do - func_append rpath "$dir:" - done - finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " - fi - fi - - if test "$no_install" = yes; then - # We don't need to create a wrapper script. - link_command="$compile_var$compile_command$compile_rpath" - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` - # Delete the old output file. - $opt_dry_run || $RM $output - # Link the executable and exit - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - exit $EXIT_SUCCESS - fi - - if test "$hardcode_action" = relink; then - # Fast installation is not supported - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - - func_warning "this platform does not like uninstalled shared libraries" - func_warning "\`$output' will be relinked during installation" - else - if test "$fast_install" != no; then - link_command="$finalize_var$compile_command$finalize_rpath" - if test "$fast_install" = yes; then - relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` - else - # fast_install is set to needless - relink_command= - fi - else - link_command="$compile_var$compile_command$compile_rpath" - relink_command="$finalize_var$finalize_command$finalize_rpath" - fi - fi - - # Replace the output file specification. - link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` - - # Delete the old output files. - $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname - - func_show_eval "$link_command" 'exit $?' - - if test -n "$postlink_cmds"; then - func_to_tool_file "$output_objdir/$outputname" - postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` - func_execute_cmds "$postlink_cmds" 'exit $?' - fi - - # Now create the wrapper script. - func_verbose "creating $output" - - # Quote the relink command for shipping. - if test -n "$relink_command"; then - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - fi - - # Only actually do things if not in dry run mode. - $opt_dry_run || { - # win32 will think the script is a binary if it has - # a .exe suffix, so we strip it off here. - case $output in - *.exe) func_stripname '' '.exe' "$output" - output=$func_stripname_result ;; - esac - # test for cygwin because mv fails w/o .exe extensions - case $host in - *cygwin*) - exeext=.exe - func_stripname '' '.exe' "$outputname" - outputname=$func_stripname_result ;; - *) exeext= ;; - esac - case $host in - *cygwin* | *mingw* ) - func_dirname_and_basename "$output" "" "." - output_name=$func_basename_result - output_path=$func_dirname_result - cwrappersource="$output_path/$objdir/lt-$output_name.c" - cwrapper="$output_path/$output_name.exe" - $RM $cwrappersource $cwrapper - trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 - - func_emit_cwrapperexe_src > $cwrappersource - - # The wrapper executable is built using the $host compiler, - # because it contains $host paths and files. If cross- - # compiling, it, like the target executable, must be - # executed on the $host or under an emulation environment. - $opt_dry_run || { - $LTCC $LTCFLAGS -o $cwrapper $cwrappersource - $STRIP $cwrapper - } - - # Now, create the wrapper script for func_source use: - func_ltwrapper_scriptname $cwrapper - $RM $func_ltwrapper_scriptname_result - trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 - $opt_dry_run || { - # note: this script will not be executed, so do not chmod. - if test "x$build" = "x$host" ; then - $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result - else - func_emit_wrapper no > $func_ltwrapper_scriptname_result - fi - } - ;; - * ) - $RM $output - trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 - - func_emit_wrapper no > $output - chmod +x $output - ;; - esac - } - exit $EXIT_SUCCESS - ;; - esac - - # See if we need to build an old-fashioned archive. - for oldlib in $oldlibs; do - - if test "$build_libtool_libs" = convenience; then - oldobjs="$libobjs_save $symfileobj" - addlibs="$convenience" - build_libtool_libs=no - else - if test "$build_libtool_libs" = module; then - oldobjs="$libobjs_save" - build_libtool_libs=no - else - oldobjs="$old_deplibs $non_pic_objects" - if test "$preload" = yes && test -f "$symfileobj"; then - func_append oldobjs " $symfileobj" - fi - fi - addlibs="$old_convenience" - fi - - if test -n "$addlibs"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $addlibs - func_append oldobjs " $func_extract_archives_result" - fi - - # Do each command in the archive commands. - if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then - cmds=$old_archive_from_new_cmds - else - - # Add any objects from preloaded convenience libraries - if test -n "$dlprefiles"; then - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - - func_extract_archives $gentop $dlprefiles - func_append oldobjs " $func_extract_archives_result" - fi - - # POSIX demands no paths to be encoded in archives. We have - # to avoid creating archives with duplicate basenames if we - # might have to extract them afterwards, e.g., when creating a - # static archive out of a convenience library, or when linking - # the entirety of a libtool archive into another (currently - # not supported by libtool). - if (for obj in $oldobjs - do - func_basename "$obj" - $ECHO "$func_basename_result" - done | sort | sort -uc >/dev/null 2>&1); then - : - else - echo "copying selected object files to avoid basename conflicts..." - gentop="$output_objdir/${outputname}x" - func_append generated " $gentop" - func_mkdir_p "$gentop" - save_oldobjs=$oldobjs - oldobjs= - counter=1 - for obj in $save_oldobjs - do - func_basename "$obj" - objbase="$func_basename_result" - case " $oldobjs " in - " ") oldobjs=$obj ;; - *[\ /]"$objbase "*) - while :; do - # Make sure we don't pick an alternate name that also - # overlaps. - newobj=lt$counter-$objbase - func_arith $counter + 1 - counter=$func_arith_result - case " $oldobjs " in - *[\ /]"$newobj "*) ;; - *) if test ! -f "$gentop/$newobj"; then break; fi ;; - esac - done - func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" - func_append oldobjs " $gentop/$newobj" - ;; - *) func_append oldobjs " $obj" ;; - esac - done - fi - func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 - tool_oldlib=$func_to_tool_file_result - eval cmds=\"$old_archive_cmds\" - - func_len " $cmds" - len=$func_len_result - if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then - cmds=$old_archive_cmds - elif test -n "$archiver_list_spec"; then - func_verbose "using command file archive linking..." - for obj in $oldobjs - do - func_to_tool_file "$obj" - $ECHO "$func_to_tool_file_result" - done > $output_objdir/$libname.libcmd - func_to_tool_file "$output_objdir/$libname.libcmd" - oldobjs=" $archiver_list_spec$func_to_tool_file_result" - cmds=$old_archive_cmds - else - # the command line is too long to link in one step, link in parts - func_verbose "using piecewise archive linking..." - save_RANLIB=$RANLIB - RANLIB=: - objlist= - concat_cmds= - save_oldobjs=$oldobjs - oldobjs= - # Is there a better way of finding the last object in the list? - for obj in $save_oldobjs - do - last_oldobj=$obj - done - eval test_cmds=\"$old_archive_cmds\" - func_len " $test_cmds" - len0=$func_len_result - len=$len0 - for obj in $save_oldobjs - do - func_len " $obj" - func_arith $len + $func_len_result - len=$func_arith_result - func_append objlist " $obj" - if test "$len" -lt "$max_cmd_len"; then - : - else - # the above command should be used before it gets too long - oldobjs=$objlist - if test "$obj" = "$last_oldobj" ; then - RANLIB=$save_RANLIB - fi - test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" - objlist= - len=$len0 - fi - done - RANLIB=$save_RANLIB - oldobjs=$objlist - if test "X$oldobjs" = "X" ; then - eval cmds=\"\$concat_cmds\" - else - eval cmds=\"\$concat_cmds~\$old_archive_cmds\" - fi - fi - fi - func_execute_cmds "$cmds" 'exit $?' - done - - test -n "$generated" && \ - func_show_eval "${RM}r$generated" - - # Now create the libtool archive. - case $output in - *.la) - old_library= - test "$build_old_libs" = yes && old_library="$libname.$libext" - func_verbose "creating $output" - - # Preserve any variables that may affect compiler behavior - for var in $variables_saved_for_relink; do - if eval test -z \"\${$var+set}\"; then - relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" - elif eval var_value=\$$var; test -z "$var_value"; then - relink_command="$var=; export $var; $relink_command" - else - func_quote_for_eval "$var_value" - relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" - fi - done - # Quote the link command for shipping. - relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` - if test "$hardcode_automatic" = yes ; then - relink_command= - fi - - # Only create the output if not a dry run. - $opt_dry_run || { - for installed in no yes; do - if test "$installed" = yes; then - if test -z "$install_libdir"; then - break - fi - output="$output_objdir/$outputname"i - # Replace all uninstalled libtool libraries with the installed ones - newdependency_libs= - for deplib in $dependency_libs; do - case $deplib in - *.la) - func_basename "$deplib" - name="$func_basename_result" - func_resolve_sysroot "$deplib" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` - test -z "$libdir" && \ - func_fatal_error "\`$deplib' is not a valid libtool archive" - func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" - ;; - -L*) - func_stripname -L '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -L$func_replace_sysroot_result" - ;; - -R*) - func_stripname -R '' "$deplib" - func_replace_sysroot "$func_stripname_result" - func_append newdependency_libs " -R$func_replace_sysroot_result" - ;; - *) func_append newdependency_libs " $deplib" ;; - esac - done - dependency_libs="$newdependency_libs" - newdlfiles= - - for lib in $dlfiles; do - case $lib in - *.la) - func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" - func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" - ;; - *) func_append newdlfiles " $lib" ;; - esac - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - *.la) - # Only pass preopened files to the pseudo-archive (for - # eventual linking with the app. that links it) if we - # didn't already link the preopened objects directly into - # the library: - func_basename "$lib" - name="$func_basename_result" - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` - test -z "$libdir" && \ - func_fatal_error "\`$lib' is not a valid libtool archive" - func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" - ;; - esac - done - dlprefiles="$newdlprefiles" - else - newdlfiles= - for lib in $dlfiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlfiles " $abs" - done - dlfiles="$newdlfiles" - newdlprefiles= - for lib in $dlprefiles; do - case $lib in - [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; - *) abs=`pwd`"/$lib" ;; - esac - func_append newdlprefiles " $abs" - done - dlprefiles="$newdlprefiles" - fi - $RM $output - # place dlname in correct position for cygwin - # In fact, it would be nice if we could use this code for all target - # systems that can't hard-code library paths into their executables - # and that have no shared library path variable independent of PATH, - # but it turns out we can't easily determine that from inspecting - # libtool variables, so we have to hard-code the OSs to which it - # applies here; at the moment, that means platforms that use the PE - # object format with DLL files. See the long comment at the top of - # tests/bindir.at for full details. - tdlname=$dlname - case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) - # If a -bindir argument was supplied, place the dll there. - if test "x$bindir" != x ; - then - func_relative_path "$install_libdir" "$bindir" - tdlname=$func_relative_path_result$dlname - else - # Otherwise fall back on heuristic. - tdlname=../bin/$dlname - fi - ;; - esac - $ECHO > $output "\ -# $outputname - a libtool library file -# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION -# -# Please DO NOT delete this file! -# It is necessary for linking the library. - -# The name that we can dlopen(3). -dlname='$tdlname' - -# Names of this library. -library_names='$library_names' - -# The name of the static archive. -old_library='$old_library' - -# Linker flags that can not go in dependency_libs. -inherited_linker_flags='$new_inherited_linker_flags' - -# Libraries that this one depends upon. -dependency_libs='$dependency_libs' - -# Names of additional weak libraries provided by this library -weak_library_names='$weak_libs' - -# Version information for $libname. -current=$current -age=$age -revision=$revision - -# Is this an already installed library? -installed=$installed - -# Should we warn about portability when linking against -modules? -shouldnotlink=$module - -# Files to dlopen/dlpreopen -dlopen='$dlfiles' -dlpreopen='$dlprefiles' - -# Directory that this library needs to be installed in: -libdir='$install_libdir'" - if test "$installed" = no && test "$need_relink" = yes; then - $ECHO >> $output "\ -relink_command=\"$relink_command\"" - fi - done - } - - # Do a symbolic link so that the libtool archive can be found in - # LD_LIBRARY_PATH before the program is installed. - func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' - ;; - esac - exit $EXIT_SUCCESS -} - -{ test "$opt_mode" = link || test "$opt_mode" = relink; } && - func_mode_link ${1+"$@"} - - -# func_mode_uninstall arg... -func_mode_uninstall () -{ - $opt_debug - RM="$nonopt" - files= - rmforce= - exit_status=0 - - # This variable tells wrapper scripts just to set variables rather - # than running their programs. - libtool_install_magic="$magic" - - for arg - do - case $arg in - -f) func_append RM " $arg"; rmforce=yes ;; - -*) func_append RM " $arg" ;; - *) func_append files " $arg" ;; - esac - done - - test -z "$RM" && \ - func_fatal_help "you must specify an RM program" - - rmdirs= - - for file in $files; do - func_dirname "$file" "" "." - dir="$func_dirname_result" - if test "X$dir" = X.; then - odir="$objdir" - else - odir="$dir/$objdir" - fi - func_basename "$file" - name="$func_basename_result" - test "$opt_mode" = uninstall && odir="$dir" - - # Remember odir for removal later, being careful to avoid duplicates - if test "$opt_mode" = clean; then - case " $rmdirs " in - *" $odir "*) ;; - *) func_append rmdirs " $odir" ;; - esac - fi - - # Don't error if the file doesn't exist and rm -f was used. - if { test -L "$file"; } >/dev/null 2>&1 || - { test -h "$file"; } >/dev/null 2>&1 || - test -f "$file"; then - : - elif test -d "$file"; then - exit_status=1 - continue - elif test "$rmforce" = yes; then - continue - fi - - rmfiles="$file" - - case $name in - *.la) - # Possibly a libtool archive, so verify it. - if func_lalib_p "$file"; then - func_source $dir/$name - - # Delete the libtool libraries and symlinks. - for n in $library_names; do - func_append rmfiles " $odir/$n" - done - test -n "$old_library" && func_append rmfiles " $odir/$old_library" - - case "$opt_mode" in - clean) - case " $library_names " in - *" $dlname "*) ;; - *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; - esac - test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" - ;; - uninstall) - if test -n "$library_names"; then - # Do each command in the postuninstall commands. - func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' - fi - - if test -n "$old_library"; then - # Do each command in the old_postuninstall commands. - func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' - fi - # FIXME: should reinstall the best remaining shared library. - ;; - esac - fi - ;; - - *.lo) - # Possibly a libtool object, so verify it. - if func_lalib_p "$file"; then - - # Read the .lo file - func_source $dir/$name - - # Add PIC object to the list of files to remove. - if test -n "$pic_object" && - test "$pic_object" != none; then - func_append rmfiles " $dir/$pic_object" - fi - - # Add non-PIC object to the list of files to remove. - if test -n "$non_pic_object" && - test "$non_pic_object" != none; then - func_append rmfiles " $dir/$non_pic_object" - fi - fi - ;; - - *) - if test "$opt_mode" = clean ; then - noexename=$name - case $file in - *.exe) - func_stripname '' '.exe' "$file" - file=$func_stripname_result - func_stripname '' '.exe' "$name" - noexename=$func_stripname_result - # $file with .exe has already been added to rmfiles, - # add $file without .exe - func_append rmfiles " $file" - ;; - esac - # Do a test to see if this is a libtool program. - if func_ltwrapper_p "$file"; then - if func_ltwrapper_executable_p "$file"; then - func_ltwrapper_scriptname "$file" - relink_command= - func_source $func_ltwrapper_scriptname_result - func_append rmfiles " $func_ltwrapper_scriptname_result" - else - relink_command= - func_source $dir/$noexename - fi - - # note $name still contains .exe if it was in $file originally - # as does the version of $file that was added into $rmfiles - func_append rmfiles " $odir/$name $odir/${name}S.${objext}" - if test "$fast_install" = yes && test -n "$relink_command"; then - func_append rmfiles " $odir/lt-$name" - fi - if test "X$noexename" != "X$name" ; then - func_append rmfiles " $odir/lt-${noexename}.c" - fi - fi - fi - ;; - esac - func_show_eval "$RM $rmfiles" 'exit_status=1' - done - - # Try to remove the ${objdir}s in the directories where we deleted files - for dir in $rmdirs; do - if test -d "$dir"; then - func_show_eval "rmdir $dir >/dev/null 2>&1" - fi - done - - exit $exit_status -} - -{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && - func_mode_uninstall ${1+"$@"} - -test -z "$opt_mode" && { - help="$generic_help" - func_fatal_help "you must specify a MODE" -} - -test -z "$exec_cmd" && \ - func_fatal_help "invalid operation mode \`$opt_mode'" - -if test -n "$exec_cmd"; then - eval exec "$exec_cmd" - exit $EXIT_FAILURE -fi - -exit $exit_status - - -# The TAGs below are defined such that we never get into a situation -# in which we disable both kinds of libraries. Given conflicting -# choices, we go for a static library, that is the most portable, -# since we can't tell whether shared libraries were disabled because -# the user asked for that or because the platform doesn't support -# them. This is particularly important on AIX, because we don't -# support having both static and shared libraries enabled at the same -# time on that platform, so we default to a shared-only configuration. -# If a disable-shared tag is given, we'll fallback to a static-only -# configuration. But we'll never go from static-only to shared-only. - -# ### BEGIN LIBTOOL TAG CONFIG: disable-shared -build_libtool_libs=no -build_old_libs=yes -# ### END LIBTOOL TAG CONFIG: disable-shared - -# ### BEGIN LIBTOOL TAG CONFIG: disable-static -build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` -# ### END LIBTOOL TAG CONFIG: disable-static - -# Local Variables: -# mode:shell-script -# sh-indentation:2 -# End: -# vi:sw=2 - diff --git a/autoconf/missing b/autoconf/missing deleted file mode 100755 index 86a8fc3..0000000 --- a/autoconf/missing +++ /dev/null @@ -1,331 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. - -scriptversion=2012-01-06.13; # UTC - -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, -# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: -sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' -sed_minuso='s/.* -o \([^ ]*\).*/\1/p' - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -msg="missing on your system" - -case $1 in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - autom4te touch the output file, or create a stub one - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - yacc create \`y.tab.[ch]', if possible, from existing .[ch] - -Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and -\`g' are ignored when checking the name. - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - -esac - -# normalize program name to check for. -program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - -# Now exit if we have it, but it failed. Also exit now if we -# don't have it and --version was passed (most likely to detect -# the program). This is about non-GNU programs, so use $1 not -# $program. -case $1 in - lex*|yacc*) - # Not GNU programs, they don't have --version. - ;; - - *) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - # Could not run --version or --help. This is probably someone - # running `$TOOL --version' or `$TOOL --help' to check whether - # $TOOL exists and not knowing $TOOL uses missing. - exit 1 - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case $program in - aclocal*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case $f in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te*) - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison*|yacc*) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if test $# -ne 1; then - eval LASTARG=\${$#} - case $LASTARG in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if test ! -f y.tab.h; then - echo >y.tab.h - fi - if test ! -f y.tab.c; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex*|flex*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if test $# -ne 1; then - eval LASTARG=\${$#} - case $LASTARG in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if test ! -f lex.yy.c; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit $? - fi - ;; - - makeinfo*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -z "$file"; then - # ... or it is the one specified with @setfilename ... - infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n ' - /^@setfilename/{ - s/.* \([^ ]*\) *$/\1/ - p - q - }' $infile` - # ... or it is derived from the source name (dir/f.texi becomes f.info) - test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info - fi - # If the file does not exist, the user really needs makeinfo; - # let's fail without touching anything. - test -f $file || exit 1 - touch $file - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/autoconf/tea/Makefile.in b/autoconf/tea/Makefile.in index a870897..3e481da 100644 --- a/autoconf/tea/Makefile.in +++ b/autoconf/tea/Makefile.in @@ -348,7 +348,7 @@ clean: distclean: clean -rm -f *.tab.c -rm -f $(CONFIG_CLEAN_FILES) - -rm -f config.cache config.log config.status + -rm -f config.h config.cache config.log config.status #======================================================================== # Install binary object libraries. On Windows this includes both .dll and diff --git a/autoconf/tea/win/nmakehlp.c b/autoconf/tea/win/nmakehlp.c index 2868857..e00f1b4 100644 --- a/autoconf/tea/win/nmakehlp.c +++ b/autoconf/tea/win/nmakehlp.c @@ -603,8 +603,8 @@ SubstituteFile( sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { - char *ks, *ke, *vs, *ve; - ks = szBuffer; + unsigned char *ks, *ke, *vs, *ve; + ks = (unsigned char*)szBuffer; while (ks && *ks && isspace(*ks)) ++ks; ke = ks; while (ke && *ke && !isspace(*ke)) ++ke; @@ -613,7 +613,7 @@ SubstituteFile( ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; - list_insert(&substPtr, ks, vs); + list_insert(&substPtr, (char*)ks, (char*)vs); } fclose(sp); } diff --git a/configure b/configure index c73b820..b2cb4d1 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sqlite 3.8.10.2. +# Generated by GNU Autoconf 2.69 for sqlite 3.11.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -726,8 +726,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.8.10.2' -PACKAGE_STRING='sqlite 3.8.10.2' +PACKAGE_VERSION='3.11.0' +PACKAGE_STRING='sqlite 3.11.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -774,6 +774,7 @@ USE_GCOV OPT_FEATURE_FLAGS USE_AMALGAMATION TARGET_DEBUG +TARGET_HAVE_EDITLINE TARGET_HAVE_READLINE TARGET_READLINE_INC TARGET_READLINE_LIBS @@ -803,7 +804,6 @@ VERSION program_prefix TCLLIBDIR TCLSH_CMD -AWK INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM @@ -896,12 +896,18 @@ enable_releasemode enable_tempstore enable_tcl with_tcl +enable_editline enable_readline with_readline_lib with_readline_inc enable_debug enable_amalgamation enable_load_extension +enable_fts3 +enable_fts4 +enable_fts5 +enable_json1 +enable_rtree enable_gcov ' ac_precious_vars='build_alias @@ -1454,7 +1460,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.8.10.2 to adapt to many kinds of systems. +\`configure' configures sqlite 3.11.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1519,7 +1525,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.8.10.2:";; + short | recursive ) echo "Configuration of sqlite 3.11.0:";; esac cat <<\_ACEOF @@ -1538,12 +1544,18 @@ Optional Features: --enable-tempstore Use an in-ram database for temporary tables (never,no,yes,always) --disable-tcl do not build TCL extension - --disable-readline disable readline support [default=detect] + --enable-editline enable BSD editline support + --disable-readline disable readline support --enable-debug enable debugging & verbose explain --disable-amalgamation Disable the amalgamation and instead build all files separately --disable-load-extension Disable loading of external extensions + --enable-fts3 Enable the FTS3 extension + --enable-fts4 Enable the FTS4 extension + --enable-fts5 Enable the FTS5 extension + --enable-json1 Enable the JSON1 extension + --enable-rtree Enable the RTREE extension --enable-gcov Enable coverage testing using gcov Optional Packages: @@ -1634,7 +1646,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.8.10.2 +sqlite configure 3.11.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2053,7 +2065,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.8.10.2, which was +It was created by sqlite $as_me 3.11.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3911,13 +3923,13 @@ if ${lt_cv_nm_interface+:} false; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:3914: $ac_compile\"" >&5) + (eval echo "\"\$as_me:3926: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:3917: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:3929: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:3920: output\"" >&5) + (eval echo "\"\$as_me:3932: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -5123,7 +5135,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 5126 "configure"' > conftest.$ac_ext + echo '#line 5138 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -6648,11 +6660,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6651: $lt_compile\"" >&5) + (eval echo "\"\$as_me:6663: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6655: \$? = $ac_status" >&5 + echo "$as_me:6667: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -6987,11 +6999,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:6990: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7002: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:6994: \$? = $ac_status" >&5 + echo "$as_me:7006: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7092,11 +7104,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7095: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7107: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7099: \$? = $ac_status" >&5 + echo "$as_me:7111: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -7147,11 +7159,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7150: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7162: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7154: \$? = $ac_status" >&5 + echo "$as_me:7166: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9527,7 +9539,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 9530 "configure" +#line 9542 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -9623,7 +9635,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 9626 "configure" +#line 9638 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -9943,48 +9955,6 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AWK" && break -done - ######### # Enable large file support (if special flags are necessary) @@ -10548,6 +10518,62 @@ ac_res=$ac_cv_search_pthread_create if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_mutexattr_init" >&5 +$as_echo_n "checking for library containing pthread_mutexattr_init... " >&6; } +if ${ac_cv_search_pthread_mutexattr_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutexattr_init (); +int +main () +{ +return pthread_mutexattr_init (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_pthread_mutexattr_init=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_pthread_mutexattr_init+:} false; then : + break +fi +done +if ${ac_cv_search_pthread_mutexattr_init+:} false; then : + +else + ac_cv_search_pthread_mutexattr_init=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_mutexattr_init" >&5 +$as_echo "$ac_cv_search_pthread_mutexattr_init" >&6; } +ac_res=$ac_cv_search_pthread_mutexattr_init +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + fi fi @@ -10715,6 +10741,20 @@ else fi fi + # On ubuntu 14.10, $auto_path on tclsh is not quite correct. + # So try again after applying corrections. + if test x"${ac_cv_c_tclconfig}" = x ; then + if test x"$cross_compiling" = xno; then + for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'` + do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="$i" + break + fi + done + fi + fi + # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ @@ -10851,6 +10891,14 @@ fi TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 +TARGET_HAVE_EDITLINE=0 +# Check whether --enable-editline was given. +if test "${enable_editline+set}" = set; then : + enableval=$enable_editline; with_editline=$enableval +else + with_editline=auto +fi + # Check whether --enable-readline was given. if test "${enable_readline+set}" = set; then : enableval=$enable_readline; with_readline=$enableval @@ -10859,6 +10907,71 @@ else fi +if test x"$with_editline" != xno; then + sLIBS=$LIBS + LIBS="" + TARGET_HAVE_EDITLINE=1 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing readline" >&5 +$as_echo_n "checking for library containing readline... " >&6; } +if ${ac_cv_search_readline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char readline (); +int +main () +{ +return readline (); + ; + return 0; +} +_ACEOF +for ac_lib in '' edit; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_readline=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_readline+:} false; then : + break +fi +done +if ${ac_cv_search_readline+:} false; then : + +else + ac_cv_search_readline=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_readline" >&5 +$as_echo "$ac_cv_search_readline" >&6; } +ac_res=$ac_cv_search_readline +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + with_readline=no +else + TARGET_HAVE_EDITLINE=0 +fi + + TARGET_READLINE_LIBS=$LIBS + LIBS=$sLIBS +fi if test x"$with_readline" != xno; then found="yes" @@ -11047,6 +11160,7 @@ fi + ########## # Figure out what C libraries are required to compile programs # that use "fdatasync()" function. @@ -11209,6 +11323,177 @@ else OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1" fi +######### +# See whether we should enable Full Text Search extensions +# Check whether --enable-fts3 was given. +if test "${enable_fts3+set}" = set; then : + enableval=$enable_fts3; enable_fts3=yes +else + enable_fts3=no +fi + +if test "${enable_fts3}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3" +fi +# Check whether --enable-fts4 was given. +if test "${enable_fts4+set}" = set; then : + enableval=$enable_fts4; enable_fts4=yes +else + enable_fts4=no +fi + +if test "${enable_fts4}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5 +$as_echo_n "checking for library containing log... " >&6; } +if ${ac_cv_search_log+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char log (); +int +main () +{ +return log (); + ; + return 0; +} +_ACEOF +for ac_lib in '' m; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_log=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_log+:} false; then : + break +fi +done +if ${ac_cv_search_log+:} false; then : + +else + ac_cv_search_log=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log" >&5 +$as_echo "$ac_cv_search_log" >&6; } +ac_res=$ac_cv_search_log +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi +# Check whether --enable-fts5 was given. +if test "${enable_fts5+set}" = set; then : + enableval=$enable_fts5; enable_fts5=yes +else + enable_fts5=no +fi + +if test "${enable_fts5}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5 +$as_echo_n "checking for library containing log... " >&6; } +if ${ac_cv_search_log+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char log (); +int +main () +{ +return log (); + ; + return 0; +} +_ACEOF +for ac_lib in '' m; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_log=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_log+:} false; then : + break +fi +done +if ${ac_cv_search_log+:} false; then : + +else + ac_cv_search_log=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_log" >&5 +$as_echo "$ac_cv_search_log" >&6; } +ac_res=$ac_cv_search_log +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +######### +# See whether we should enable JSON1 +# Check whether --enable-json1 was given. +if test "${enable_json1+set}" = set; then : + enableval=$enable_json1; enable_json1=yes +else + enable_json1=no +fi + +if test "${enable_json1}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1" +fi + +######### +# See whether we should enable RTREE +# Check whether --enable-rtree was given. +if test "${enable_rtree+set}" = set; then : + enableval=$enable_rtree; enable_rtree=yes +else + enable_rtree=no +fi + +if test "${enable_rtree}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE" +fi + ######### # attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter for option in $CFLAGS $CPPFLAGS @@ -11794,7 +12079,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.8.10.2, which was +This file was extended by sqlite $as_me 3.11.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -11860,7 +12145,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sqlite config.status 3.8.10.2 +sqlite config.status 3.11.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -11871,7 +12156,6 @@ gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' -AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF diff --git a/configure.ac b/configure.ac index 6a11888..19f85dc 100644 --- a/configure.ac +++ b/configure.ac @@ -90,7 +90,6 @@ fi # AC_PROG_LIBTOOL AC_PROG_INSTALL -AC_PROG_AWK ######### # Enable large file support (if special flags are necessary) @@ -196,6 +195,7 @@ AC_SUBST(SQLITE_THREADSAFE) if test "$SQLITE_THREADSAFE" = "1"; then AC_SEARCH_LIBS(pthread_create, pthread) + AC_SEARCH_LIBS(pthread_mutexattr_init, pthread) fi ########## @@ -320,6 +320,20 @@ if test "${use_tcl}" = "yes" ; then fi fi + # On ubuntu 14.10, $auto_path on tclsh is not quite correct. + # So try again after applying corrections. + if test x"${ac_cv_c_tclconfig}" = x ; then + if test x"$cross_compiling" = xno; then + for i in `echo 'puts stdout $auto_path' | ${TCLSH_CMD} | sed 's,/tcltk/tcl,/tcl,g'` + do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig="$i" + break + fi + done + fi + fi + # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ @@ -447,11 +461,24 @@ AC_SUBST(HAVE_TCL) TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 +TARGET_HAVE_EDITLINE=0 +AC_ARG_ENABLE([editline], + [AC_HELP_STRING([--enable-editline],[enable BSD editline support])], + [with_editline=$enableval], + [with_editline=auto]) AC_ARG_ENABLE([readline], - [AC_HELP_STRING([--disable-readline],[disable readline support [default=detect]])], + [AC_HELP_STRING([--disable-readline],[disable readline support])], [with_readline=$enableval], [with_readline=auto]) +if test x"$with_editline" != xno; then + sLIBS=$LIBS + LIBS="" + TARGET_HAVE_EDITLINE=1 + AC_SEARCH_LIBS(readline,edit,[with_readline=no],[TARGET_HAVE_EDITLINE=0]) + TARGET_READLINE_LIBS=$LIBS + LIBS=$sLIBS +fi if test x"$with_readline" != xno; then found="yes" @@ -506,6 +533,7 @@ fi AC_SUBST(TARGET_READLINE_LIBS) AC_SUBST(TARGET_READLINE_INC) AC_SUBST(TARGET_HAVE_READLINE) +AC_SUBST(TARGET_HAVE_EDITLINE) ########## # Figure out what C libraries are required to compile programs @@ -546,6 +574,47 @@ else OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1" fi +######### +# See whether we should enable Full Text Search extensions +AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3], + [Enable the FTS3 extension]), + [enable_fts3=yes],[enable_fts3=no]) +if test "${enable_fts3}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS3" +fi +AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4], + [Enable the FTS4 extension]), + [enable_fts4=yes],[enable_fts4=no]) +if test "${enable_fts4}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS4" + AC_SEARCH_LIBS([log],[m]) +fi +AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5], + [Enable the FTS5 extension]), + [enable_fts5=yes],[enable_fts5=no]) +if test "${enable_fts5}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_FTS5" + AC_SEARCH_LIBS([log],[m]) +fi + +######### +# See whether we should enable JSON1 +AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1], + [Enable the JSON1 extension]), + [enable_json1=yes],[enable_json1=no]) +if test "${enable_json1}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_JSON1" +fi + +######### +# See whether we should enable RTREE +AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree], + [Enable the RTREE extension]), + [enable_rtree=yes],[enable_rtree=no]) +if test "${enable_rtree}" = "yes" ; then + OPT_FEATURE_FLAGS+=" -DSQLITE_ENABLE_RTREE" +fi + ######### # attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter for option in $CFLAGS $CPPFLAGS diff --git a/ext/async/sqlite3async.c b/ext/async/sqlite3async.c index 4ab39ca..b6f4a4b 100644 --- a/ext/async/sqlite3async.c +++ b/ext/async/sqlite3async.c @@ -1636,6 +1636,7 @@ void sqlite3async_run(void){ ** Control/configure the asynchronous IO system. */ int sqlite3async_control(int op, ...){ + int rc = SQLITE_OK; va_list ap; va_start(ap, op); switch( op ){ @@ -1645,7 +1646,8 @@ int sqlite3async_control(int op, ...){ && eWhen!=SQLITEASYNC_HALT_NOW && eWhen!=SQLITEASYNC_HALT_IDLE ){ - return SQLITE_MISUSE; + rc = SQLITE_MISUSE; + break; } async.eHalt = eWhen; async_mutex_enter(ASYNC_MUTEX_QUEUE); @@ -1657,7 +1659,8 @@ int sqlite3async_control(int op, ...){ case SQLITEASYNC_DELAY: { int iDelay = va_arg(ap, int); if( iDelay<0 ){ - return SQLITE_MISUSE; + rc = SQLITE_MISUSE; + break; } async.ioDelay = iDelay; break; @@ -1668,7 +1671,8 @@ int sqlite3async_control(int op, ...){ async_mutex_enter(ASYNC_MUTEX_QUEUE); if( async.nFile || async.pQueueFirst ){ async_mutex_leave(ASYNC_MUTEX_QUEUE); - return SQLITE_MISUSE; + rc = SQLITE_MISUSE; + break; } async.bLockFiles = bLock; async_mutex_leave(ASYNC_MUTEX_QUEUE); @@ -1692,9 +1696,11 @@ int sqlite3async_control(int op, ...){ } default: - return SQLITE_ERROR; + rc = SQLITE_ERROR; + break; } - return SQLITE_OK; + va_end(ap); + return rc; } #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO) */ diff --git a/ext/fts1/fts1.c b/ext/fts1/fts1.c index 482cf75..77fa9e2 100644 --- a/ext/fts1/fts1.c +++ b/ext/fts1/fts1.c @@ -205,13 +205,13 @@ static int getVarint32(const char *p, int *pi){ */ /* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ static int safe_isspace(char c){ - return (c&0x80)==0 ? isspace(c) : 0; + return (c&0x80)==0 ? isspace((unsigned char)c) : 0; } static int safe_tolower(char c){ - return (c&0x80)==0 ? tolower(c) : c; + return (c&0x80)==0 ? tolower((unsigned char)c) : c; } static int safe_isalnum(char c){ - return (c&0x80)==0 ? isalnum(c) : 0; + return (c&0x80)==0 ? isalnum((unsigned char)c) : 0; } typedef enum DocListType { diff --git a/ext/fts1/simple_tokenizer.c b/ext/fts1/simple_tokenizer.c index d00a770..0ddc705 100644 --- a/ext/fts1/simple_tokenizer.c +++ b/ext/fts1/simple_tokenizer.c @@ -138,7 +138,7 @@ static int simpleNext( ** case-insensitivity. */ char ch = c->pCurrent[ii]; - c->zToken[ii] = (unsigned char)ch<0x80 ? tolower(ch) : ch; + c->zToken[ii] = (unsigned char)ch<0x80 ? tolower((unsigned char)ch):ch; } c->zToken[n] = '\0'; *ppToken = c->zToken; diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index e7958d9..748faef 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -1517,6 +1517,19 @@ static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){ #endif } +/* +** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this +** extension is currently being used by a version of SQLite too old to +** support index-info flags. In that case this function is a no-op. +*/ +static void fts3SetUniqueFlag(sqlite3_index_info *pIdxInfo){ +#if SQLITE_VERSION_NUMBER>=3008012 + if( sqlite3_libversion_number()>=3008012 ){ + pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; + } +#endif +} + /* ** Implementation of the xBestIndex method for FTS3 tables. There ** are three possible strategies, in order of preference: @@ -1607,6 +1620,9 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ } } + /* If using a docid=? or rowid=? strategy, set the UNIQUE flag. */ + if( pInfo->idxNum==FTS3_DOCID_SEARCH ) fts3SetUniqueFlag(pInfo); + iIdx = 1; if( iCons>=0 ){ pInfo->aConstraintUsage[iCons].argvIndex = iIdx++; @@ -1675,7 +1691,7 @@ static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){ sqlite3Fts3ExprFree(pCsr->pExpr); sqlite3Fts3FreeDeferredTokens(pCsr); sqlite3_free(pCsr->aDoclist); - sqlite3_free(pCsr->aMatchinfo); + sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 ); sqlite3_free(pCsr); return SQLITE_OK; @@ -3176,7 +3192,7 @@ static int fts3FilterMethod( /* In case the cursor has been used before, clear it now. */ sqlite3_finalize(pCsr->pStmt); sqlite3_free(pCsr->aDoclist); - sqlite3_free(pCsr->aMatchinfo); + sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); sqlite3Fts3ExprFree(pCsr->pExpr); memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor)); @@ -4231,7 +4247,6 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){ int bIncrOk = (bOptOk && pCsr->bDesc==pTab->bDescIdx && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 - && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0 #ifdef SQLITE_TEST && pTab->bNoIncrDoclist==0 #endif @@ -4351,6 +4366,7 @@ void sqlite3Fts3DoclistNext( p += sqlite3Fts3GetVarint(p, piDocid); }else{ fts3PoslistCopy(0, &p); + while( p<&aDoclist[nDoclist] && *p==0 ) p++; if( p>=&aDoclist[nDoclist] ){ *pbEof = 1; }else{ @@ -5074,7 +5090,7 @@ static int fts3EvalNearTrim( ** 2. NEAR is treated as AND. If the expression is "x NEAR y", it is ** advanced to point to the next row that matches "x AND y". ** -** See fts3EvalTestDeferredAndNear() for details on testing if a row is +** See sqlite3Fts3EvalTestDeferred() for details on testing if a row is ** really a match, taking into account deferred tokens and NEAR operators. */ static void fts3EvalNextRow( @@ -5294,7 +5310,7 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){ } /* -** This function is a helper function for fts3EvalTestDeferredAndNear(). +** This function is a helper function for sqlite3Fts3EvalTestDeferred(). ** Assuming no error occurs or has occurred, It returns non-zero if the ** expression passed as the second argument matches the row that pCsr ** currently points to, or zero if it does not. @@ -5415,7 +5431,7 @@ static int fts3EvalTestExpr( ** Or, if no error occurs and it seems the current row does match the FTS ** query, return 0. */ -static int fts3EvalTestDeferredAndNear(Fts3Cursor *pCsr, int *pRc){ +int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc){ int rc = *pRc; int bMiss = 0; if( rc==SQLITE_OK ){ @@ -5462,7 +5478,7 @@ static int fts3EvalNext(Fts3Cursor *pCsr){ pCsr->isRequireSeek = 1; pCsr->isMatchinfoNeeded = 1; pCsr->iPrevId = pExpr->iDocid; - }while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) ); + }while( pCsr->isEof==0 && sqlite3Fts3EvalTestDeferred(pCsr, &rc) ); } /* Check if the cursor is past the end of the docid range specified @@ -5623,7 +5639,7 @@ static int fts3EvalGatherStats( pCsr->iPrevId = pRoot->iDocid; }while( pCsr->isEof==0 && pRoot->eType==FTSQUERY_NEAR - && fts3EvalTestDeferredAndNear(pCsr, &rc) + && sqlite3Fts3EvalTestDeferred(pCsr, &rc) ); if( rc==SQLITE_OK && pCsr->isEof==0 ){ @@ -5648,7 +5664,6 @@ static int fts3EvalGatherStats( fts3EvalNextRow(pCsr, pRoot, &rc); assert( pRoot->bEof==0 ); }while( pRoot->iDocid!=iDocid && rc==SQLITE_OK ); - fts3EvalTestDeferredAndNear(pCsr, &rc); } } return rc; @@ -5758,10 +5773,10 @@ int sqlite3Fts3EvalPhrasePoslist( int rc = SQLITE_OK; int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ int bOr = 0; - u8 bEof = 0; u8 bTreeEof = 0; Fts3Expr *p; /* Used to iterate from pExpr to root */ Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */ + int bMatch; /* Check if this phrase descends from an OR expression node. If not, ** return NULL. Otherwise, the entry that corresponds to docid @@ -5795,31 +5810,47 @@ int sqlite3Fts3EvalPhrasePoslist( } if( rc!=SQLITE_OK ) return rc; - pIter = pPhrase->pOrPoslist; - iDocid = pPhrase->iOrDocid; - if( pCsr->bDesc==bDescDoclist ){ - bEof = !pPhrase->doclist.nAll || - (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll)); - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ - sqlite3Fts3DoclistNext( - bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, - &pIter, &iDocid, &bEof - ); - } - }else{ - bEof = !pPhrase->doclist.nAll || (pIter && pIter<=pPhrase->doclist.aAll); - while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ - int dummy; - sqlite3Fts3DoclistPrev( - bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, - &pIter, &iDocid, &dummy, &bEof - ); - } - } - pPhrase->pOrPoslist = pIter; - pPhrase->iOrDocid = iDocid; + bMatch = 1; + for(p=pNear; p; p=p->pLeft){ + u8 bEof = 0; + Fts3Expr *pTest = p; + Fts3Phrase *pPh; + assert( pTest->eType==FTSQUERY_NEAR || pTest->eType==FTSQUERY_PHRASE ); + if( pTest->eType==FTSQUERY_NEAR ) pTest = pTest->pRight; + assert( pTest->eType==FTSQUERY_PHRASE ); + pPh = pTest->pPhrase; - if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0; + pIter = pPh->pOrPoslist; + iDocid = pPh->iOrDocid; + if( pCsr->bDesc==bDescDoclist ){ + bEof = !pPh->doclist.nAll || + (pIter >= (pPh->doclist.aAll + pPh->doclist.nAll)); + while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ + sqlite3Fts3DoclistNext( + bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, + &pIter, &iDocid, &bEof + ); + } + }else{ + bEof = !pPh->doclist.nAll || (pIter && pIter<=pPh->doclist.aAll); + while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ + int dummy; + sqlite3Fts3DoclistPrev( + bDescDoclist, pPh->doclist.aAll, pPh->doclist.nAll, + &pIter, &iDocid, &dummy, &bEof + ); + } + } + pPh->pOrPoslist = pIter; + pPh->iOrDocid = iDocid; + if( bEof || iDocid!=pCsr->iPrevId ) bMatch = 0; + } + + if( bMatch ){ + pIter = pPhrase->pOrPoslist; + }else{ + pIter = 0; + } } if( pIter==0 ) return SQLITE_OK; diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h index 0748d91..0c86c42 100644 --- a/ext/fts3/fts3Int.h +++ b/ext/fts3/fts3Int.h @@ -18,6 +18,12 @@ # define NDEBUG 1 #endif +/* FTS3/FTS4 require virtual tables */ +#ifdef SQLITE_OMIT_VIRTUALTABLE +# undef SQLITE_ENABLE_FTS3 +# undef SQLITE_ENABLE_FTS4 +#endif + /* ** FTS4 is really an extension for FTS3. It is enabled using the ** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also all @@ -197,6 +203,8 @@ typedef struct Fts3DeferredToken Fts3DeferredToken; typedef struct Fts3SegReader Fts3SegReader; typedef struct Fts3MultiSegReader Fts3MultiSegReader; +typedef struct MatchinfoBuffer MatchinfoBuffer; + /* ** A connection to a fulltext index is an instance of the following ** structure. The xCreate and xConnect methods create an instance @@ -262,6 +270,7 @@ struct Fts3Table { int nPendingData; /* Current bytes of pending data */ sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ int iPrevLangid; /* Langid of recently inserted document */ + int bPrevDelete; /* True if last operation was a delete */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) /* State variables used for validating that the transaction control @@ -306,9 +315,7 @@ struct Fts3Cursor { i64 iMinDocid; /* Minimum docid to return */ i64 iMaxDocid; /* Maximum docid to return */ int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */ - u32 *aMatchinfo; /* Information about most recent match */ - int nMatchinfo; /* Number of elements in aMatchinfo[] */ - char *zMatchinfo; /* Matchinfo specification */ + MatchinfoBuffer *pMIBuffer; /* Buffer for matchinfo data */ }; #define FTS3_EVAL_FILTER 0 @@ -428,7 +435,9 @@ struct Fts3Expr { u8 bStart; /* True if iDocid is valid */ u8 bDeferred; /* True if this expression is entirely deferred */ - u32 *aMI; + /* The following are used by the fts3_snippet.c module. */ + int iPhrase; /* Index of this phrase in matchinfo() results */ + u32 *aMI; /* See above */ }; /* @@ -549,6 +558,7 @@ void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*); int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *); int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *); void sqlite3Fts3CreateStatTable(int*, Fts3Table*); +int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc); /* fts3_tokenizer.c */ const char *sqlite3Fts3NextToken(const char *, int *); @@ -564,6 +574,7 @@ void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const char *, const char *, const char *, int, int ); void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); +void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p); /* fts3_expr.c */ int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, diff --git a/ext/fts3/fts3_expr.c b/ext/fts3/fts3_expr.c index d7cabd9..788e502 100644 --- a/ext/fts3/fts3_expr.c +++ b/ext/fts3/fts3_expr.c @@ -793,125 +793,151 @@ static int fts3ExprBalance(Fts3Expr **pp, int nMaxDepth){ rc = SQLITE_ERROR; } - if( rc==SQLITE_OK && (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){ - Fts3Expr **apLeaf; - apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth); - if( 0==apLeaf ){ - rc = SQLITE_NOMEM; - }else{ - memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth); - } - - if( rc==SQLITE_OK ){ - int i; - Fts3Expr *p; - - /* Set $p to point to the left-most leaf in the tree of eType nodes. */ - for(p=pRoot; p->eType==eType; p=p->pLeft){ - assert( p->pParent==0 || p->pParent->pLeft==p ); - assert( p->pLeft && p->pRight ); - } - - /* This loop runs once for each leaf in the tree of eType nodes. */ - while( 1 ){ - int iLvl; - Fts3Expr *pParent = p->pParent; /* Current parent of p */ - - assert( pParent==0 || pParent->pLeft==p ); - p->pParent = 0; - if( pParent ){ - pParent->pLeft = 0; - }else{ - pRoot = 0; - } - rc = fts3ExprBalance(&p, nMaxDepth-1); - if( rc!=SQLITE_OK ) break; - - for(iLvl=0; p && iLvlpLeft = apLeaf[iLvl]; - pFree->pRight = p; - pFree->pLeft->pParent = pFree; - pFree->pRight->pParent = pFree; - - p = pFree; - pFree = pFree->pParent; - p->pParent = 0; - apLeaf[iLvl] = 0; - } - } - if( p ){ - sqlite3Fts3ExprFree(p); - rc = SQLITE_TOOBIG; - break; - } - - /* If that was the last leaf node, break out of the loop */ - if( pParent==0 ) break; - - /* Set $p to point to the next leaf in the tree of eType nodes */ - for(p=pParent->pRight; p->eType==eType; p=p->pLeft); - - /* Remove pParent from the original tree. */ - assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent ); - pParent->pRight->pParent = pParent->pParent; - if( pParent->pParent ){ - pParent->pParent->pLeft = pParent->pRight; - }else{ - assert( pParent==pRoot ); - pRoot = pParent->pRight; - } - - /* Link pParent into the free node list. It will be used as an - ** internal node of the new tree. */ - pParent->pParent = pFree; - pFree = pParent; + if( rc==SQLITE_OK ){ + if( (eType==FTSQUERY_AND || eType==FTSQUERY_OR) ){ + Fts3Expr **apLeaf; + apLeaf = (Fts3Expr **)sqlite3_malloc(sizeof(Fts3Expr *) * nMaxDepth); + if( 0==apLeaf ){ + rc = SQLITE_NOMEM; + }else{ + memset(apLeaf, 0, sizeof(Fts3Expr *) * nMaxDepth); } if( rc==SQLITE_OK ){ - p = 0; - for(i=0; ipParent = 0; + int i; + Fts3Expr *p; + + /* Set $p to point to the left-most leaf in the tree of eType nodes. */ + for(p=pRoot; p->eType==eType; p=p->pLeft){ + assert( p->pParent==0 || p->pParent->pLeft==p ); + assert( p->pLeft && p->pRight ); + } + + /* This loop runs once for each leaf in the tree of eType nodes. */ + while( 1 ){ + int iLvl; + Fts3Expr *pParent = p->pParent; /* Current parent of p */ + + assert( pParent==0 || pParent->pLeft==p ); + p->pParent = 0; + if( pParent ){ + pParent->pLeft = 0; + }else{ + pRoot = 0; + } + rc = fts3ExprBalance(&p, nMaxDepth-1); + if( rc!=SQLITE_OK ) break; + + for(iLvl=0; p && iLvlpLeft = apLeaf[iLvl]; pFree->pRight = p; - pFree->pLeft = apLeaf[i]; pFree->pLeft->pParent = pFree; pFree->pRight->pParent = pFree; p = pFree; pFree = pFree->pParent; p->pParent = 0; + apLeaf[iLvl] = 0; } } + if( p ){ + sqlite3Fts3ExprFree(p); + rc = SQLITE_TOOBIG; + break; + } + + /* If that was the last leaf node, break out of the loop */ + if( pParent==0 ) break; + + /* Set $p to point to the next leaf in the tree of eType nodes */ + for(p=pParent->pRight; p->eType==eType; p=p->pLeft); + + /* Remove pParent from the original tree. */ + assert( pParent->pParent==0 || pParent->pParent->pLeft==pParent ); + pParent->pRight->pParent = pParent->pParent; + if( pParent->pParent ){ + pParent->pParent->pLeft = pParent->pRight; + }else{ + assert( pParent==pRoot ); + pRoot = pParent->pRight; + } + + /* Link pParent into the free node list. It will be used as an + ** internal node of the new tree. */ + pParent->pParent = pFree; + pFree = pParent; } - pRoot = p; - }else{ - /* An error occurred. Delete the contents of the apLeaf[] array - ** and pFree list. Everything else is cleaned up by the call to - ** sqlite3Fts3ExprFree(pRoot) below. */ - Fts3Expr *pDel; - for(i=0; ipParent; - sqlite3_free(pDel); + + if( rc==SQLITE_OK ){ + p = 0; + for(i=0; ipParent = 0; + }else{ + assert( pFree!=0 ); + pFree->pRight = p; + pFree->pLeft = apLeaf[i]; + pFree->pLeft->pParent = pFree; + pFree->pRight->pParent = pFree; + + p = pFree; + pFree = pFree->pParent; + p->pParent = 0; + } + } + } + pRoot = p; + }else{ + /* An error occurred. Delete the contents of the apLeaf[] array + ** and pFree list. Everything else is cleaned up by the call to + ** sqlite3Fts3ExprFree(pRoot) below. */ + Fts3Expr *pDel; + for(i=0; ipParent; + sqlite3_free(pDel); + } } + + assert( pFree==0 ); + sqlite3_free( apLeaf ); + } + }else if( eType==FTSQUERY_NOT ){ + Fts3Expr *pLeft = pRoot->pLeft; + Fts3Expr *pRight = pRoot->pRight; + + pRoot->pLeft = 0; + pRoot->pRight = 0; + pLeft->pParent = 0; + pRight->pParent = 0; + + rc = fts3ExprBalance(&pLeft, nMaxDepth-1); + if( rc==SQLITE_OK ){ + rc = fts3ExprBalance(&pRight, nMaxDepth-1); } - assert( pFree==0 ); - sqlite3_free( apLeaf ); + if( rc!=SQLITE_OK ){ + sqlite3Fts3ExprFree(pRight); + sqlite3Fts3ExprFree(pLeft); + }else{ + assert( pLeft && pRight ); + pRoot->pLeft = pLeft; + pLeft->pParent = pRoot; + pRoot->pRight = pRight; + pRight->pParent = pRoot; + } } } - + if( rc!=SQLITE_OK ){ sqlite3Fts3ExprFree(pRoot); pRoot = 0; diff --git a/ext/fts3/fts3_icu.c b/ext/fts3/fts3_icu.c index 52df8c7..6f90e1e 100644 --- a/ext/fts3/fts3_icu.c +++ b/ext/fts3/fts3_icu.c @@ -240,12 +240,13 @@ static int icuNext( ** The set of routines that implement the simple tokenizer */ static const sqlite3_tokenizer_module icuTokenizerModule = { - 0, /* iVersion */ - icuCreate, /* xCreate */ - icuDestroy, /* xCreate */ - icuOpen, /* xOpen */ - icuClose, /* xClose */ - icuNext, /* xNext */ + 0, /* iVersion */ + icuCreate, /* xCreate */ + icuDestroy, /* xCreate */ + icuOpen, /* xOpen */ + icuClose, /* xClose */ + icuNext, /* xNext */ + 0, /* xLanguageid */ }; /* diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c index 6abb169..a0771c0 100644 --- a/ext/fts3/fts3_snippet.c +++ b/ext/fts3/fts3_snippet.c @@ -28,6 +28,7 @@ #define FTS3_MATCHINFO_LCS 's' /* nCol values */ #define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */ #define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */ +#define FTS3_MATCHINFO_LHITS_BM 'b' /* nCol*nPhrase values */ /* ** The default value for the second argument to matchinfo(). @@ -89,9 +90,22 @@ struct MatchInfo { int nCol; /* Number of columns in table */ int nPhrase; /* Number of matchable phrases in query */ sqlite3_int64 nDoc; /* Number of docs in database */ + char flag; u32 *aMatchinfo; /* Pre-allocated buffer */ }; +/* +** An instance of this structure is used to manage a pair of buffers, each +** (nElem * sizeof(u32)) bytes in size. See the MatchinfoBuffer code below +** for details. +*/ +struct MatchinfoBuffer { + u8 aRef[3]; + int nElem; + int bGlobal; /* Set if global data is loaded */ + char *zMatchinfo; + u32 aMatchinfo[1]; +}; /* @@ -107,6 +121,97 @@ struct StrBuffer { }; +/************************************************************************* +** Start of MatchinfoBuffer code. +*/ + +/* +** Allocate a two-slot MatchinfoBuffer object. +*/ +static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){ + MatchinfoBuffer *pRet; + int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer); + int nStr = (int)strlen(zMatchinfo); + + pRet = sqlite3_malloc(nByte + nStr+1); + if( pRet ){ + memset(pRet, 0, nByte); + pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet; + pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1); + pRet->nElem = nElem; + pRet->zMatchinfo = ((char*)pRet) + nByte; + memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1); + pRet->aRef[0] = 1; + } + + return pRet; +} + +static void fts3MIBufferFree(void *p){ + MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]); + + assert( (u32*)p==&pBuf->aMatchinfo[1] + || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2] + ); + if( (u32*)p==&pBuf->aMatchinfo[1] ){ + pBuf->aRef[1] = 0; + }else{ + pBuf->aRef[2] = 0; + } + + if( pBuf->aRef[0]==0 && pBuf->aRef[1]==0 && pBuf->aRef[2]==0 ){ + sqlite3_free(pBuf); + } +} + +static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){ + void (*xRet)(void*) = 0; + u32 *aOut = 0; + + if( p->aRef[1]==0 ){ + p->aRef[1] = 1; + aOut = &p->aMatchinfo[1]; + xRet = fts3MIBufferFree; + } + else if( p->aRef[2]==0 ){ + p->aRef[2] = 1; + aOut = &p->aMatchinfo[p->nElem+2]; + xRet = fts3MIBufferFree; + }else{ + aOut = (u32*)sqlite3_malloc(p->nElem * sizeof(u32)); + if( aOut ){ + xRet = sqlite3_free; + if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32)); + } + } + + *paOut = aOut; + return xRet; +} + +static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){ + p->bGlobal = 1; + memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32)); +} + +/* +** Free a MatchinfoBuffer object allocated using fts3MIBufferNew() +*/ +void sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){ + if( p ){ + assert( p->aRef[0]==1 ); + p->aRef[0] = 0; + if( p->aRef[0]==0 && p->aRef[1]==0 && p->aRef[2]==0 ){ + sqlite3_free(p); + } + } +} + +/* +** End of MatchinfoBuffer code. +*************************************************************************/ + + /* ** This function is used to help iterate through a position-list. A position ** list is a list of unique integers, sorted from smallest to largest. Each @@ -143,7 +248,7 @@ static int fts3ExprIterate2( void *pCtx /* Second argument to pass to callback */ ){ int rc; /* Return code */ - int eType = pExpr->eType; /* Type of expression node pExpr */ + int eType = pExpr->eType; /* Type of expression node pExpr */ if( eType!=FTSQUERY_PHRASE ){ assert( pExpr->pLeft && pExpr->pRight ); @@ -177,6 +282,7 @@ static int fts3ExprIterate( return fts3ExprIterate2(pExpr, &iPhrase, x, pCtx); } + /* ** This is an fts3ExprIterate() callback used while loading the doclists ** for each phrase into Fts3Expr.aDoclist[]/nDoclist. See also @@ -221,8 +327,7 @@ static int fts3ExprLoadDoclists( static int fts3ExprPhraseCountCb(Fts3Expr *pExpr, int iPhrase, void *ctx){ (*(int *)ctx)++; - UNUSED_PARAMETER(pExpr); - UNUSED_PARAMETER(iPhrase); + pExpr->iPhrase = iPhrase; return SQLITE_OK; } static int fts3ExprPhraseCount(Fts3Expr *pExpr){ @@ -443,7 +548,7 @@ static int fts3BestSnippet( sIter.nSnippet = nSnippet; sIter.nPhrase = nList; sIter.iCurrent = -1; - rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void *)&sIter); + rc = fts3ExprIterate(pCsr->pExpr, fts3SnippetFindPositions, (void*)&sIter); if( rc==SQLITE_OK ){ /* Set the *pmSeen output variable. */ @@ -744,6 +849,60 @@ static int fts3ColumnlistCount(char **ppCollist){ return nEntry; } +/* +** This function gathers 'y' or 'b' data for a single phrase. +*/ +static void fts3ExprLHits( + Fts3Expr *pExpr, /* Phrase expression node */ + MatchInfo *p /* Matchinfo context */ +){ + Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab; + int iStart; + Fts3Phrase *pPhrase = pExpr->pPhrase; + char *pIter = pPhrase->doclist.pList; + int iCol = 0; + + assert( p->flag==FTS3_MATCHINFO_LHITS_BM || p->flag==FTS3_MATCHINFO_LHITS ); + if( p->flag==FTS3_MATCHINFO_LHITS ){ + iStart = pExpr->iPhrase * p->nCol; + }else{ + iStart = pExpr->iPhrase * ((p->nCol + 31) / 32); + } + + while( 1 ){ + int nHit = fts3ColumnlistCount(&pIter); + if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){ + if( p->flag==FTS3_MATCHINFO_LHITS ){ + p->aMatchinfo[iStart + iCol] = (u32)nHit; + }else if( nHit ){ + p->aMatchinfo[iStart + (iCol+1)/32] |= (1 << (iCol&0x1F)); + } + } + assert( *pIter==0x00 || *pIter==0x01 ); + if( *pIter!=0x01 ) break; + pIter++; + pIter += fts3GetVarint32(pIter, &iCol); + } +} + +/* +** Gather the results for matchinfo directives 'y' and 'b'. +*/ +static void fts3ExprLHitGather( + Fts3Expr *pExpr, + MatchInfo *p +){ + assert( (pExpr->pLeft==0)==(pExpr->pRight==0) ); + if( pExpr->bEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){ + if( pExpr->pLeft ){ + fts3ExprLHitGather(pExpr->pLeft, p); + fts3ExprLHitGather(pExpr->pRight, p); + }else{ + fts3ExprLHits(pExpr, p); + } + } +} + /* ** fts3ExprIterate() callback used to collect the "global" matchinfo stats ** for a single query. @@ -810,51 +969,6 @@ static int fts3ExprLocalHitsCb( return rc; } -/* -** fts3ExprIterate() callback used to gather information for the matchinfo -** directive 'y'. -*/ -static int fts3ExprLHitsCb( - Fts3Expr *pExpr, /* Phrase expression node */ - int iPhrase, /* Phrase number */ - void *pCtx /* Pointer to MatchInfo structure */ -){ - MatchInfo *p = (MatchInfo *)pCtx; - Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab; - int rc = SQLITE_OK; - int iStart = iPhrase * p->nCol; - Fts3Expr *pEof; /* Ancestor node already at EOF */ - - /* This must be a phrase */ - assert( pExpr->pPhrase ); - - /* Initialize all output integers to zero. */ - memset(&p->aMatchinfo[iStart], 0, sizeof(u32) * p->nCol); - - /* Check if this or any parent node is at EOF. If so, then all output - ** values are zero. */ - for(pEof=pExpr; pEof && pEof->bEof==0; pEof=pEof->pParent); - - if( pEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){ - Fts3Phrase *pPhrase = pExpr->pPhrase; - char *pIter = pPhrase->doclist.pList; - int iCol = 0; - - while( 1 ){ - int nHit = fts3ColumnlistCount(&pIter); - if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){ - p->aMatchinfo[iStart + iCol] = (u32)nHit; - } - assert( *pIter==0x00 || *pIter==0x01 ); - if( *pIter!=0x01 ) break; - pIter++; - pIter += fts3GetVarint32(pIter, &iCol); - } - } - - return rc; -} - static int fts3MatchinfoCheck( Fts3Table *pTab, char cArg, @@ -868,6 +982,7 @@ static int fts3MatchinfoCheck( || (cArg==FTS3_MATCHINFO_LCS) || (cArg==FTS3_MATCHINFO_HITS) || (cArg==FTS3_MATCHINFO_LHITS) + || (cArg==FTS3_MATCHINFO_LHITS_BM) ){ return SQLITE_OK; } @@ -895,6 +1010,10 @@ static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ nVal = pInfo->nCol * pInfo->nPhrase; break; + case FTS3_MATCHINFO_LHITS_BM: + nVal = pInfo->nPhrase * ((pInfo->nCol + 31) / 32); + break; + default: assert( cArg==FTS3_MATCHINFO_HITS ); nVal = pInfo->nCol * pInfo->nPhrase * 3; @@ -1089,7 +1208,7 @@ static int fts3MatchinfoValues( sqlite3_stmt *pSelect = 0; for(i=0; rc==SQLITE_OK && zArg[i]; i++){ - + pInfo->flag = zArg[i]; switch( zArg[i] ){ case FTS3_MATCHINFO_NPHRASE: if( bGlobal ) pInfo->aMatchinfo[0] = pInfo->nPhrase; @@ -1149,9 +1268,13 @@ static int fts3MatchinfoValues( } break; - case FTS3_MATCHINFO_LHITS: - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLHitsCb, (void*)pInfo); + case FTS3_MATCHINFO_LHITS_BM: + case FTS3_MATCHINFO_LHITS: { + int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32); + memset(pInfo->aMatchinfo, 0, nZero); + fts3ExprLHitGather(pCsr->pExpr, pInfo); break; + } default: { Fts3Expr *pExpr; @@ -1165,6 +1288,7 @@ static int fts3MatchinfoValues( if( rc!=SQLITE_OK ) break; } rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo); + sqlite3Fts3EvalTestDeferred(pCsr, &rc); if( rc!=SQLITE_OK ) break; } (void)fts3ExprIterate(pExpr, fts3ExprLocalHitsCb,(void*)pInfo); @@ -1184,7 +1308,8 @@ static int fts3MatchinfoValues( ** Populate pCsr->aMatchinfo[] with data for the current row. The ** 'matchinfo' data is an array of 32-bit unsigned integers (C type u32). */ -static int fts3GetMatchinfo( +static void fts3GetMatchinfo( + sqlite3_context *pCtx, /* Return results here */ Fts3Cursor *pCsr, /* FTS3 Cursor object */ const char *zArg /* Second argument to matchinfo() function */ ){ @@ -1193,6 +1318,9 @@ static int fts3GetMatchinfo( int rc = SQLITE_OK; int bGlobal = 0; /* Collect 'global' stats as well as local */ + u32 *aOut = 0; + void (*xDestroyOut)(void*) = 0; + memset(&sInfo, 0, sizeof(MatchInfo)); sInfo.pCursor = pCsr; sInfo.nCol = pTab->nColumn; @@ -1200,21 +1328,18 @@ static int fts3GetMatchinfo( /* If there is cached matchinfo() data, but the format string for the ** cache does not match the format string for this request, discard ** the cached data. */ - if( pCsr->zMatchinfo && strcmp(pCsr->zMatchinfo, zArg) ){ - assert( pCsr->aMatchinfo ); - sqlite3_free(pCsr->aMatchinfo); - pCsr->zMatchinfo = 0; - pCsr->aMatchinfo = 0; + if( pCsr->pMIBuffer && strcmp(pCsr->pMIBuffer->zMatchinfo, zArg) ){ + sqlite3Fts3MIBufferFree(pCsr->pMIBuffer); + pCsr->pMIBuffer = 0; } - /* If Fts3Cursor.aMatchinfo[] is NULL, then this is the first time the + /* If Fts3Cursor.pMIBuffer is NULL, then this is the first time the ** matchinfo function has been called for this query. In this case ** allocate the array used to accumulate the matchinfo data and ** initialize those elements that are constant for every row. */ - if( pCsr->aMatchinfo==0 ){ + if( pCsr->pMIBuffer==0 ){ int nMatchinfo = 0; /* Number of u32 elements in match-info */ - int nArg; /* Bytes in zArg */ int i; /* Used to iterate through zArg */ /* Determine the number of phrases in the query */ @@ -1223,30 +1348,46 @@ static int fts3GetMatchinfo( /* Determine the number of integers in the buffer returned by this call. */ for(i=0; zArg[i]; i++){ + char *zErr = 0; + if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ + sqlite3_result_error(pCtx, zErr, -1); + sqlite3_free(zErr); + return; + } nMatchinfo += fts3MatchinfoSize(&sInfo, zArg[i]); } /* Allocate space for Fts3Cursor.aMatchinfo[] and Fts3Cursor.zMatchinfo. */ - nArg = (int)strlen(zArg); - pCsr->aMatchinfo = (u32 *)sqlite3_malloc(sizeof(u32)*nMatchinfo + nArg + 1); - if( !pCsr->aMatchinfo ) return SQLITE_NOMEM; + pCsr->pMIBuffer = fts3MIBufferNew(nMatchinfo, zArg); + if( !pCsr->pMIBuffer ) rc = SQLITE_NOMEM; - pCsr->zMatchinfo = (char *)&pCsr->aMatchinfo[nMatchinfo]; - pCsr->nMatchinfo = nMatchinfo; - memcpy(pCsr->zMatchinfo, zArg, nArg+1); - memset(pCsr->aMatchinfo, 0, sizeof(u32)*nMatchinfo); pCsr->isMatchinfoNeeded = 1; bGlobal = 1; } - sInfo.aMatchinfo = pCsr->aMatchinfo; - sInfo.nPhrase = pCsr->nPhrase; - if( pCsr->isMatchinfoNeeded ){ - rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); - pCsr->isMatchinfoNeeded = 0; + if( rc==SQLITE_OK ){ + xDestroyOut = fts3MIBufferAlloc(pCsr->pMIBuffer, &aOut); + if( xDestroyOut==0 ){ + rc = SQLITE_NOMEM; + } } - return rc; + if( rc==SQLITE_OK ){ + sInfo.aMatchinfo = aOut; + sInfo.nPhrase = pCsr->nPhrase; + rc = fts3MatchinfoValues(pCsr, bGlobal, &sInfo, zArg); + if( bGlobal ){ + fts3MIBufferSetGlobal(pCsr->pMIBuffer); + } + } + + if( rc!=SQLITE_OK ){ + sqlite3_result_error_code(pCtx, rc); + if( xDestroyOut ) xDestroyOut(aOut); + }else{ + int n = pCsr->pMIBuffer->nElem * sizeof(u32); + sqlite3_result_blob(pCtx, aOut, n, xDestroyOut); + } } /* @@ -1452,7 +1593,7 @@ void sqlite3Fts3Offsets( */ sCtx.iCol = iCol; sCtx.iTerm = 0; - (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void *)&sCtx); + (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx); /* Retreive the text stored in column iCol. If an SQL NULL is stored ** in column iCol, jump immediately to the next iteration of the loop. @@ -1544,19 +1685,9 @@ void sqlite3Fts3Matchinfo( const char *zArg /* Second arg to matchinfo() function */ ){ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - int rc; - int i; const char *zFormat; if( zArg ){ - for(i=0; zArg[i]; i++){ - char *zErr = 0; - if( fts3MatchinfoCheck(pTab, zArg[i], &zErr) ){ - sqlite3_result_error(pContext, zErr, -1); - sqlite3_free(zErr); - return; - } - } zFormat = zArg; }else{ zFormat = FTS3_MATCHINFO_DEFAULT; @@ -1565,17 +1696,10 @@ void sqlite3Fts3Matchinfo( if( !pCsr->pExpr ){ sqlite3_result_blob(pContext, "", 0, SQLITE_STATIC); return; - } - - /* Retrieve matchinfo() data. */ - rc = fts3GetMatchinfo(pCsr, zFormat); - sqlite3Fts3SegmentsClose(pTab); - - if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(pContext, rc); }else{ - int n = pCsr->nMatchinfo * sizeof(u32); - sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT); + /* Retrieve matchinfo() data. */ + fts3GetMatchinfo(pContext, pCsr, zFormat); + sqlite3Fts3SegmentsClose(pTab); } } diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c index 64cfe07..fcabe5c 100644 --- a/ext/fts3/fts3_tokenizer.c +++ b/ext/fts3/fts3_tokenizer.c @@ -67,6 +67,7 @@ static void scalarFunc( nName = sqlite3_value_bytes(argv[0])+1; if( argc==2 ){ +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER void *pOld; int n = sqlite3_value_bytes(argv[1]); if( zName==0 || n!=sizeof(pPtr) ){ @@ -79,7 +80,14 @@ static void scalarFunc( sqlite3_result_error(context, "out of memory", -1); return; } - }else{ +#else + sqlite3_result_error(context, "fts3tokenize: " + "disabled - rebuild with -DSQLITE_ENABLE_FTS3_TOKENIZER", -1 + ); + return; +#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ + }else + { if( zName ){ pPtr = sqlite3Fts3HashFind(pHash, zName, nName); } @@ -328,6 +336,7 @@ finish: Tcl_DecrRefCount(pRet); } +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER static int registerTokenizer( sqlite3 *db, @@ -349,6 +358,8 @@ int registerTokenizer( return sqlite3_finalize(pStmt); } +#endif /* SQLITE_ENABLE_FTS3_TOKENIZER */ + static int queryTokenizer( @@ -420,11 +431,13 @@ static void intTestFunc( assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); /* Test the storage function */ +#ifdef SQLITE_ENABLE_FTS3_TOKENIZER rc = registerTokenizer(db, "nosuchtokenizer", p1); assert( rc==SQLITE_OK ); rc = queryTokenizer(db, "nosuchtokenizer", &p2); assert( rc==SQLITE_OK ); assert( p2==p1 ); +#endif sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); } diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c index 4cd2aeb..d5a4082 100644 --- a/ext/fts3/fts3_write.c +++ b/ext/fts3/fts3_write.c @@ -860,10 +860,12 @@ static int fts3PendingTermsAdd( */ static int fts3PendingTermsDocid( Fts3Table *p, /* Full-text table handle */ + int bDelete, /* True if this op is a delete */ int iLangid, /* Language id of row being written */ sqlite_int64 iDocid /* Docid of row being written */ ){ assert( iLangid>=0 ); + assert( bDelete==1 || bDelete==0 ); /* TODO(shess) Explore whether partially flushing the buffer on ** forced-flush would provide better performance. I suspect that if @@ -871,7 +873,8 @@ static int fts3PendingTermsDocid( ** buffer was half empty, that would let the less frequent terms ** generate longer doclists. */ - if( iDocid<=p->iPrevDocid + if( iDocidiPrevDocid + || (iDocid==p->iPrevDocid && p->bPrevDelete==0) || p->iPrevLangid!=iLangid || p->nPendingData>p->nMaxPendingData ){ @@ -880,6 +883,7 @@ static int fts3PendingTermsDocid( } p->iPrevDocid = iDocid; p->iPrevLangid = iLangid; + p->bPrevDelete = bDelete; return SQLITE_OK; } @@ -1069,7 +1073,8 @@ static void fts3DeleteTerms( if( SQLITE_ROW==sqlite3_step(pSelect) ){ int i; int iLangid = langidFromSelect(p, pSelect); - rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); + i64 iDocid = sqlite3_column_int64(pSelect, 0); + rc = fts3PendingTermsDocid(p, 1, iLangid, iDocid); for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ int iCol = i-1; if( p->abNotindexed[iCol]==0 ){ @@ -1317,14 +1322,19 @@ static int fts3SegReaderNext( if( fts3SegReaderIsPending(pReader) ){ Fts3HashElem *pElem = *(pReader->ppNextElem); - if( pElem==0 ){ - pReader->aNode = 0; - }else{ + sqlite3_free(pReader->aNode); + pReader->aNode = 0; + if( pElem ){ + char *aCopy; PendingList *pList = (PendingList *)fts3HashData(pElem); + int nCopy = pList->nData+1; pReader->zTerm = (char *)fts3HashKey(pElem); pReader->nTerm = fts3HashKeysize(pElem); - pReader->nNode = pReader->nDoclist = pList->nData + 1; - pReader->aNode = pReader->aDoclist = pList->aData; + aCopy = (char*)sqlite3_malloc(nCopy); + if( !aCopy ) return SQLITE_NOMEM; + memcpy(aCopy, pList->aData, nCopy); + pReader->nNode = pReader->nDoclist = nCopy; + pReader->aNode = pReader->aDoclist = aCopy; pReader->ppNextElem++; assert( pReader->aNode ); } @@ -1564,12 +1574,14 @@ int sqlite3Fts3MsrOvfl( ** second argument. */ void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ - if( pReader && !fts3SegReaderIsPending(pReader) ){ - sqlite3_free(pReader->zTerm); + if( pReader ){ + if( !fts3SegReaderIsPending(pReader) ){ + sqlite3_free(pReader->zTerm); + } if( !fts3SegReaderIsRootOnly(pReader) ){ sqlite3_free(pReader->aNode); - sqlite3_blob_close(pReader->pBlob); } + sqlite3_blob_close(pReader->pBlob); } sqlite3_free(pReader); } @@ -3512,7 +3524,7 @@ static int fts3DoRebuild(Fts3Table *p){ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ int iCol; int iLangid = langidFromSelect(p, pStmt); - rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); + rc = fts3PendingTermsDocid(p, 0, iLangid, sqlite3_column_int64(pStmt, 0)); memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ if( p->abNotindexed[iCol]==0 ){ @@ -5617,7 +5629,7 @@ int sqlite3Fts3UpdateMethod( } } if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ - rc = fts3PendingTermsDocid(p, iLangid, *pRowid); + rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); } if( rc==SQLITE_OK ){ assert( p->iPrevDocid==*pRowid ); diff --git a/ext/fts3/tool/fts3view.c b/ext/fts3/tool/fts3view.c index 6dada35..a8d7981 100644 --- a/ext/fts3/tool/fts3view.c +++ b/ext/fts3/tool/fts3view.c @@ -398,7 +398,7 @@ static void showSegmentStats(sqlite3 *db, const char *zTab){ if( sqlite3_step(pStmt)==SQLITE_ROW && (nLeaf = sqlite3_column_int(pStmt, 0))>0 ){ - int nIdx = sqlite3_column_int(pStmt, 5); + nIdx = sqlite3_column_int(pStmt, 5); sqlite3_int64 sz; printf("For level %d:\n", i); printf(" Number of indexes...................... %9d\n", nIdx); diff --git a/ext/fts3/unicode/mkunicode.tcl b/ext/fts3/unicode/mkunicode.tcl index c3083ee..aafb4e9 100644 --- a/ext/fts3/unicode/mkunicode.tcl +++ b/ext/fts3/unicode/mkunicode.tcl @@ -1,77 +1,5 @@ -# -# Parameter $zName must be a path to the file UnicodeData.txt. This command -# reads the file and returns a list of mappings required to remove all -# diacritical marks from a unicode string. Each mapping is itself a list -# consisting of two elements - the unicode codepoint and the single ASCII -# character that it should be replaced with, or an empty string if the -# codepoint should simply be removed from the input. Examples: -# -# { 224 a } (replace codepoint 224 to "a") -# { 769 "" } (remove codepoint 769 from input) -# -# Mappings are only returned for non-upper case codepoints. It is assumed -# that the input has already been folded to lower case. -# -proc rd_load_unicodedata_text {zName} { - global tl_lookup_table - - set fd [open $zName] - set lField { - code - character_name - general_category - canonical_combining_classes - bidirectional_category - character_decomposition_mapping - decimal_digit_value - digit_value - numeric_value - mirrored - unicode_1_name - iso10646_comment_field - uppercase_mapping - lowercase_mapping - titlecase_mapping - } - set lRet [list] - - while { ![eof $fd] } { - set line [gets $fd] - if {$line == ""} continue - - set fields [split $line ";"] - if {[llength $fields] != [llength $lField]} { error "parse error: $line" } - foreach $lField $fields {} - if { [llength $character_decomposition_mapping]!=2 - || [string is xdigit [lindex $character_decomposition_mapping 0]]==0 - } { - continue - } - - set iCode [expr "0x$code"] - set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"] - set iDia [expr "0x[lindex $character_decomposition_mapping 1]"] - - if {[info exists tl_lookup_table($iCode)]} continue - - if { ($iAscii >= 97 && $iAscii <= 122) - || ($iAscii >= 65 && $iAscii <= 90) - } { - lappend lRet [list $iCode [string tolower [format %c $iAscii]]] - set dia($iDia) 1 - } - } - - foreach d [array names dia] { - lappend lRet [list $d ""] - } - set lRet [lsort -integer -index 0 $lRet] - - close $fd - set lRet -} - +source [file join [file dirname [info script]] parseunicode.tcl] proc print_rd {map} { global tl_lookup_table @@ -117,7 +45,7 @@ proc print_rd {map} { puts "** E\"). The resuls of passing a codepoint that corresponds to an" puts "** uppercase letter are undefined." puts "*/" - puts "static int remove_diacritic(int c)\{" + puts "static int ${::remove_diacritic}(int c)\{" puts " unsigned short aDia\[\] = \{" puts -nonewline " 0, " set i 1 @@ -204,53 +132,6 @@ proc print_isdiacritic {zFunc map} { #------------------------------------------------------------------------- -# Parameter $zName must be a path to the file UnicodeData.txt. This command -# reads the file and returns a list of codepoints (integers). The list -# contains all codepoints in the UnicodeData.txt assigned to any "General -# Category" that is not a "Letter" or "Number". -# -proc an_load_unicodedata_text {zName} { - set fd [open $zName] - set lField { - code - character_name - general_category - canonical_combining_classes - bidirectional_category - character_decomposition_mapping - decimal_digit_value - digit_value - numeric_value - mirrored - unicode_1_name - iso10646_comment_field - uppercase_mapping - lowercase_mapping - titlecase_mapping - } - set lRet [list] - - while { ![eof $fd] } { - set line [gets $fd] - if {$line == ""} continue - - set fields [split $line ";"] - if {[llength $fields] != [llength $lField]} { error "parse error: $line" } - foreach $lField $fields {} - - set iCode [expr "0x$code"] - set bAlnum [expr { - [lsearch {L N} [string range $general_category 0 0]] >= 0 - || $general_category=="Co" - }] - - if { !$bAlnum } { lappend lRet $iCode } - } - - close $fd - set lRet -} - proc an_load_separator_ranges {} { global unicodedata.txt set lSep [an_load_unicodedata_text ${unicodedata.txt}] @@ -345,9 +226,9 @@ proc print_isalnum {zFunc lRange} { an_print_range_array $lRange an_print_ascii_bitmap $lRange puts { - if( c<128 ){ + if( (unsigned int)c<128 ){ return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); - }else if( c<(1<<22) ){ + }else if( (unsigned int)c<(1<<22) ){ unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; int iRes = 0; int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; @@ -440,29 +321,6 @@ proc print_test_isalnum {zFunc lRange} { #------------------------------------------------------------------------- -proc tl_load_casefolding_txt {zName} { - global tl_lookup_table - - set fd [open $zName] - while { ![eof $fd] } { - set line [gets $fd] - if {[string range $line 0 0] == "#"} continue - if {$line == ""} continue - - foreach x {a b c d} {unset -nocomplain $x} - foreach {a b c d} [split $line ";"] {} - - set a2 [list] - set c2 [list] - foreach elem $a { lappend a2 [expr "0x[string trim $elem]"] } - foreach elem $c { lappend c2 [expr "0x[string trim $elem]"] } - set b [string trim $b] - set d [string trim $d] - - if {$b=="C" || $b=="S"} { set tl_lookup_table($a2) $c2 } - } -} - proc tl_create_records {} { global tl_lookup_table @@ -626,19 +484,20 @@ proc print_fold {zFunc} { tl_print_table_footer toggle tl_print_ioff_table $liOff - puts { + puts [subst -nocommands { int ret = c; - assert( c>=0 ); assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); if( c<128 ){ if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); }else if( c<65536 ){ + const struct TableEntry *p; int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; int iLo = 0; int iRes = -1; + assert( c>aEntry[0].iCode ); while( iHi>=iLo ){ int iTest = (iHi + iLo) / 2; int cmp = (c - aEntry[iTest].iCode); @@ -649,19 +508,17 @@ proc print_fold {zFunc} { iHi = iTest-1; } } - assert( iRes<0 || c>=aEntry[iRes].iCode ); - if( iRes>=0 ){ - const struct TableEntry *p = &aEntry[iRes]; - if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ - ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; - assert( ret>0 ); - } + assert( iRes>=0 && c>=aEntry[iRes].iCode ); + p = &aEntry[iRes]; + if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ + ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; + assert( ret>0 ); } - if( bRemoveDiacritic ) ret = remove_diacritic(ret); - } + if( bRemoveDiacritic ) ret = ${::remove_diacritic}(ret); } + }] foreach entry $lHigh { tl_print_if_entry $entry @@ -732,8 +589,12 @@ proc print_fileheader {} { */ }] puts "" - puts "#ifndef SQLITE_DISABLE_FTS3_UNICODE" - puts "#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)" + if {$::generate_fts5_code} { + # no-op + } else { + puts "#ifndef SQLITE_DISABLE_FTS3_UNICODE" + puts "#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)" + } puts "" puts "#include " puts "" @@ -760,22 +621,40 @@ proc print_test_main {} { # our liking. # proc usage {} { - puts -nonewline stderr "Usage: $::argv0 ?-test? " + puts -nonewline stderr "Usage: $::argv0 ?-test? ?-fts5? " puts stderr " " exit 1 } -if {[llength $argv]!=2 && [llength $argv]!=3} usage -if {[llength $argv]==3 && [lindex $argv 0]!="-test"} usage +if {[llength $argv]<2} usage set unicodedata.txt [lindex $argv end] set casefolding.txt [lindex $argv end-1] -set generate_test_code [expr {[llength $argv]==3}] + +set remove_diacritic remove_diacritic +set generate_test_code 0 +set generate_fts5_code 0 +set function_prefix "sqlite3Fts" +for {set i 0} {$i < [llength $argv]-2} {incr i} { + switch -- [lindex $argv $i] { + -test { + set generate_test_code 1 + } + -fts5 { + set function_prefix sqlite3Fts5 + set generate_fts5_code 1 + set remove_diacritic fts5_remove_diacritic + } + default { + usage + } + } +} print_fileheader # Print the isalnum() function to stdout. # set lRange [an_load_separator_ranges] -print_isalnum sqlite3FtsUnicodeIsalnum $lRange +print_isalnum ${function_prefix}UnicodeIsalnum $lRange # Leave a gap between the two generated C functions. # @@ -790,22 +669,26 @@ set mappings [rd_load_unicodedata_text ${unicodedata.txt}] print_rd $mappings puts "" puts "" -print_isdiacritic sqlite3FtsUnicodeIsdiacritic $mappings +print_isdiacritic ${function_prefix}UnicodeIsdiacritic $mappings puts "" puts "" # Print the fold() function to stdout. # -print_fold sqlite3FtsUnicodeFold +print_fold ${function_prefix}UnicodeFold # Print the test routines and main() function to stdout, if -test # was specified. # if {$::generate_test_code} { - print_test_isalnum sqlite3FtsUnicodeIsalnum $lRange - print_fold_test sqlite3FtsUnicodeFold $mappings + print_test_isalnum ${function_prefix}UnicodeIsalnum $lRange + print_fold_test ${function_prefix}UnicodeFold $mappings print_test_main } -puts "#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */" -puts "#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */" +if {$generate_fts5_code} { + # no-op +} else { + puts "#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */" + puts "#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */" +} diff --git a/ext/fts3/unicode/parseunicode.tcl b/ext/fts3/unicode/parseunicode.tcl new file mode 100644 index 0000000..0cb2c83 --- /dev/null +++ b/ext/fts3/unicode/parseunicode.tcl @@ -0,0 +1,146 @@ + +#-------------------------------------------------------------------------- +# Parameter $zName must be a path to the file UnicodeData.txt. This command +# reads the file and returns a list of mappings required to remove all +# diacritical marks from a unicode string. Each mapping is itself a list +# consisting of two elements - the unicode codepoint and the single ASCII +# character that it should be replaced with, or an empty string if the +# codepoint should simply be removed from the input. Examples: +# +# { 224 a } (replace codepoint 224 to "a") +# { 769 "" } (remove codepoint 769 from input) +# +# Mappings are only returned for non-upper case codepoints. It is assumed +# that the input has already been folded to lower case. +# +proc rd_load_unicodedata_text {zName} { + global tl_lookup_table + + set fd [open $zName] + set lField { + code + character_name + general_category + canonical_combining_classes + bidirectional_category + character_decomposition_mapping + decimal_digit_value + digit_value + numeric_value + mirrored + unicode_1_name + iso10646_comment_field + uppercase_mapping + lowercase_mapping + titlecase_mapping + } + set lRet [list] + + while { ![eof $fd] } { + set line [gets $fd] + if {$line == ""} continue + + set fields [split $line ";"] + if {[llength $fields] != [llength $lField]} { error "parse error: $line" } + foreach $lField $fields {} + if { [llength $character_decomposition_mapping]!=2 + || [string is xdigit [lindex $character_decomposition_mapping 0]]==0 + } { + continue + } + + set iCode [expr "0x$code"] + set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"] + set iDia [expr "0x[lindex $character_decomposition_mapping 1]"] + + if {[info exists tl_lookup_table($iCode)]} continue + + if { ($iAscii >= 97 && $iAscii <= 122) + || ($iAscii >= 65 && $iAscii <= 90) + } { + lappend lRet [list $iCode [string tolower [format %c $iAscii]]] + set dia($iDia) 1 + } + } + + foreach d [array names dia] { + lappend lRet [list $d ""] + } + set lRet [lsort -integer -index 0 $lRet] + + close $fd + set lRet +} + +#------------------------------------------------------------------------- +# Parameter $zName must be a path to the file UnicodeData.txt. This command +# reads the file and returns a list of codepoints (integers). The list +# contains all codepoints in the UnicodeData.txt assigned to any "General +# Category" that is not a "Letter" or "Number". +# +proc an_load_unicodedata_text {zName} { + set fd [open $zName] + set lField { + code + character_name + general_category + canonical_combining_classes + bidirectional_category + character_decomposition_mapping + decimal_digit_value + digit_value + numeric_value + mirrored + unicode_1_name + iso10646_comment_field + uppercase_mapping + lowercase_mapping + titlecase_mapping + } + set lRet [list] + + while { ![eof $fd] } { + set line [gets $fd] + if {$line == ""} continue + + set fields [split $line ";"] + if {[llength $fields] != [llength $lField]} { error "parse error: $line" } + foreach $lField $fields {} + + set iCode [expr "0x$code"] + set bAlnum [expr { + [lsearch {L N} [string range $general_category 0 0]] >= 0 + || $general_category=="Co" + }] + + if { !$bAlnum } { lappend lRet $iCode } + } + + close $fd + set lRet +} + +proc tl_load_casefolding_txt {zName} { + global tl_lookup_table + + set fd [open $zName] + while { ![eof $fd] } { + set line [gets $fd] + if {[string range $line 0 0] == "#"} continue + if {$line == ""} continue + + foreach x {a b c d} {unset -nocomplain $x} + foreach {a b c d} [split $line ";"] {} + + set a2 [list] + set c2 [list] + foreach elem $a { lappend a2 [expr "0x[string trim $elem]"] } + foreach elem $c { lappend c2 [expr "0x[string trim $elem]"] } + set b [string trim $b] + set d [string trim $d] + + if {$b=="C" || $b=="S"} { set tl_lookup_table($a2) $c2 } + } +} + + diff --git a/ext/fts5/extract_api_docs.tcl b/ext/fts5/extract_api_docs.tcl new file mode 100644 index 0000000..2320d70 --- /dev/null +++ b/ext/fts5/extract_api_docs.tcl @@ -0,0 +1,252 @@ +# +# 2014 August 24 +# +# 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 script extracts the documentation for the API used by fts5 auxiliary +# functions from header file fts5.h. It outputs html text on stdout that +# is included in the documentation on the web. +# + +set ::fts5_docs_output "" +if {[info commands hd_putsnl]==""} { + if {[llength $argv]>0} { set ::extract_api_docs_mode [lindex $argv 0] } + proc output {text} { + puts $text + } +} else { + proc output {text} { + append ::fts5_docs_output "$text\n" + } +} +if {[info exists ::extract_api_docs_mode]==0} {set ::extract_api_docs_mode api} + + +set input_file [file join [file dir [info script]] fts5.h] +set fd [open $input_file] +set data [read $fd] +close $fd + + +# Argument $data is the entire text of the fts5.h file. This function +# extracts the definition of the Fts5ExtensionApi structure from it and +# returns a key/value list of structure member names and definitions. i.e. +# +# iVersion {int iVersion} xUserData {void *(*xUserData)(Fts5Context*)} ... +# +proc get_struct_members {data} { + + # Extract the structure definition from the fts5.h file. + regexp "struct Fts5ExtensionApi {(.*?)};" $data -> defn + + # Remove all comments from the structure definition + regsub -all {/[*].*?[*]/} $defn {} defn2 + + set res [list] + foreach member [split $defn2 {;}] { + + set member [string trim $member] + if {$member!=""} { + catch { set name [lindex $member end] } + regexp {.*?[(][*]([^)]*)[)]} $member -> name + lappend res $name $member + } + } + + set res +} + +proc get_struct_docs {data names} { + # Extract the structure definition from the fts5.h file. + regexp {EXTENSION API FUNCTIONS(.*?)[*]/} $data -> docs + + set current_doc "" + set current_header "" + + foreach line [split $docs "\n"] { + regsub {[*]*} $line {} line + if {[regexp {^ } $line]} { + append current_doc "$line\n" + } elseif {[string trim $line]==""} { + if {$current_header!=""} { append current_doc "\n" } + } else { + if {$current_doc != ""} { + lappend res $current_header $current_doc + set current_doc "" + } + set subject n/a + regexp {^ *([[:alpha:]]*)} $line -> subject + if {[lsearch $names $subject]>=0} { + set current_header $subject + } else { + set current_header [string trim $line] + } + } + } + + if {$current_doc != ""} { + lappend res $current_header $current_doc + } + + set res +} + +proc get_tokenizer_docs {data} { + regexp {(xCreate:.*?)[*]/} $data -> docs + + set res "
\n" + foreach line [split [string trim $docs] "\n"] { + regexp {[*][*](.*)} $line -> line + if {[regexp {^ ?x.*:} $line]} { + append res "
$line

\n" + continue + } + if {[regexp {SYNONYM SUPPORT} $line]} { + set line "

Synonym Support

" + } + if {[string trim $line] == ""} { + append res "

\n" + } else { + append res "$line\n" + } + } + + set res +} + +proc get_api_docs {data} { + # Initialize global array M as a map from Fts5StructureApi member name + # to member definition. i.e. + # + # iVersion -> {int iVersion} + # xUserData -> {void *(*xUserData)(Fts5Context*)} + # ... + # + array set M [get_struct_members $data] + + # Initialize global list D as a map from section name to documentation + # text. Most (all?) section names are structure member names. + # + set D [get_struct_docs $data [array names M]] + + output "

" + foreach {sub docs} $D { + if {[info exists M($sub)]} { + set hdr $M($sub) + set link " id=$sub" + } else { + set link "" + } + + #output "
" + #set style "padding-left:6ex;font-size:1.4em;display:block" + #output "
$hdr
" + + regsub -line {^ *[)]} $hdr ")" hdr + output "
" + output "$hdr
" + + set mode "" + set margin " style=margin-top:0.1em" + foreach line [split [string trim $docs] "\n"] { + if {[string trim $line]==""} { + if {$mode != ""} {output ""} + set mode "" + } elseif {$mode == ""} { + if {[regexp {^ } $line]} { + set mode codeblock + } else { + set mode p + } + output "<$mode$margin>" + set margin "" + } + output $line + } + if {$mode != ""} {output ""} + output "
" + } + output "
" +} + +proc get_fts5_struct {data start end} { + set res "" + set bOut 0 + foreach line [split $data "\n"] { + if {$bOut==0} { + if {[regexp $start $line]} { + set bOut 1 + } + } + + if {$bOut} { + append res "$line\n" + } + + if {$bOut} { + if {[regexp $end $line]} { + set bOut 0 + } + } + } + + set map [list /* /* */ */] + string map $map $res +} + +proc main {data} { + switch $::extract_api_docs_mode { + fts5_api { + output [get_fts5_struct $data "typedef struct fts5_api" "^\};"] + } + + fts5_tokenizer { + output [get_fts5_struct $data "typedef struct Fts5Tokenizer" "^\};"] + output [get_fts5_struct $data \ + "Flags that may be passed as the third argument to xTokenize()" \ + "#define FTS5_TOKEN_COLOCATED" + ] + } + + fts5_extension { + output [get_fts5_struct $data "typedef.*Fts5ExtensionApi" "^.;"] + } + + Fts5ExtensionApi { + set struct [get_fts5_struct $data "^struct Fts5ExtensionApi" "^.;"] + set map [list] + foreach {k v} [get_struct_members $data] { + if {[string match x* $k]==0} continue + lappend map $k "
$k" + } + output [string map $map $struct] + } + + api { + get_api_docs $data + } + + tokenizer_api { + output [get_tokenizer_docs $data] + } + + default { + } + } +} +main $data + +set ::fts5_docs_output + + + + + diff --git a/ext/fts5/fts5.h b/ext/fts5/fts5.h new file mode 100644 index 0000000..96ecb38 --- /dev/null +++ b/ext/fts5/fts5.h @@ -0,0 +1,578 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +** +** Interfaces to extend FTS5. Using the interfaces defined in this file, +** FTS5 may be extended with: +** +** * custom tokenizers, and +** * custom auxiliary functions. +*/ + + +#ifndef _FTS5_H +#define _FTS5_H + +#include "sqlite3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************* +** CUSTOM AUXILIARY FUNCTIONS +** +** Virtual table implementations may overload SQL functions by implementing +** the sqlite3_module.xFindFunction() method. +*/ + +typedef struct Fts5ExtensionApi Fts5ExtensionApi; +typedef struct Fts5Context Fts5Context; +typedef struct Fts5PhraseIter Fts5PhraseIter; + +typedef void (*fts5_extension_function)( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning result/error */ + int nVal, /* Number of values in apVal[] array */ + sqlite3_value **apVal /* Array of trailing arguments */ +); + +struct Fts5PhraseIter { + const unsigned char *a; + const unsigned char *b; +}; + +/* +** EXTENSION API FUNCTIONS +** +** xUserData(pFts): +** Return a copy of the context pointer the extension function was +** registered with. +** +** xColumnTotalSize(pFts, iCol, pnToken): +** If parameter iCol is less than zero, set output variable *pnToken +** to the total number of tokens in the FTS5 table. Or, if iCol is +** non-negative but less than the number of columns in the table, return +** the total number of tokens in column iCol, considering all rows in +** the FTS5 table. +** +** If parameter iCol is greater than or equal to the number of columns +** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. +** an OOM condition or IO error), an appropriate SQLite error code is +** returned. +** +** xColumnCount(pFts): +** Return the number of columns in the table. +** +** xColumnSize(pFts, iCol, pnToken): +** If parameter iCol is less than zero, set output variable *pnToken +** to the total number of tokens in the current row. Or, if iCol is +** non-negative but less than the number of columns in the table, set +** *pnToken to the number of tokens in column iCol of the current row. +** +** If parameter iCol is greater than or equal to the number of columns +** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. +** an OOM condition or IO error), an appropriate SQLite error code is +** returned. +** +** This function may be quite inefficient if used with an FTS5 table +** created with the "columnsize=0" option. +** +** xColumnText: +** This function attempts to retrieve the text of column iCol of the +** current document. If successful, (*pz) is set to point to a buffer +** containing the text in utf-8 encoding, (*pn) is set to the size in bytes +** (not characters) of the buffer and SQLITE_OK is returned. Otherwise, +** if an error occurs, an SQLite error code is returned and the final values +** of (*pz) and (*pn) are undefined. +** +** xPhraseCount: +** Returns the number of phrases in the current query expression. +** +** xPhraseSize: +** Returns the number of tokens in phrase iPhrase of the query. Phrases +** are numbered starting from zero. +** +** xInstCount: +** Set *pnInst to the total number of occurrences of all phrases within +** the query within the current row. Return SQLITE_OK if successful, or +** an error code (i.e. SQLITE_NOMEM) if an error occurs. +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option +** (i.e. if it is a contentless table), then this API always returns 0. +** +** xInst: +** Query for the details of phrase match iIdx within the current row. +** Phrase matches are numbered starting from zero, so the iIdx argument +** should be greater than or equal to zero and smaller than the value +** output by xInstCount(). +** +** Usually, output parameter *piPhrase is set to the phrase number, *piCol +** to the column in which it occurs and *piOff the token offset of the +** first token of the phrase. The exception is if the table was created +** with the offsets=0 option specified. In this case *piOff is always +** set to -1. +** +** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM) +** if an error occurs. +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. +** +** xRowid: +** Returns the rowid of the current row. +** +** xTokenize: +** Tokenize text using the tokenizer belonging to the FTS5 table. +** +** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback): +** This API function is used to query the FTS table for phrase iPhrase +** of the current query. Specifically, a query equivalent to: +** +** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid +** +** with $p set to a phrase equivalent to the phrase iPhrase of the +** current query is executed. For each row visited, the callback function +** passed as the fourth argument is invoked. The context and API objects +** passed to the callback function may be used to access the properties of +** each matched row. Invoking Api.xUserData() returns a copy of the pointer +** passed as the third argument to pUserData. +** +** If the callback function returns any value other than SQLITE_OK, the +** query is abandoned and the xQueryPhrase function returns immediately. +** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. +** Otherwise, the error code is propagated upwards. +** +** If the query runs to completion without incident, SQLITE_OK is returned. +** Or, if some error occurs before the query completes or is aborted by +** the callback, an SQLite error code is returned. +** +** +** xSetAuxdata(pFts5, pAux, xDelete) +** +** Save the pointer passed as the second argument as the extension functions +** "auxiliary data". The pointer may then be retrieved by the current or any +** future invocation of the same fts5 extension function made as part of +** of the same MATCH query using the xGetAuxdata() API. +** +** Each extension function is allocated a single auxiliary data slot for +** each FTS query (MATCH expression). If the extension function is invoked +** more than once for a single FTS query, then all invocations share a +** single auxiliary data context. +** +** If there is already an auxiliary data pointer when this function is +** invoked, then it is replaced by the new pointer. If an xDelete callback +** was specified along with the original pointer, it is invoked at this +** point. +** +** The xDelete callback, if one is specified, is also invoked on the +** auxiliary data pointer after the FTS5 query has finished. +** +** If an error (e.g. an OOM condition) occurs within this function, an +** the auxiliary data is set to NULL and an error code returned. If the +** xDelete parameter was not NULL, it is invoked on the auxiliary data +** pointer before returning. +** +** +** xGetAuxdata(pFts5, bClear) +** +** Returns the current auxiliary data pointer for the fts5 extension +** function. See the xSetAuxdata() method for details. +** +** If the bClear argument is non-zero, then the auxiliary data is cleared +** (set to NULL) before this function returns. In this case the xDelete, +** if any, is not invoked. +** +** +** xRowCount(pFts5, pnRow) +** +** This function is used to retrieve the total number of rows in the table. +** In other words, the same value that would be returned by: +** +** SELECT count(*) FROM ftstable; +** +** xPhraseFirst() +** This function is used, along with type Fts5PhraseIter and the xPhraseNext +** method, to iterate through all instances of a single query phrase within +** the current row. This is the same information as is accessible via the +** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient +** to use, this API may be faster under some circumstances. To iterate +** through instances of phrase iPhrase, use the following code: +** +** Fts5PhraseIter iter; +** int iCol, iOff; +** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); +** iCol>=0; +** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) +** ){ +** // An instance of phrase iPhrase at offset iOff of column iCol +** } +** +** The Fts5PhraseIter structure is defined above. Applications should not +** modify this structure directly - it should only be used as shown above +** with the xPhraseFirst() and xPhraseNext() API methods (and by +** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below). +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" or "detail=column" option. If the FTS5 table is created +** with either "detail=none" or "detail=column" and "content=" option +** (i.e. if it is a contentless table), then this API always iterates +** through an empty set (all calls to xPhraseFirst() set iCol to -1). +** +** xPhraseNext() +** See xPhraseFirst above. +** +** xPhraseFirstColumn() +** This function and xPhraseNextColumn() are similar to the xPhraseFirst() +** and xPhraseNext() APIs described above. The difference is that instead +** of iterating through all instances of a phrase in the current row, these +** APIs are used to iterate through the set of columns in the current row +** that contain one or more instances of a specified phrase. For example: +** +** Fts5PhraseIter iter; +** int iCol; +** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol); +** iCol>=0; +** pApi->xPhraseNextColumn(pFts, &iter, &iCol) +** ){ +** // Column iCol contains at least one instance of phrase iPhrase +** } +** +** This API can be quite slow if used with an FTS5 table created with the +** "detail=none" option. If the FTS5 table is created with either +** "detail=none" "content=" option (i.e. if it is a contentless table), +** then this API always iterates through an empty set (all calls to +** xPhraseFirstColumn() set iCol to -1). +** +** The information accessed using this API and its companion +** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext +** (or xInst/xInstCount). The chief advantage of this API is that it is +** significantly more efficient than those alternatives when used with +** "detail=column" tables. +** +** xPhraseNextColumn() +** See xPhraseFirstColumn above. +*/ +struct Fts5ExtensionApi { + int iVersion; /* Currently always set to 3 */ + + void *(*xUserData)(Fts5Context*); + + int (*xColumnCount)(Fts5Context*); + int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow); + int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken); + + int (*xTokenize)(Fts5Context*, + const char *pText, int nText, /* Text to tokenize */ + void *pCtx, /* Context passed to xToken() */ + int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ + ); + + int (*xPhraseCount)(Fts5Context*); + int (*xPhraseSize)(Fts5Context*, int iPhrase); + + int (*xInstCount)(Fts5Context*, int *pnInst); + int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff); + + sqlite3_int64 (*xRowid)(Fts5Context*); + int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn); + int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken); + + int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData, + int(*)(const Fts5ExtensionApi*,Fts5Context*,void*) + ); + int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*)); + void *(*xGetAuxdata)(Fts5Context*, int bClear); + + int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*); + void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff); + + int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*); + void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol); +}; + +/* +** CUSTOM AUXILIARY FUNCTIONS +*************************************************************************/ + +/************************************************************************* +** CUSTOM TOKENIZERS +** +** Applications may also register custom tokenizer types. A tokenizer +** is registered by providing fts5 with a populated instance of the +** following structure. All structure methods must be defined, setting +** any member of the fts5_tokenizer struct to NULL leads to undefined +** behaviour. The structure methods are expected to function as follows: +** +** xCreate: +** This function is used to allocate and inititalize a tokenizer instance. +** A tokenizer instance is required to actually tokenize text. +** +** The first argument passed to this function is a copy of the (void*) +** pointer provided by the application when the fts5_tokenizer object +** was registered with FTS5 (the third argument to xCreateTokenizer()). +** The second and third arguments are an array of nul-terminated strings +** containing the tokenizer arguments, if any, specified following the +** tokenizer name as part of the CREATE VIRTUAL TABLE statement used +** to create the FTS5 table. +** +** The final argument is an output variable. If successful, (*ppOut) +** should be set to point to the new tokenizer handle and SQLITE_OK +** returned. If an error occurs, some value other than SQLITE_OK should +** be returned. In this case, fts5 assumes that the final value of *ppOut +** is undefined. +** +** xDelete: +** This function is invoked to delete a tokenizer handle previously +** allocated using xCreate(). Fts5 guarantees that this function will +** be invoked exactly once for each successful call to xCreate(). +** +** xTokenize: +** This function is expected to tokenize the nText byte string indicated +** by argument pText. pText may or may not be nul-terminated. The first +** argument passed to this function is a pointer to an Fts5Tokenizer object +** returned by an earlier call to xCreate(). +** +** The second argument indicates the reason that FTS5 is requesting +** tokenization of the supplied text. This is always one of the following +** four values: +** +**
  • FTS5_TOKENIZE_DOCUMENT - A document is being inserted into +** or removed from the FTS table. The tokenizer is being invoked to +** determine the set of tokens to add to (or delete from) the +** FTS index. +** +**
  • FTS5_TOKENIZE_QUERY - A MATCH query is being executed +** against the FTS index. The tokenizer is being called to tokenize +** a bareword or quoted string specified as part of the query. +** +**
  • (FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) - Same as +** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is +** followed by a "*" character, indicating that the last token +** returned by the tokenizer will be treated as a token prefix. +** +**
  • FTS5_TOKENIZE_AUX - The tokenizer is being invoked to +** satisfy an fts5_api.xTokenize() request made by an auxiliary +** function. Or an fts5_api.xColumnSize() request made by the same +** on a columnsize=0 database. +**
+** +** For each token in the input string, the supplied callback xToken() must +** be invoked. The first argument to it should be a copy of the pointer +** passed as the second argument to xTokenize(). The third and fourth +** arguments are a pointer to a buffer containing the token text, and the +** size of the token in bytes. The 4th and 5th arguments are the byte offsets +** of the first byte of and first byte immediately following the text from +** which the token is derived within the input. +** +** The second argument passed to the xToken() callback ("tflags") should +** normally be set to 0. The exception is if the tokenizer supports +** synonyms. In this case see the discussion below for details. +** +** FTS5 assumes the xToken() callback is invoked for each token in the +** order that they occur within the input text. +** +** If an xToken() callback returns any value other than SQLITE_OK, then +** the tokenization should be abandoned and the xTokenize() method should +** immediately return a copy of the xToken() return value. Or, if the +** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally, +** if an error occurs with the xTokenize() implementation itself, it +** may abandon the tokenization and return any error code other than +** SQLITE_OK or SQLITE_DONE. +** +** SYNONYM SUPPORT +** +** Custom tokenizers may also support synonyms. Consider a case in which a +** user wishes to query for a phrase such as "first place". Using the +** built-in tokenizers, the FTS5 query 'first + place' will match instances +** of "first place" within the document set, but not alternative forms +** such as "1st place". In some applications, it would be better to match +** all instances of "first place" or "1st place" regardless of which form +** the user specified in the MATCH query text. +** +** There are several ways to approach this in FTS5: +** +**
  1. By mapping all synonyms to a single token. In this case, the +** In the above example, this means that the tokenizer returns the +** same token for inputs "first" and "1st". Say that token is in +** fact "first", so that when the user inserts the document "I won +** 1st place" entries are added to the index for tokens "i", "won", +** "first" and "place". If the user then queries for '1st + place', +** the tokenizer substitutes "first" for "1st" and the query works +** as expected. +** +**
  2. By adding multiple synonyms for a single term to the FTS index. +** In this case, when tokenizing query text, the tokenizer may +** provide multiple synonyms for a single term within the document. +** FTS5 then queries the index for each synonym individually. For +** example, faced with the query: +** +** +** ... MATCH 'first place' +** +** the tokenizer offers both "1st" and "first" as synonyms for the +** first token in the MATCH query and FTS5 effectively runs a query +** similar to: +** +** +** ... MATCH '(first OR 1st) place' +** +** except that, for the purposes of auxiliary functions, the query +** still appears to contain just two phrases - "(first OR 1st)" +** being treated as a single phrase. +** +**
  3. By adding multiple synonyms for a single term to the FTS index. +** Using this method, when tokenizing document text, the tokenizer +** provides multiple synonyms for each token. So that when a +** document such as "I won first place" is tokenized, entries are +** added to the FTS index for "i", "won", "first", "1st" and +** "place". +** +** This way, even if the tokenizer does not provide synonyms +** when tokenizing query text (it should not - to do would be +** inefficient), it doesn't matter if the user queries for +** 'first + place' or '1st + place', as there are entires in the +** FTS index corresponding to both forms of the first token. +**
+** +** Whether it is parsing document or query text, any call to xToken that +** specifies a tflags argument with the FTS5_TOKEN_COLOCATED bit +** is considered to supply a synonym for the previous token. For example, +** when parsing the document "I won first place", a tokenizer that supports +** synonyms would call xToken() 5 times, as follows: +** +** +** xToken(pCtx, 0, "i", 1, 0, 1); +** xToken(pCtx, 0, "won", 3, 2, 5); +** xToken(pCtx, 0, "first", 5, 6, 11); +** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11); +** xToken(pCtx, 0, "place", 5, 12, 17); +** +** +** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time +** xToken() is called. Multiple synonyms may be specified for a single token +** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence. +** There is no limit to the number of synonyms that may be provided for a +** single token. +** +** In many cases, method (1) above is the best approach. It does not add +** extra data to the FTS index or require FTS5 to query for multiple terms, +** so it is efficient in terms of disk space and query speed. However, it +** does not support prefix queries very well. If, as suggested above, the +** token "first" is subsituted for "1st" by the tokenizer, then the query: +** +** +** ... MATCH '1s*' +** +** will not match documents that contain the token "1st" (as the tokenizer +** will probably not map "1s" to any prefix of "first"). +** +** For full prefix support, method (3) may be preferred. In this case, +** because the index contains entries for both "first" and "1st", prefix +** queries such as 'fi*' or '1s*' will match correctly. However, because +** extra entries are added to the FTS index, this method uses more space +** within the database. +** +** Method (2) offers a midpoint between (1) and (3). Using this method, +** a query such as '1s*' will match documents that contain the literal +** token "1st", but not "first" (assuming the tokenizer is not able to +** provide synonyms for prefixes). However, a non-prefix query like '1st' +** will match against "1st" and "first". This method does not require +** extra disk space, as no extra entries are added to the FTS index. +** On the other hand, it may require more CPU cycles to run MATCH queries, +** as separate queries of the FTS index are required for each synonym. +** +** When using methods (2) or (3), it is important that the tokenizer only +** provide synonyms when tokenizing document text (method (2)) or query +** text (method (3)), not both. Doing so will not cause any errors, but is +** inefficient. +*/ +typedef struct Fts5Tokenizer Fts5Tokenizer; +typedef struct fts5_tokenizer fts5_tokenizer; +struct fts5_tokenizer { + int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut); + void (*xDelete)(Fts5Tokenizer*); + int (*xTokenize)(Fts5Tokenizer*, + void *pCtx, + int flags, /* Mask of FTS5_TOKENIZE_* flags */ + const char *pText, int nText, + int (*xToken)( + void *pCtx, /* Copy of 2nd argument to xTokenize() */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Pointer to buffer containing token */ + int nToken, /* Size of token in bytes */ + int iStart, /* Byte offset of token within input text */ + int iEnd /* Byte offset of end of token within input text */ + ) + ); +}; + +/* Flags that may be passed as the third argument to xTokenize() */ +#define FTS5_TOKENIZE_QUERY 0x0001 +#define FTS5_TOKENIZE_PREFIX 0x0002 +#define FTS5_TOKENIZE_DOCUMENT 0x0004 +#define FTS5_TOKENIZE_AUX 0x0008 + +/* Flags that may be passed by the tokenizer implementation back to FTS5 +** as the third argument to the supplied xToken callback. */ +#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */ + +/* +** END OF CUSTOM TOKENIZERS +*************************************************************************/ + +/************************************************************************* +** FTS5 EXTENSION REGISTRATION API +*/ +typedef struct fts5_api fts5_api; +struct fts5_api { + int iVersion; /* Currently always set to 2 */ + + /* Create a new tokenizer */ + int (*xCreateTokenizer)( + fts5_api *pApi, + const char *zName, + void *pContext, + fts5_tokenizer *pTokenizer, + void (*xDestroy)(void*) + ); + + /* Find an existing tokenizer */ + int (*xFindTokenizer)( + fts5_api *pApi, + const char *zName, + void **ppContext, + fts5_tokenizer *pTokenizer + ); + + /* Create a new auxiliary function */ + int (*xCreateFunction)( + fts5_api *pApi, + const char *zName, + void *pContext, + fts5_extension_function xFunction, + void (*xDestroy)(void*) + ); +}; + +/* +** END OF REGISTRATION API +*************************************************************************/ + +#ifdef __cplusplus +} /* end of the 'extern "C"' block */ +#endif + +#endif /* _FTS5_H */ + diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h new file mode 100644 index 0000000..af40412 --- /dev/null +++ b/ext/fts5/fts5Int.h @@ -0,0 +1,776 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +** +*/ +#ifndef _FTS5INT_H +#define _FTS5INT_H + +#include "fts5.h" +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 + +#include +#include + +#ifndef SQLITE_AMALGAMATION + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned short u16; +typedef short i16; +typedef sqlite3_int64 i64; +typedef sqlite3_uint64 u64; + +#define ArraySize(x) ((int)(sizeof(x) / sizeof(x[0]))) + +#define testcase(x) +#define ALWAYS(x) 1 +#define NEVER(x) 0 + +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) + +/* +** Constants for the largest and smallest possible 64-bit signed integers. +*/ +# define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +# define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + +#endif + + +/* +** Maximum number of prefix indexes on single FTS5 table. This must be +** less than 32. If it is set to anything large than that, an #error +** directive in fts5_index.c will cause the build to fail. +*/ +#define FTS5_MAX_PREFIX_INDEXES 31 + +#define FTS5_DEFAULT_NEARDIST 10 +#define FTS5_DEFAULT_RANK "bm25" + +/* Name of rank and rowid columns */ +#define FTS5_RANK_NAME "rank" +#define FTS5_ROWID_NAME "rowid" + +#ifdef SQLITE_DEBUG +# define FTS5_CORRUPT sqlite3Fts5Corrupt() +int sqlite3Fts5Corrupt(void); +#else +# define FTS5_CORRUPT SQLITE_CORRUPT_VTAB +#endif + +/* +** The assert_nc() macro is similar to the assert() macro, except that it +** is used for assert() conditions that are true only if it can be +** guranteed that the database is not corrupt. +*/ +#ifdef SQLITE_DEBUG +extern int sqlite3_fts5_may_be_corrupt; +# define assert_nc(x) assert(sqlite3_fts5_may_be_corrupt || (x)) +#else +# define assert_nc(x) assert(x) +#endif + +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAM +# define UNUSED_PARAM(X) (void)(X) +#endif + +#ifndef UNUSED_PARAM2 +# define UNUSED_PARAM2(X, Y) (void)(X), (void)(Y) +#endif + +typedef struct Fts5Global Fts5Global; +typedef struct Fts5Colset Fts5Colset; + +/* If a NEAR() clump or phrase may only match a specific set of columns, +** then an object of the following type is used to record the set of columns. +** Each entry in the aiCol[] array is a column that may be matched. +** +** This object is used by fts5_expr.c and fts5_index.c. +*/ +struct Fts5Colset { + int nCol; + int aiCol[1]; +}; + + + +/************************************************************************** +** Interface to code in fts5_config.c. fts5_config.c contains contains code +** to parse the arguments passed to the CREATE VIRTUAL TABLE statement. +*/ + +typedef struct Fts5Config Fts5Config; + +/* +** An instance of the following structure encodes all information that can +** be gleaned from the CREATE VIRTUAL TABLE statement. +** +** And all information loaded from the %_config table. +** +** nAutomerge: +** The minimum number of segments that an auto-merge operation should +** attempt to merge together. A value of 1 sets the object to use the +** compile time default. Zero disables auto-merge altogether. +** +** zContent: +** +** zContentRowid: +** The value of the content_rowid= option, if one was specified. Or +** the string "rowid" otherwise. This text is not quoted - if it is +** used as part of an SQL statement it needs to be quoted appropriately. +** +** zContentExprlist: +** +** pzErrmsg: +** This exists in order to allow the fts5_index.c module to return a +** decent error message if it encounters a file-format version it does +** not understand. +** +** bColumnsize: +** True if the %_docsize table is created. +** +** bPrefixIndex: +** This is only used for debugging. If set to false, any prefix indexes +** are ignored. This value is configured using: +** +** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex); +** +*/ +struct Fts5Config { + sqlite3 *db; /* Database handle */ + char *zDb; /* Database holding FTS index (e.g. "main") */ + char *zName; /* Name of FTS index */ + int nCol; /* Number of columns */ + char **azCol; /* Column names */ + u8 *abUnindexed; /* True for unindexed columns */ + int nPrefix; /* Number of prefix indexes */ + int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */ + int eContent; /* An FTS5_CONTENT value */ + char *zContent; /* content table */ + char *zContentRowid; /* "content_rowid=" option value */ + int bColumnsize; /* "columnsize=" option value (dflt==1) */ + int eDetail; /* FTS5_DETAIL_XXX value */ + char *zContentExprlist; + Fts5Tokenizer *pTok; + fts5_tokenizer *pTokApi; + + /* Values loaded from the %_config table */ + int iCookie; /* Incremented when %_config is modified */ + int pgsz; /* Approximate page size used in %_data */ + int nAutomerge; /* 'automerge' setting */ + int nCrisisMerge; /* Maximum allowed segments per level */ + int nHashSize; /* Bytes of memory for in-memory hash */ + char *zRank; /* Name of rank function */ + char *zRankArgs; /* Arguments to rank function */ + + /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */ + char **pzErrmsg; + +#ifdef SQLITE_DEBUG + int bPrefixIndex; /* True to use prefix-indexes */ +#endif +}; + +/* Current expected value of %_config table 'version' field */ +#define FTS5_CURRENT_VERSION 4 + +#define FTS5_CONTENT_NORMAL 0 +#define FTS5_CONTENT_NONE 1 +#define FTS5_CONTENT_EXTERNAL 2 + +#define FTS5_DETAIL_FULL 0 +#define FTS5_DETAIL_NONE 1 +#define FTS5_DETAIL_COLUMNS 2 + + + +int sqlite3Fts5ConfigParse( + Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char** +); +void sqlite3Fts5ConfigFree(Fts5Config*); + +int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig); + +int sqlite3Fts5Tokenize( + Fts5Config *pConfig, /* FTS5 Configuration object */ + int flags, /* FTS5_TOKENIZE_* flags */ + const char *pText, int nText, /* Text to tokenize */ + void *pCtx, /* Context passed to xToken() */ + int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ +); + +void sqlite3Fts5Dequote(char *z); + +/* Load the contents of the %_config table */ +int sqlite3Fts5ConfigLoad(Fts5Config*, int); + +/* Set the value of a single config attribute */ +int sqlite3Fts5ConfigSetValue(Fts5Config*, const char*, sqlite3_value*, int*); + +int sqlite3Fts5ConfigParseRank(const char*, char**, char**); + +/* +** End of interface to code in fts5_config.c. +**************************************************************************/ + +/************************************************************************** +** Interface to code in fts5_buffer.c. +*/ + +/* +** Buffer object for the incremental building of string data. +*/ +typedef struct Fts5Buffer Fts5Buffer; +struct Fts5Buffer { + u8 *p; + int n; + int nSpace; +}; + +int sqlite3Fts5BufferSize(int*, Fts5Buffer*, u32); +void sqlite3Fts5BufferAppendVarint(int*, Fts5Buffer*, i64); +void sqlite3Fts5BufferAppendBlob(int*, Fts5Buffer*, u32, const u8*); +void sqlite3Fts5BufferAppendString(int *, Fts5Buffer*, const char*); +void sqlite3Fts5BufferFree(Fts5Buffer*); +void sqlite3Fts5BufferZero(Fts5Buffer*); +void sqlite3Fts5BufferSet(int*, Fts5Buffer*, int, const u8*); +void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...); + +char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...); + +#define fts5BufferZero(x) sqlite3Fts5BufferZero(x) +#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c) +#define fts5BufferFree(a) sqlite3Fts5BufferFree(a) +#define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d) +#define fts5BufferSet(a,b,c,d) sqlite3Fts5BufferSet(a,b,c,d) + +#define fts5BufferGrow(pRc,pBuf,nn) ( \ + (u32)((pBuf)->n) + (u32)(nn) <= (u32)((pBuf)->nSpace) ? 0 : \ + sqlite3Fts5BufferSize((pRc),(pBuf),(nn)+(pBuf)->n) \ +) + +/* Write and decode big-endian 32-bit integer values */ +void sqlite3Fts5Put32(u8*, int); +int sqlite3Fts5Get32(const u8*); + +#define FTS5_POS2COLUMN(iPos) (int)(iPos >> 32) +#define FTS5_POS2OFFSET(iPos) (int)(iPos & 0xFFFFFFFF) + +typedef struct Fts5PoslistReader Fts5PoslistReader; +struct Fts5PoslistReader { + /* Variables used only by sqlite3Fts5PoslistIterXXX() functions. */ + const u8 *a; /* Position list to iterate through */ + int n; /* Size of buffer at a[] in bytes */ + int i; /* Current offset in a[] */ + + u8 bFlag; /* For client use (any custom purpose) */ + + /* Output variables */ + u8 bEof; /* Set to true at EOF */ + i64 iPos; /* (iCol<<32) + iPos */ +}; +int sqlite3Fts5PoslistReaderInit( + const u8 *a, int n, /* Poslist buffer to iterate through */ + Fts5PoslistReader *pIter /* Iterator object to initialize */ +); +int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader*); + +typedef struct Fts5PoslistWriter Fts5PoslistWriter; +struct Fts5PoslistWriter { + i64 iPrev; +}; +int sqlite3Fts5PoslistWriterAppend(Fts5Buffer*, Fts5PoslistWriter*, i64); +void sqlite3Fts5PoslistSafeAppend(Fts5Buffer*, i64*, i64); + +int sqlite3Fts5PoslistNext64( + const u8 *a, int n, /* Buffer containing poslist */ + int *pi, /* IN/OUT: Offset within a[] */ + i64 *piOff /* IN/OUT: Current offset */ +); + +/* Malloc utility */ +void *sqlite3Fts5MallocZero(int *pRc, int nByte); +char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn); + +/* Character set tests (like isspace(), isalpha() etc.) */ +int sqlite3Fts5IsBareword(char t); + + +/* Bucket of terms object used by the integrity-check in offsets=0 mode. */ +typedef struct Fts5Termset Fts5Termset; +int sqlite3Fts5TermsetNew(Fts5Termset**); +int sqlite3Fts5TermsetAdd(Fts5Termset*, int, const char*, int, int *pbPresent); +void sqlite3Fts5TermsetFree(Fts5Termset*); + +/* +** End of interface to code in fts5_buffer.c. +**************************************************************************/ + +/************************************************************************** +** Interface to code in fts5_index.c. fts5_index.c contains contains code +** to access the data stored in the %_data table. +*/ + +typedef struct Fts5Index Fts5Index; +typedef struct Fts5IndexIter Fts5IndexIter; + +struct Fts5IndexIter { + i64 iRowid; + const u8 *pData; + int nData; + u8 bEof; +}; + +#define sqlite3Fts5IterEof(x) ((x)->bEof) + +/* +** Values used as part of the flags argument passed to IndexQuery(). +*/ +#define FTS5INDEX_QUERY_PREFIX 0x0001 /* Prefix query */ +#define FTS5INDEX_QUERY_DESC 0x0002 /* Docs in descending rowid order */ +#define FTS5INDEX_QUERY_TEST_NOIDX 0x0004 /* Do not use prefix index */ +#define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ + +/* The following are used internally by the fts5_index.c module. They are +** defined here only to make it easier to avoid clashes with the flags +** above. */ +#define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 +#define FTS5INDEX_QUERY_NOOUTPUT 0x0020 + +/* +** Create/destroy an Fts5Index object. +*/ +int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); +int sqlite3Fts5IndexClose(Fts5Index *p); + +/* +** Return a simple checksum value based on the arguments. +*/ +u64 sqlite3Fts5IndexEntryCksum( + i64 iRowid, + int iCol, + int iPos, + int iIdx, + const char *pTerm, + int nTerm +); + +/* +** Argument p points to a buffer containing utf-8 text that is n bytes in +** size. Return the number of bytes in the nChar character prefix of the +** buffer, or 0 if there are less than nChar characters in total. +*/ +int sqlite3Fts5IndexCharlenToBytelen( + const char *p, + int nByte, + int nChar +); + +/* +** Open a new iterator to iterate though all rowids that match the +** specified token or token prefix. +*/ +int sqlite3Fts5IndexQuery( + Fts5Index *p, /* FTS index to query */ + const char *pToken, int nToken, /* Token (or prefix) to query for */ + int flags, /* Mask of FTS5INDEX_QUERY_X flags */ + Fts5Colset *pColset, /* Match these columns only */ + Fts5IndexIter **ppIter /* OUT: New iterator object */ +); + +/* +** The various operations on open token or token prefix iterators opened +** using sqlite3Fts5IndexQuery(). +*/ +int sqlite3Fts5IterNext(Fts5IndexIter*); +int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch); + +/* +** Close an iterator opened by sqlite3Fts5IndexQuery(). +*/ +void sqlite3Fts5IterClose(Fts5IndexIter*); + +/* +** This interface is used by the fts5vocab module. +*/ +const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*); +int sqlite3Fts5IterNextScan(Fts5IndexIter*); + + +/* +** Insert or remove data to or from the index. Each time a document is +** added to or removed from the index, this function is called one or more +** times. +** +** For an insert, it must be called once for each token in the new document. +** If the operation is a delete, it must be called (at least) once for each +** unique token in the document with an iCol value less than zero. The iPos +** argument is ignored for a delete. +*/ +int sqlite3Fts5IndexWrite( + Fts5Index *p, /* Index to write to */ + int iCol, /* Column token appears in (-ve -> delete) */ + int iPos, /* Position of token within column */ + const char *pToken, int nToken /* Token to add or remove to or from index */ +); + +/* +** Indicate that subsequent calls to sqlite3Fts5IndexWrite() pertain to +** document iDocid. +*/ +int sqlite3Fts5IndexBeginWrite( + Fts5Index *p, /* Index to write to */ + int bDelete, /* True if current operation is a delete */ + i64 iDocid /* Docid to add or remove data from */ +); + +/* +** Flush any data stored in the in-memory hash tables to the database. +** If the bCommit flag is true, also close any open blob handles. +*/ +int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit); + +/* +** Discard any data stored in the in-memory hash tables. Do not write it +** to the database. Additionally, assume that the contents of the %_data +** table may have changed on disk. So any in-memory caches of %_data +** records must be invalidated. +*/ +int sqlite3Fts5IndexRollback(Fts5Index *p); + +/* +** Get or set the "averages" values. +*/ +int sqlite3Fts5IndexGetAverages(Fts5Index *p, i64 *pnRow, i64 *anSize); +int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int); + +/* +** Functions called by the storage module as part of integrity-check. +*/ +int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum); + +/* +** Called during virtual module initialization to register UDF +** fts5_decode() with SQLite +*/ +int sqlite3Fts5IndexInit(sqlite3*); + +int sqlite3Fts5IndexSetCookie(Fts5Index*, int); + +/* +** Return the total number of entries read from the %_data table by +** this connection since it was created. +*/ +int sqlite3Fts5IndexReads(Fts5Index *p); + +int sqlite3Fts5IndexReinit(Fts5Index *p); +int sqlite3Fts5IndexOptimize(Fts5Index *p); +int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge); + +int sqlite3Fts5IndexLoadConfig(Fts5Index *p); + +/* +** End of interface to code in fts5_index.c. +**************************************************************************/ + +/************************************************************************** +** Interface to code in fts5_varint.c. +*/ +int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v); +int sqlite3Fts5GetVarintLen(u32 iVal); +u8 sqlite3Fts5GetVarint(const unsigned char*, u64*); +int sqlite3Fts5PutVarint(unsigned char *p, u64 v); + +#define fts5GetVarint32(a,b) sqlite3Fts5GetVarint32(a,(u32*)&b) +#define fts5GetVarint sqlite3Fts5GetVarint + +#define fts5FastGetVarint32(a, iOff, nVal) { \ + nVal = (a)[iOff++]; \ + if( nVal & 0x80 ){ \ + iOff--; \ + iOff += fts5GetVarint32(&(a)[iOff], nVal); \ + } \ +} + + +/* +** End of interface to code in fts5_varint.c. +**************************************************************************/ + + +/************************************************************************** +** Interface to code in fts5.c. +*/ + +int sqlite3Fts5GetTokenizer( + Fts5Global*, + const char **azArg, + int nArg, + Fts5Tokenizer**, + fts5_tokenizer**, + char **pzErr +); + +Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **); + +/* +** End of interface to code in fts5.c. +**************************************************************************/ + +/************************************************************************** +** Interface to code in fts5_hash.c. +*/ +typedef struct Fts5Hash Fts5Hash; + +/* +** Create a hash table, free a hash table. +*/ +int sqlite3Fts5HashNew(Fts5Config*, Fts5Hash**, int *pnSize); +void sqlite3Fts5HashFree(Fts5Hash*); + +int sqlite3Fts5HashWrite( + Fts5Hash*, + i64 iRowid, /* Rowid for this entry */ + int iCol, /* Column token appears in (-ve -> delete) */ + int iPos, /* Position of token within column */ + char bByte, + const char *pToken, int nToken /* Token to add or remove to or from index */ +); + +/* +** Empty (but do not delete) a hash table. +*/ +void sqlite3Fts5HashClear(Fts5Hash*); + +int sqlite3Fts5HashQuery( + Fts5Hash*, /* Hash table to query */ + const char *pTerm, int nTerm, /* Query term */ + const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ + int *pnDoclist /* OUT: Size of doclist in bytes */ +); + +int sqlite3Fts5HashScanInit( + Fts5Hash*, /* Hash table to query */ + const char *pTerm, int nTerm /* Query prefix */ +); +void sqlite3Fts5HashScanNext(Fts5Hash*); +int sqlite3Fts5HashScanEof(Fts5Hash*); +void sqlite3Fts5HashScanEntry(Fts5Hash *, + const char **pzTerm, /* OUT: term (nul-terminated) */ + const u8 **ppDoclist, /* OUT: pointer to doclist */ + int *pnDoclist /* OUT: size of doclist in bytes */ +); + + +/* +** End of interface to code in fts5_hash.c. +**************************************************************************/ + +/************************************************************************** +** Interface to code in fts5_storage.c. fts5_storage.c contains contains +** code to access the data stored in the %_content and %_docsize tables. +*/ + +#define FTS5_STMT_SCAN_ASC 0 /* SELECT rowid, * FROM ... ORDER BY 1 ASC */ +#define FTS5_STMT_SCAN_DESC 1 /* SELECT rowid, * FROM ... ORDER BY 1 DESC */ +#define FTS5_STMT_LOOKUP 2 /* SELECT rowid, * FROM ... WHERE rowid=? */ + +typedef struct Fts5Storage Fts5Storage; + +int sqlite3Fts5StorageOpen(Fts5Config*, Fts5Index*, int, Fts5Storage**, char**); +int sqlite3Fts5StorageClose(Fts5Storage *p); +int sqlite3Fts5StorageRename(Fts5Storage*, const char *zName); + +int sqlite3Fts5DropAll(Fts5Config*); +int sqlite3Fts5CreateTable(Fts5Config*, const char*, const char*, int, char **); + +int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**); +int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*); +int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64); + +int sqlite3Fts5StorageIntegrity(Fts5Storage *p); + +int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**); +void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*); + +int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol); +int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnAvg); +int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow); + +int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit); +int sqlite3Fts5StorageRollback(Fts5Storage *p); + +int sqlite3Fts5StorageConfigValue( + Fts5Storage *p, const char*, sqlite3_value*, int +); + +int sqlite3Fts5StorageDeleteAll(Fts5Storage *p); +int sqlite3Fts5StorageRebuild(Fts5Storage *p); +int sqlite3Fts5StorageOptimize(Fts5Storage *p); +int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge); + +/* +** End of interface to code in fts5_storage.c. +**************************************************************************/ + + +/************************************************************************** +** Interface to code in fts5_expr.c. +*/ +typedef struct Fts5Expr Fts5Expr; +typedef struct Fts5ExprNode Fts5ExprNode; +typedef struct Fts5Parse Fts5Parse; +typedef struct Fts5Token Fts5Token; +typedef struct Fts5ExprPhrase Fts5ExprPhrase; +typedef struct Fts5ExprNearset Fts5ExprNearset; + +struct Fts5Token { + const char *p; /* Token text (not NULL terminated) */ + int n; /* Size of buffer p in bytes */ +}; + +/* Parse a MATCH expression. */ +int sqlite3Fts5ExprNew( + Fts5Config *pConfig, + const char *zExpr, + Fts5Expr **ppNew, + char **pzErr +); + +/* +** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc); +** rc==SQLITE_OK && 0==sqlite3Fts5ExprEof(pExpr); +** rc = sqlite3Fts5ExprNext(pExpr) +** ){ +** // The document with rowid iRowid matches the expression! +** i64 iRowid = sqlite3Fts5ExprRowid(pExpr); +** } +*/ +int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc); +int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax); +int sqlite3Fts5ExprEof(Fts5Expr*); +i64 sqlite3Fts5ExprRowid(Fts5Expr*); + +void sqlite3Fts5ExprFree(Fts5Expr*); + +/* Called during startup to register a UDF with SQLite */ +int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*); + +int sqlite3Fts5ExprPhraseCount(Fts5Expr*); +int sqlite3Fts5ExprPhraseSize(Fts5Expr*, int iPhrase); +int sqlite3Fts5ExprPoslist(Fts5Expr*, int, const u8 **); + +typedef struct Fts5PoslistPopulator Fts5PoslistPopulator; +Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr*, int); +int sqlite3Fts5ExprPopulatePoslists( + Fts5Config*, Fts5Expr*, Fts5PoslistPopulator*, int, const char*, int +); +void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64); +void sqlite3Fts5ExprClearEof(Fts5Expr*); + +int sqlite3Fts5ExprClonePhrase(Fts5Expr*, int, Fts5Expr**); + +int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *); + +/******************************************* +** The fts5_expr.c API above this point is used by the other hand-written +** C code in this module. The interfaces below this point are called by +** the parser code in fts5parse.y. */ + +void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...); + +Fts5ExprNode *sqlite3Fts5ParseNode( + Fts5Parse *pParse, + int eType, + Fts5ExprNode *pLeft, + Fts5ExprNode *pRight, + Fts5ExprNearset *pNear +); + +Fts5ExprPhrase *sqlite3Fts5ParseTerm( + Fts5Parse *pParse, + Fts5ExprPhrase *pPhrase, + Fts5Token *pToken, + int bPrefix +); + +Fts5ExprNearset *sqlite3Fts5ParseNearset( + Fts5Parse*, + Fts5ExprNearset*, + Fts5ExprPhrase* +); + +Fts5Colset *sqlite3Fts5ParseColset( + Fts5Parse*, + Fts5Colset*, + Fts5Token * +); + +void sqlite3Fts5ParsePhraseFree(Fts5ExprPhrase*); +void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset*); +void sqlite3Fts5ParseNodeFree(Fts5ExprNode*); + +void sqlite3Fts5ParseSetDistance(Fts5Parse*, Fts5ExprNearset*, Fts5Token*); +void sqlite3Fts5ParseSetColset(Fts5Parse*, Fts5ExprNearset*, Fts5Colset*); +void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p); +void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*); + +/* +** End of interface to code in fts5_expr.c. +**************************************************************************/ + + + +/************************************************************************** +** Interface to code in fts5_aux.c. +*/ + +int sqlite3Fts5AuxInit(fts5_api*); +/* +** End of interface to code in fts5_aux.c. +**************************************************************************/ + +/************************************************************************** +** Interface to code in fts5_tokenizer.c. +*/ + +int sqlite3Fts5TokenizerInit(fts5_api*); +/* +** End of interface to code in fts5_tokenizer.c. +**************************************************************************/ + +/************************************************************************** +** Interface to code in fts5_vocab.c. +*/ + +int sqlite3Fts5VocabInit(Fts5Global*, sqlite3*); + +/* +** End of interface to code in fts5_vocab.c. +**************************************************************************/ + + +/************************************************************************** +** Interface to automatically generated code in fts5_unicode2.c. +*/ +int sqlite3Fts5UnicodeIsalnum(int c); +int sqlite3Fts5UnicodeIsdiacritic(int c); +int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic); +/* +** End of interface to code in fts5_unicode2.c. +**************************************************************************/ + +#endif diff --git a/ext/fts5/fts5_aux.c b/ext/fts5/fts5_aux.c new file mode 100644 index 0000000..836de8a --- /dev/null +++ b/ext/fts5/fts5_aux.c @@ -0,0 +1,562 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +*/ + + +#include "fts5Int.h" +#include /* amalgamator: keep */ + +/* +** Object used to iterate through all "coalesced phrase instances" in +** a single column of the current row. If the phrase instances in the +** column being considered do not overlap, this object simply iterates +** through them. Or, if they do overlap (share one or more tokens in +** common), each set of overlapping instances is treated as a single +** match. See documentation for the highlight() auxiliary function for +** details. +** +** Usage is: +** +** for(rc = fts5CInstIterNext(pApi, pFts, iCol, &iter); +** (rc==SQLITE_OK && 0==fts5CInstIterEof(&iter); +** rc = fts5CInstIterNext(&iter) +** ){ +** printf("instance starts at %d, ends at %d\n", iter.iStart, iter.iEnd); +** } +** +*/ +typedef struct CInstIter CInstIter; +struct CInstIter { + const Fts5ExtensionApi *pApi; /* API offered by current FTS version */ + Fts5Context *pFts; /* First arg to pass to pApi functions */ + int iCol; /* Column to search */ + int iInst; /* Next phrase instance index */ + int nInst; /* Total number of phrase instances */ + + /* Output variables */ + int iStart; /* First token in coalesced phrase instance */ + int iEnd; /* Last token in coalesced phrase instance */ +}; + +/* +** Advance the iterator to the next coalesced phrase instance. Return +** an SQLite error code if an error occurs, or SQLITE_OK otherwise. +*/ +static int fts5CInstIterNext(CInstIter *pIter){ + int rc = SQLITE_OK; + pIter->iStart = -1; + pIter->iEnd = -1; + + while( rc==SQLITE_OK && pIter->iInstnInst ){ + int ip; int ic; int io; + rc = pIter->pApi->xInst(pIter->pFts, pIter->iInst, &ip, &ic, &io); + if( rc==SQLITE_OK ){ + if( ic==pIter->iCol ){ + int iEnd = io - 1 + pIter->pApi->xPhraseSize(pIter->pFts, ip); + if( pIter->iStart<0 ){ + pIter->iStart = io; + pIter->iEnd = iEnd; + }else if( io<=pIter->iEnd ){ + if( iEnd>pIter->iEnd ) pIter->iEnd = iEnd; + }else{ + break; + } + } + pIter->iInst++; + } + } + + return rc; +} + +/* +** Initialize the iterator object indicated by the final parameter to +** iterate through coalesced phrase instances in column iCol. +*/ +static int fts5CInstIterInit( + const Fts5ExtensionApi *pApi, + Fts5Context *pFts, + int iCol, + CInstIter *pIter +){ + int rc; + + memset(pIter, 0, sizeof(CInstIter)); + pIter->pApi = pApi; + pIter->pFts = pFts; + pIter->iCol = iCol; + rc = pApi->xInstCount(pFts, &pIter->nInst); + + if( rc==SQLITE_OK ){ + rc = fts5CInstIterNext(pIter); + } + + return rc; +} + + + +/************************************************************************* +** Start of highlight() implementation. +*/ +typedef struct HighlightContext HighlightContext; +struct HighlightContext { + CInstIter iter; /* Coalesced Instance Iterator */ + int iPos; /* Current token offset in zIn[] */ + int iRangeStart; /* First token to include */ + int iRangeEnd; /* If non-zero, last token to include */ + const char *zOpen; /* Opening highlight */ + const char *zClose; /* Closing highlight */ + const char *zIn; /* Input text */ + int nIn; /* Size of input text in bytes */ + int iOff; /* Current offset within zIn[] */ + char *zOut; /* Output value */ +}; + +/* +** Append text to the HighlightContext output string - p->zOut. Argument +** z points to a buffer containing n bytes of text to append. If n is +** negative, everything up until the first '\0' is appended to the output. +** +** If *pRc is set to any value other than SQLITE_OK when this function is +** called, it is a no-op. If an error (i.e. an OOM condition) is encountered, +** *pRc is set to an error code before returning. +*/ +static void fts5HighlightAppend( + int *pRc, + HighlightContext *p, + const char *z, int n +){ + if( *pRc==SQLITE_OK ){ + if( n<0 ) n = (int)strlen(z); + p->zOut = sqlite3_mprintf("%z%.*s", p->zOut, n, z); + if( p->zOut==0 ) *pRc = SQLITE_NOMEM; + } +} + +/* +** Tokenizer callback used by implementation of highlight() function. +*/ +static int fts5HighlightCb( + void *pContext, /* Pointer to HighlightContext object */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Buffer containing token */ + int nToken, /* Size of token in bytes */ + int iStartOff, /* Start offset of token */ + int iEndOff /* End offset of token */ +){ + HighlightContext *p = (HighlightContext*)pContext; + int rc = SQLITE_OK; + int iPos; + + UNUSED_PARAM2(pToken, nToken); + + if( tflags & FTS5_TOKEN_COLOCATED ) return SQLITE_OK; + iPos = p->iPos++; + + if( p->iRangeEnd>0 ){ + if( iPosiRangeStart || iPos>p->iRangeEnd ) return SQLITE_OK; + if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff; + } + + if( iPos==p->iter.iStart ){ + fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iStartOff - p->iOff); + fts5HighlightAppend(&rc, p, p->zOpen, -1); + p->iOff = iStartOff; + } + + if( iPos==p->iter.iEnd ){ + if( p->iRangeEnd && p->iter.iStartiRangeStart ){ + fts5HighlightAppend(&rc, p, p->zOpen, -1); + } + fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); + fts5HighlightAppend(&rc, p, p->zClose, -1); + p->iOff = iEndOff; + if( rc==SQLITE_OK ){ + rc = fts5CInstIterNext(&p->iter); + } + } + + if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){ + fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); + p->iOff = iEndOff; + if( iPositer.iEnd ){ + fts5HighlightAppend(&rc, p, p->zClose, -1); + } + } + + return rc; +} + +/* +** Implementation of highlight() function. +*/ +static void fts5HighlightFunction( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning result/error */ + int nVal, /* Number of values in apVal[] array */ + sqlite3_value **apVal /* Array of trailing arguments */ +){ + HighlightContext ctx; + int rc; + int iCol; + + if( nVal!=3 ){ + const char *zErr = "wrong number of arguments to function highlight()"; + sqlite3_result_error(pCtx, zErr, -1); + return; + } + + iCol = sqlite3_value_int(apVal[0]); + memset(&ctx, 0, sizeof(HighlightContext)); + ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); + ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); + rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn); + + if( ctx.zIn ){ + if( rc==SQLITE_OK ){ + rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter); + } + + if( rc==SQLITE_OK ){ + rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); + } + fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); + + if( rc==SQLITE_OK ){ + sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); + } + sqlite3_free(ctx.zOut); + } + if( rc!=SQLITE_OK ){ + sqlite3_result_error_code(pCtx, rc); + } +} +/* +** End of highlight() implementation. +**************************************************************************/ + +/* +** Implementation of snippet() function. +*/ +static void fts5SnippetFunction( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning result/error */ + int nVal, /* Number of values in apVal[] array */ + sqlite3_value **apVal /* Array of trailing arguments */ +){ + HighlightContext ctx; + int rc = SQLITE_OK; /* Return code */ + int iCol; /* 1st argument to snippet() */ + const char *zEllips; /* 4th argument to snippet() */ + int nToken; /* 5th argument to snippet() */ + int nInst = 0; /* Number of instance matches this row */ + int i; /* Used to iterate through instances */ + int nPhrase; /* Number of phrases in query */ + unsigned char *aSeen; /* Array of "seen instance" flags */ + int iBestCol; /* Column containing best snippet */ + int iBestStart = 0; /* First token of best snippet */ + int iBestLast; /* Last token of best snippet */ + int nBestScore = 0; /* Score of best snippet */ + int nColSize = 0; /* Total size of iBestCol in tokens */ + + if( nVal!=5 ){ + const char *zErr = "wrong number of arguments to function snippet()"; + sqlite3_result_error(pCtx, zErr, -1); + return; + } + + memset(&ctx, 0, sizeof(HighlightContext)); + iCol = sqlite3_value_int(apVal[0]); + ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); + ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); + zEllips = (const char*)sqlite3_value_text(apVal[3]); + nToken = sqlite3_value_int(apVal[4]); + iBestLast = nToken-1; + + iBestCol = (iCol>=0 ? iCol : 0); + nPhrase = pApi->xPhraseCount(pFts); + aSeen = sqlite3_malloc(nPhrase); + if( aSeen==0 ){ + rc = SQLITE_NOMEM; + } + + if( rc==SQLITE_OK ){ + rc = pApi->xInstCount(pFts, &nInst); + } + for(i=0; rc==SQLITE_OK && ixInst(pFts, i, &ip, &iSnippetCol, &iStart); + if( rc==SQLITE_OK && (iCol<0 || iSnippetCol==iCol) ){ + int nScore = 1000; + int iLast = iStart - 1 + pApi->xPhraseSize(pFts, ip); + int j; + aSeen[ip] = 1; + + for(j=i+1; rc==SQLITE_OK && jxInst(pFts, j, &ip, &ic, &io); + iFinal = io + pApi->xPhraseSize(pFts, ip) - 1; + if( rc==SQLITE_OK && ic==iSnippetCol && iLastiLast ) iLast = iFinal; + } + } + + if( rc==SQLITE_OK && nScore>nBestScore ){ + iBestCol = iSnippetCol; + iBestStart = iStart; + iBestLast = iLast; + nBestScore = nScore; + } + } + } + + if( rc==SQLITE_OK ){ + rc = pApi->xColumnSize(pFts, iBestCol, &nColSize); + } + if( rc==SQLITE_OK ){ + rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn); + } + if( ctx.zIn ){ + if( rc==SQLITE_OK ){ + rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter); + } + + if( (iBestStart+nToken-1)>iBestLast ){ + iBestStart -= (iBestStart+nToken-1-iBestLast) / 2; + } + if( iBestStart+nToken>nColSize ){ + iBestStart = nColSize - nToken; + } + if( iBestStart<0 ) iBestStart = 0; + + ctx.iRangeStart = iBestStart; + ctx.iRangeEnd = iBestStart + nToken - 1; + + if( iBestStart>0 ){ + fts5HighlightAppend(&rc, &ctx, zEllips, -1); + } + if( rc==SQLITE_OK ){ + rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); + } + if( ctx.iRangeEnd>=(nColSize-1) ){ + fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff); + }else{ + fts5HighlightAppend(&rc, &ctx, zEllips, -1); + } + + if( rc==SQLITE_OK ){ + sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT); + }else{ + sqlite3_result_error_code(pCtx, rc); + } + sqlite3_free(ctx.zOut); + } + sqlite3_free(aSeen); +} + +/************************************************************************/ + +/* +** The first time the bm25() function is called for a query, an instance +** of the following structure is allocated and populated. +*/ +typedef struct Fts5Bm25Data Fts5Bm25Data; +struct Fts5Bm25Data { + int nPhrase; /* Number of phrases in query */ + double avgdl; /* Average number of tokens in each row */ + double *aIDF; /* IDF for each phrase */ + double *aFreq; /* Array used to calculate phrase freq. */ +}; + +/* +** Callback used by fts5Bm25GetData() to count the number of rows in the +** table matched by each individual phrase within the query. +*/ +static int fts5CountCb( + const Fts5ExtensionApi *pApi, + Fts5Context *pFts, + void *pUserData /* Pointer to sqlite3_int64 variable */ +){ + sqlite3_int64 *pn = (sqlite3_int64*)pUserData; + UNUSED_PARAM2(pApi, pFts); + (*pn)++; + return SQLITE_OK; +} + +/* +** Set *ppData to point to the Fts5Bm25Data object for the current query. +** If the object has not already been allocated, allocate and populate it +** now. +*/ +static int fts5Bm25GetData( + const Fts5ExtensionApi *pApi, + Fts5Context *pFts, + Fts5Bm25Data **ppData /* OUT: bm25-data object for this query */ +){ + int rc = SQLITE_OK; /* Return code */ + Fts5Bm25Data *p; /* Object to return */ + + p = pApi->xGetAuxdata(pFts, 0); + if( p==0 ){ + int nPhrase; /* Number of phrases in query */ + sqlite3_int64 nRow = 0; /* Number of rows in table */ + sqlite3_int64 nToken = 0; /* Number of tokens in table */ + int nByte; /* Bytes of space to allocate */ + int i; + + /* Allocate the Fts5Bm25Data object */ + nPhrase = pApi->xPhraseCount(pFts); + nByte = sizeof(Fts5Bm25Data) + nPhrase*2*sizeof(double); + p = (Fts5Bm25Data*)sqlite3_malloc(nByte); + if( p==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(p, 0, nByte); + p->nPhrase = nPhrase; + p->aIDF = (double*)&p[1]; + p->aFreq = &p->aIDF[nPhrase]; + } + + /* Calculate the average document length for this FTS5 table */ + if( rc==SQLITE_OK ) rc = pApi->xRowCount(pFts, &nRow); + if( rc==SQLITE_OK ) rc = pApi->xColumnTotalSize(pFts, -1, &nToken); + if( rc==SQLITE_OK ) p->avgdl = (double)nToken / (double)nRow; + + /* Calculate an IDF for each phrase in the query */ + for(i=0; rc==SQLITE_OK && ixQueryPhrase(pFts, i, (void*)&nHit, fts5CountCb); + if( rc==SQLITE_OK ){ + /* Calculate the IDF (Inverse Document Frequency) for phrase i. + ** This is done using the standard BM25 formula as found on wikipedia: + ** + ** IDF = log( (N - nHit + 0.5) / (nHit + 0.5) ) + ** + ** where "N" is the total number of documents in the set and nHit + ** is the number that contain at least one instance of the phrase + ** under consideration. + ** + ** The problem with this is that if (N < 2*nHit), the 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) ); + if( idf<=0.0 ) idf = 1e-6; + p->aIDF[i] = idf; + } + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(p); + }else{ + rc = pApi->xSetAuxdata(pFts, p, sqlite3_free); + } + if( rc!=SQLITE_OK ) p = 0; + } + *ppData = p; + return rc; +} + +/* +** Implementation of bm25() function. +*/ +static void fts5Bm25Function( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning result/error */ + int nVal, /* Number of values in apVal[] array */ + sqlite3_value **apVal /* Array of trailing arguments */ +){ + const double k1 = 1.2; /* Constant "k1" from BM25 formula */ + const double b = 0.75; /* Constant "b" from BM25 formula */ + int rc = SQLITE_OK; /* Error code */ + double score = 0.0; /* SQL function return value */ + Fts5Bm25Data *pData; /* Values allocated/calculated once only */ + int i; /* Iterator variable */ + int nInst = 0; /* Value returned by xInstCount() */ + double D = 0.0; /* Total number of tokens in row */ + double *aFreq = 0; /* Array of phrase freq. for current row */ + + /* Calculate the phrase frequency (symbol "f(qi,D)" in the documentation) + ** for each phrase in the query for the current row. */ + rc = fts5Bm25GetData(pApi, pFts, &pData); + if( rc==SQLITE_OK ){ + aFreq = pData->aFreq; + memset(aFreq, 0, sizeof(double) * pData->nPhrase); + rc = pApi->xInstCount(pFts, &nInst); + } + for(i=0; rc==SQLITE_OK && ixInst(pFts, i, &ip, &ic, &io); + if( rc==SQLITE_OK ){ + double w = (nVal > ic) ? sqlite3_value_double(apVal[ic]) : 1.0; + aFreq[ip] += w; + } + } + + /* Figure out the total size of the current row in tokens. */ + if( rc==SQLITE_OK ){ + int nTok; + rc = pApi->xColumnSize(pFts, -1, &nTok); + D = (double)nTok; + } + + /* Determine the BM25 score for the current row. */ + for(i=0; rc==SQLITE_OK && inPhrase; i++){ + score += pData->aIDF[i] * ( + ( aFreq[i] * (k1 + 1.0) ) / + ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) ) + ); + } + + /* If no error has occurred, return the calculated score. Otherwise, + ** throw an SQL exception. */ + if( rc==SQLITE_OK ){ + sqlite3_result_double(pCtx, -1.0 * score); + }else{ + sqlite3_result_error_code(pCtx, rc); + } +} + +int sqlite3Fts5AuxInit(fts5_api *pApi){ + struct Builtin { + const char *zFunc; /* Function name (nul-terminated) */ + void *pUserData; /* User-data pointer */ + fts5_extension_function xFunc;/* Callback function */ + void (*xDestroy)(void*); /* Destructor function */ + } aBuiltin [] = { + { "snippet", 0, fts5SnippetFunction, 0 }, + { "highlight", 0, fts5HighlightFunction, 0 }, + { "bm25", 0, fts5Bm25Function, 0 }, + }; + int rc = SQLITE_OK; /* Return code */ + int i; /* To iterate through builtin functions */ + + for(i=0; rc==SQLITE_OK && ixCreateFunction(pApi, + aBuiltin[i].zFunc, + aBuiltin[i].pUserData, + aBuiltin[i].xFunc, + aBuiltin[i].xDestroy + ); + } + + return rc; +} + + diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c new file mode 100644 index 0000000..0098846 --- /dev/null +++ b/ext/fts5/fts5_buffer.c @@ -0,0 +1,392 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +*/ + + + +#include "fts5Int.h" + +int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){ + if( (u32)pBuf->nSpacenSpace ? pBuf->nSpace : 64; + u8 *pNew; + while( nNewp, nNew); + if( pNew==0 ){ + *pRc = SQLITE_NOMEM; + return 1; + }else{ + pBuf->nSpace = nNew; + pBuf->p = pNew; + } + } + return 0; +} + + +/* +** Encode value iVal as an SQLite varint and append it to the buffer object +** pBuf. If an OOM error occurs, set the error code in p. +*/ +void sqlite3Fts5BufferAppendVarint(int *pRc, Fts5Buffer *pBuf, i64 iVal){ + if( fts5BufferGrow(pRc, pBuf, 9) ) return; + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iVal); +} + +void sqlite3Fts5Put32(u8 *aBuf, int iVal){ + aBuf[0] = (iVal>>24) & 0x00FF; + aBuf[1] = (iVal>>16) & 0x00FF; + aBuf[2] = (iVal>> 8) & 0x00FF; + aBuf[3] = (iVal>> 0) & 0x00FF; +} + +int sqlite3Fts5Get32(const u8 *aBuf){ + return (aBuf[0] << 24) + (aBuf[1] << 16) + (aBuf[2] << 8) + aBuf[3]; +} + +/* +** Append buffer nData/pData to buffer pBuf. If an OOM error occurs, set +** the error code in p. If an error has already occurred when this function +** is called, it is a no-op. +*/ +void sqlite3Fts5BufferAppendBlob( + int *pRc, + Fts5Buffer *pBuf, + u32 nData, + const u8 *pData +){ + assert_nc( *pRc || nData>=0 ); + if( fts5BufferGrow(pRc, pBuf, nData) ) return; + memcpy(&pBuf->p[pBuf->n], pData, nData); + pBuf->n += nData; +} + +/* +** Append the nul-terminated string zStr to the buffer pBuf. This function +** ensures that the byte following the buffer data is set to 0x00, even +** though this byte is not included in the pBuf->n count. +*/ +void sqlite3Fts5BufferAppendString( + int *pRc, + Fts5Buffer *pBuf, + const char *zStr +){ + int nStr = (int)strlen(zStr); + sqlite3Fts5BufferAppendBlob(pRc, pBuf, nStr+1, (const u8*)zStr); + pBuf->n--; +} + +/* +** Argument zFmt is a printf() style format string. This function performs +** the printf() style processing, then appends the results to buffer pBuf. +** +** Like sqlite3Fts5BufferAppendString(), this function ensures that the byte +** following the buffer data is set to 0x00, even though this byte is not +** included in the pBuf->n count. +*/ +void sqlite3Fts5BufferAppendPrintf( + int *pRc, + Fts5Buffer *pBuf, + char *zFmt, ... +){ + if( *pRc==SQLITE_OK ){ + char *zTmp; + va_list ap; + va_start(ap, zFmt); + zTmp = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + + if( zTmp==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + sqlite3Fts5BufferAppendString(pRc, pBuf, zTmp); + sqlite3_free(zTmp); + } + } +} + +char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...){ + char *zRet = 0; + if( *pRc==SQLITE_OK ){ + va_list ap; + va_start(ap, zFmt); + zRet = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + if( zRet==0 ){ + *pRc = SQLITE_NOMEM; + } + } + return zRet; +} + + +/* +** Free any buffer allocated by pBuf. Zero the structure before returning. +*/ +void sqlite3Fts5BufferFree(Fts5Buffer *pBuf){ + sqlite3_free(pBuf->p); + memset(pBuf, 0, sizeof(Fts5Buffer)); +} + +/* +** Zero the contents of the buffer object. But do not free the associated +** memory allocation. +*/ +void sqlite3Fts5BufferZero(Fts5Buffer *pBuf){ + pBuf->n = 0; +} + +/* +** Set the buffer to contain nData/pData. If an OOM error occurs, leave an +** the error code in p. If an error has already occurred when this function +** is called, it is a no-op. +*/ +void sqlite3Fts5BufferSet( + int *pRc, + Fts5Buffer *pBuf, + int nData, + const u8 *pData +){ + pBuf->n = 0; + sqlite3Fts5BufferAppendBlob(pRc, pBuf, nData, pData); +} + +int sqlite3Fts5PoslistNext64( + const u8 *a, int n, /* Buffer containing poslist */ + int *pi, /* IN/OUT: Offset within a[] */ + i64 *piOff /* IN/OUT: Current offset */ +){ + int i = *pi; + if( i>=n ){ + /* EOF */ + *piOff = -1; + return 1; + }else{ + i64 iOff = *piOff; + int iVal; + fts5FastGetVarint32(a, i, iVal); + if( iVal==1 ){ + fts5FastGetVarint32(a, i, iVal); + iOff = ((i64)iVal) << 32; + fts5FastGetVarint32(a, i, iVal); + } + *piOff = iOff + (iVal-2); + *pi = i; + return 0; + } +} + + +/* +** Advance the iterator object passed as the only argument. Return true +** if the iterator reaches EOF, or false otherwise. +*/ +int sqlite3Fts5PoslistReaderNext(Fts5PoslistReader *pIter){ + if( sqlite3Fts5PoslistNext64(pIter->a, pIter->n, &pIter->i, &pIter->iPos) ){ + pIter->bEof = 1; + } + return pIter->bEof; +} + +int sqlite3Fts5PoslistReaderInit( + const u8 *a, int n, /* Poslist buffer to iterate through */ + Fts5PoslistReader *pIter /* Iterator object to initialize */ +){ + memset(pIter, 0, sizeof(*pIter)); + pIter->a = a; + pIter->n = n; + sqlite3Fts5PoslistReaderNext(pIter); + return pIter->bEof; +} + +/* +** Append position iPos to the position list being accumulated in buffer +** pBuf, which must be already be large enough to hold the new data. +** The previous position written to this list is *piPrev. *piPrev is set +** to iPos before returning. +*/ +void sqlite3Fts5PoslistSafeAppend( + Fts5Buffer *pBuf, + i64 *piPrev, + i64 iPos +){ + static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32; + if( (iPos & colmask) != (*piPrev & colmask) ){ + pBuf->p[pBuf->n++] = 1; + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32)); + *piPrev = (iPos & colmask); + } + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2); + *piPrev = iPos; +} + +int sqlite3Fts5PoslistWriterAppend( + Fts5Buffer *pBuf, + Fts5PoslistWriter *pWriter, + i64 iPos +){ + int rc = 0; /* Initialized only to suppress erroneous warning from Clang */ + if( fts5BufferGrow(&rc, pBuf, 5+5+5) ) return rc; + sqlite3Fts5PoslistSafeAppend(pBuf, &pWriter->iPrev, iPos); + return SQLITE_OK; +} + +void *sqlite3Fts5MallocZero(int *pRc, int nByte){ + void *pRet = 0; + if( *pRc==SQLITE_OK ){ + pRet = sqlite3_malloc(nByte); + if( pRet==0 && nByte>0 ){ + *pRc = SQLITE_NOMEM; + }else{ + memset(pRet, 0, nByte); + } + } + return pRet; +} + +/* +** Return a nul-terminated copy of the string indicated by pIn. If nIn +** is non-negative, then it is the length of the string in bytes. Otherwise, +** the length of the string is determined using strlen(). +** +** It is the responsibility of the caller to eventually free the returned +** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned. +*/ +char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){ + char *zRet = 0; + if( *pRc==SQLITE_OK ){ + if( nIn<0 ){ + nIn = (int)strlen(pIn); + } + zRet = (char*)sqlite3_malloc(nIn+1); + if( zRet ){ + memcpy(zRet, pIn, nIn); + zRet[nIn] = '\0'; + }else{ + *pRc = SQLITE_NOMEM; + } + } + return zRet; +} + + +/* +** Return true if character 't' may be part of an FTS5 bareword, or false +** otherwise. Characters that may be part of barewords: +** +** * All non-ASCII characters, +** * The 52 upper and lower case ASCII characters, and +** * The 10 integer ASCII characters. +** * The underscore character "_" (0x5F). +** * The unicode "subsitute" character (0x1A). +*/ +int sqlite3Fts5IsBareword(char t){ + u8 aBareword[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 .. 0x0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 0x10 .. 0x1F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 .. 0x2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30 .. 0x3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 .. 0x4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50 .. 0x5F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 .. 0x6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /* 0x70 .. 0x7F */ + }; + + return (t & 0x80) || aBareword[(int)t]; +} + + +/************************************************************************* +*/ +typedef struct Fts5TermsetEntry Fts5TermsetEntry; +struct Fts5TermsetEntry { + char *pTerm; + int nTerm; + int iIdx; /* Index (main or aPrefix[] entry) */ + Fts5TermsetEntry *pNext; +}; + +struct Fts5Termset { + Fts5TermsetEntry *apHash[512]; +}; + +int sqlite3Fts5TermsetNew(Fts5Termset **pp){ + int rc = SQLITE_OK; + *pp = sqlite3Fts5MallocZero(&rc, sizeof(Fts5Termset)); + return rc; +} + +int sqlite3Fts5TermsetAdd( + Fts5Termset *p, + int iIdx, + const char *pTerm, int nTerm, + int *pbPresent +){ + int rc = SQLITE_OK; + *pbPresent = 0; + if( p ){ + int i; + u32 hash = 13; + Fts5TermsetEntry *pEntry; + + /* Calculate a hash value for this term. This is the same hash checksum + ** used by the fts5_hash.c module. This is not important for correct + ** operation of the module, but is necessary to ensure that some tests + ** designed to produce hash table collisions really do work. */ + for(i=nTerm-1; i>=0; i--){ + hash = (hash << 3) ^ hash ^ pTerm[i]; + } + hash = (hash << 3) ^ hash ^ iIdx; + hash = hash % ArraySize(p->apHash); + + for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){ + if( pEntry->iIdx==iIdx + && pEntry->nTerm==nTerm + && memcmp(pEntry->pTerm, pTerm, nTerm)==0 + ){ + *pbPresent = 1; + break; + } + } + + if( pEntry==0 ){ + pEntry = sqlite3Fts5MallocZero(&rc, sizeof(Fts5TermsetEntry) + nTerm); + if( pEntry ){ + pEntry->pTerm = (char*)&pEntry[1]; + pEntry->nTerm = nTerm; + pEntry->iIdx = iIdx; + memcpy(pEntry->pTerm, pTerm, nTerm); + pEntry->pNext = p->apHash[hash]; + p->apHash[hash] = pEntry; + } + } + } + + return rc; +} + +void sqlite3Fts5TermsetFree(Fts5Termset *p){ + if( p ){ + u32 i; + for(i=0; iapHash); i++){ + Fts5TermsetEntry *pEntry = p->apHash[i]; + while( pEntry ){ + Fts5TermsetEntry *pDel = pEntry; + pEntry = pEntry->pNext; + sqlite3_free(pDel); + } + } + sqlite3_free(p); + } +} diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c new file mode 100644 index 0000000..f49cede --- /dev/null +++ b/ext/fts5/fts5_config.c @@ -0,0 +1,945 @@ +/* +** 2014 Jun 09 +** +** 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 is an SQLite module implementing full-text search. +*/ + + +#include "fts5Int.h" + +#define FTS5_DEFAULT_PAGE_SIZE 4050 +#define FTS5_DEFAULT_AUTOMERGE 4 +#define FTS5_DEFAULT_CRISISMERGE 16 +#define FTS5_DEFAULT_HASHSIZE (1024*1024) + +/* Maximum allowed page size */ +#define FTS5_MAX_PAGE_SIZE (128*1024) + +static int fts5_iswhitespace(char x){ + return (x==' '); +} + +static int fts5_isopenquote(char x){ + return (x=='"' || x=='\'' || x=='[' || x=='`'); +} + +/* +** Argument pIn points to a character that is part of a nul-terminated +** string. Return a pointer to the first character following *pIn in +** the string that is not a white-space character. +*/ +static const char *fts5ConfigSkipWhitespace(const char *pIn){ + const char *p = pIn; + if( p ){ + while( fts5_iswhitespace(*p) ){ p++; } + } + return p; +} + +/* +** Argument pIn points to a character that is part of a nul-terminated +** string. Return a pointer to the first character following *pIn in +** the string that is not a "bareword" character. +*/ +static const char *fts5ConfigSkipBareword(const char *pIn){ + const char *p = pIn; + while ( sqlite3Fts5IsBareword(*p) ) p++; + if( p==pIn ) p = 0; + return p; +} + +static int fts5_isdigit(char a){ + return (a>='0' && a<='9'); +} + + + +static const char *fts5ConfigSkipLiteral(const char *pIn){ + const char *p = pIn; + switch( *p ){ + case 'n': case 'N': + if( sqlite3_strnicmp("null", p, 4)==0 ){ + p = &p[4]; + }else{ + p = 0; + } + break; + + case 'x': case 'X': + p++; + if( *p=='\'' ){ + p++; + while( (*p>='a' && *p<='f') + || (*p>='A' && *p<='F') + || (*p>='0' && *p<='9') + ){ + p++; + } + if( *p=='\'' && 0==((p-pIn)%2) ){ + p++; + }else{ + p = 0; + } + }else{ + p = 0; + } + break; + + case '\'': + p++; + while( p ){ + if( *p=='\'' ){ + p++; + if( *p!='\'' ) break; + } + p++; + if( *p==0 ) p = 0; + } + break; + + default: + /* maybe a number */ + if( *p=='+' || *p=='-' ) p++; + while( fts5_isdigit(*p) ) p++; + + /* At this point, if the literal was an integer, the parse is + ** finished. Or, if it is a floating point value, it may continue + ** with either a decimal point or an 'E' character. */ + if( *p=='.' && fts5_isdigit(p[1]) ){ + p += 2; + while( fts5_isdigit(*p) ) p++; + } + if( p==pIn ) p = 0; + + break; + } + + return p; +} + +/* +** The first character of the string pointed to by argument z is guaranteed +** to be an open-quote character (see function fts5_isopenquote()). +** +** This function searches for the corresponding close-quote character within +** the string and, if found, dequotes the string in place and adds a new +** nul-terminator byte. +** +** If the close-quote is found, the value returned is the byte offset of +** the character immediately following it. Or, if the close-quote is not +** found, -1 is returned. If -1 is returned, the buffer is left in an +** undefined state. +*/ +static int fts5Dequote(char *z){ + char q; + int iIn = 1; + int iOut = 0; + q = z[0]; + + /* Set stack variable q to the close-quote character */ + assert( q=='[' || q=='\'' || q=='"' || q=='`' ); + if( q=='[' ) q = ']'; + + while( ALWAYS(z[iIn]) ){ + if( z[iIn]==q ){ + if( z[iIn+1]!=q ){ + /* Character iIn was the close quote. */ + iIn++; + break; + }else{ + /* Character iIn and iIn+1 form an escaped quote character. Skip + ** the input cursor past both and copy a single quote character + ** to the output buffer. */ + iIn += 2; + z[iOut++] = q; + } + }else{ + z[iOut++] = z[iIn++]; + } + } + + z[iOut] = '\0'; + return iIn; +} + +/* +** Convert an SQL-style quoted string into a normal string by removing +** the quote characters. The conversion is done in-place. If the +** input does not begin with a quote character, then this routine +** is a no-op. +** +** Examples: +** +** "abc" becomes abc +** 'xyz' becomes xyz +** [pqr] becomes pqr +** `mno` becomes mno +*/ +void sqlite3Fts5Dequote(char *z){ + char quote; /* Quote character (if any ) */ + + assert( 0==fts5_iswhitespace(z[0]) ); + quote = z[0]; + if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){ + fts5Dequote(z); + } +} + + +struct Fts5Enum { + const char *zName; + int eVal; +}; +typedef struct Fts5Enum Fts5Enum; + +static int fts5ConfigSetEnum( + const Fts5Enum *aEnum, + const char *zEnum, + int *peVal +){ + int nEnum = (int)strlen(zEnum); + int i; + int iVal = -1; + + for(i=0; aEnum[i].zName; i++){ + if( sqlite3_strnicmp(aEnum[i].zName, zEnum, nEnum)==0 ){ + if( iVal>=0 ) return SQLITE_ERROR; + iVal = aEnum[i].eVal; + } + } + + *peVal = iVal; + return iVal<0 ? SQLITE_ERROR : SQLITE_OK; +} + +/* +** Parse a "special" CREATE VIRTUAL TABLE directive and update +** configuration object pConfig as appropriate. +** +** If successful, object pConfig is updated and SQLITE_OK returned. If +** an error occurs, an SQLite error code is returned and an error message +** may be left in *pzErr. It is the responsibility of the caller to +** eventually free any such error message using sqlite3_free(). +*/ +static int fts5ConfigParseSpecial( + Fts5Global *pGlobal, + Fts5Config *pConfig, /* Configuration object to update */ + const char *zCmd, /* Special command to parse */ + const char *zArg, /* Argument to parse */ + char **pzErr /* OUT: Error message */ +){ + int rc = SQLITE_OK; + int nCmd = (int)strlen(zCmd); + if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){ + const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES; + const char *p; + int bFirst = 1; + if( pConfig->aPrefix==0 ){ + pConfig->aPrefix = sqlite3Fts5MallocZero(&rc, nByte); + if( rc ) return rc; + } + + p = zArg; + while( 1 ){ + int nPre = 0; + + while( p[0]==' ' ) p++; + if( bFirst==0 && p[0]==',' ){ + p++; + while( p[0]==' ' ) p++; + }else if( p[0]=='\0' ){ + break; + } + if( p[0]<'0' || p[0]>'9' ){ + *pzErr = sqlite3_mprintf("malformed prefix=... directive"); + rc = SQLITE_ERROR; + break; + } + + if( pConfig->nPrefix==FTS5_MAX_PREFIX_INDEXES ){ + *pzErr = sqlite3_mprintf( + "too many prefix indexes (max %d)", FTS5_MAX_PREFIX_INDEXES + ); + rc = SQLITE_ERROR; + break; + } + + while( p[0]>='0' && p[0]<='9' && nPre<1000 ){ + nPre = nPre*10 + (p[0] - '0'); + p++; + } + + if( nPre<=0 || nPre>=1000 ){ + *pzErr = sqlite3_mprintf("prefix length out of range (max 999)"); + rc = SQLITE_ERROR; + break; + } + + pConfig->aPrefix[pConfig->nPrefix] = nPre; + pConfig->nPrefix++; + bFirst = 0; + } + assert( pConfig->nPrefix<=FTS5_MAX_PREFIX_INDEXES ); + return rc; + } + + if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){ + const char *p = (const char*)zArg; + int nArg = (int)strlen(zArg) + 1; + char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg); + char *pDel = sqlite3Fts5MallocZero(&rc, nArg * 2); + char *pSpace = pDel; + + if( azArg && pSpace ){ + if( pConfig->pTok ){ + *pzErr = sqlite3_mprintf("multiple tokenize=... directives"); + rc = SQLITE_ERROR; + }else{ + for(nArg=0; p && *p; nArg++){ + const char *p2 = fts5ConfigSkipWhitespace(p); + if( *p2=='\'' ){ + p = fts5ConfigSkipLiteral(p2); + }else{ + p = fts5ConfigSkipBareword(p2); + } + if( p ){ + memcpy(pSpace, p2, p-p2); + azArg[nArg] = pSpace; + sqlite3Fts5Dequote(pSpace); + pSpace += (p - p2) + 1; + p = fts5ConfigSkipWhitespace(p); + } + } + if( p==0 ){ + *pzErr = sqlite3_mprintf("parse error in tokenize directive"); + rc = SQLITE_ERROR; + }else{ + rc = sqlite3Fts5GetTokenizer(pGlobal, + (const char**)azArg, nArg, &pConfig->pTok, &pConfig->pTokApi, + pzErr + ); + } + } + } + + sqlite3_free(azArg); + sqlite3_free(pDel); + return rc; + } + + if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){ + if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){ + *pzErr = sqlite3_mprintf("multiple content=... directives"); + rc = SQLITE_ERROR; + }else{ + if( zArg[0] ){ + pConfig->eContent = FTS5_CONTENT_EXTERNAL; + pConfig->zContent = sqlite3Fts5Mprintf(&rc, "%Q.%Q", pConfig->zDb,zArg); + }else{ + pConfig->eContent = FTS5_CONTENT_NONE; + } + } + return rc; + } + + if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){ + if( pConfig->zContentRowid ){ + *pzErr = sqlite3_mprintf("multiple content_rowid=... directives"); + rc = SQLITE_ERROR; + }else{ + pConfig->zContentRowid = sqlite3Fts5Strndup(&rc, zArg, -1); + } + return rc; + } + + if( sqlite3_strnicmp("columnsize", zCmd, nCmd)==0 ){ + if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){ + *pzErr = sqlite3_mprintf("malformed columnsize=... directive"); + rc = SQLITE_ERROR; + }else{ + pConfig->bColumnsize = (zArg[0]=='1'); + } + return rc; + } + + if( sqlite3_strnicmp("detail", zCmd, nCmd)==0 ){ + const Fts5Enum aDetail[] = { + { "none", FTS5_DETAIL_NONE }, + { "full", FTS5_DETAIL_FULL }, + { "columns", FTS5_DETAIL_COLUMNS }, + { 0, 0 } + }; + + if( (rc = fts5ConfigSetEnum(aDetail, zArg, &pConfig->eDetail)) ){ + *pzErr = sqlite3_mprintf("malformed detail=... directive"); + } + return rc; + } + + *pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd); + return SQLITE_ERROR; +} + +/* +** Allocate an instance of the default tokenizer ("simple") at +** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error +** code if an error occurs. +*/ +static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){ + assert( pConfig->pTok==0 && pConfig->pTokApi==0 ); + return sqlite3Fts5GetTokenizer( + pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0 + ); +} + +/* +** Gobble up the first bareword or quoted word from the input buffer zIn. +** Return a pointer to the character immediately following the last in +** the gobbled word if successful, or a NULL pointer otherwise (failed +** to find close-quote character). +** +** Before returning, set pzOut to point to a new buffer containing a +** nul-terminated, dequoted copy of the gobbled word. If the word was +** quoted, *pbQuoted is also set to 1 before returning. +** +** If *pRc is other than SQLITE_OK when this function is called, it is +** a no-op (NULL is returned). Otherwise, if an OOM occurs within this +** function, *pRc is set to SQLITE_NOMEM before returning. *pRc is *not* +** set if a parse error (failed to find close quote) occurs. +*/ +static const char *fts5ConfigGobbleWord( + int *pRc, /* IN/OUT: Error code */ + const char *zIn, /* Buffer to gobble string/bareword from */ + char **pzOut, /* OUT: malloc'd buffer containing str/bw */ + int *pbQuoted /* OUT: Set to true if dequoting required */ +){ + const char *zRet = 0; + + int nIn = (int)strlen(zIn); + char *zOut = sqlite3_malloc(nIn+1); + + assert( *pRc==SQLITE_OK ); + *pbQuoted = 0; + *pzOut = 0; + + if( zOut==0 ){ + *pRc = SQLITE_NOMEM; + }else{ + memcpy(zOut, zIn, nIn+1); + if( fts5_isopenquote(zOut[0]) ){ + int ii = fts5Dequote(zOut); + zRet = &zIn[ii]; + *pbQuoted = 1; + }else{ + zRet = fts5ConfigSkipBareword(zIn); + zOut[zRet-zIn] = '\0'; + } + } + + if( zRet==0 ){ + sqlite3_free(zOut); + }else{ + *pzOut = zOut; + } + + return zRet; +} + +static int fts5ConfigParseColumn( + Fts5Config *p, + char *zCol, + char *zArg, + char **pzErr +){ + int rc = SQLITE_OK; + if( 0==sqlite3_stricmp(zCol, FTS5_RANK_NAME) + || 0==sqlite3_stricmp(zCol, FTS5_ROWID_NAME) + ){ + *pzErr = sqlite3_mprintf("reserved fts5 column name: %s", zCol); + rc = SQLITE_ERROR; + }else if( zArg ){ + if( 0==sqlite3_stricmp(zArg, "unindexed") ){ + p->abUnindexed[p->nCol] = 1; + }else{ + *pzErr = sqlite3_mprintf("unrecognized column option: %s", zArg); + rc = SQLITE_ERROR; + } + } + + p->azCol[p->nCol++] = zCol; + return rc; +} + +/* +** Populate the Fts5Config.zContentExprlist string. +*/ +static int fts5ConfigMakeExprlist(Fts5Config *p){ + int i; + int rc = SQLITE_OK; + Fts5Buffer buf = {0, 0, 0}; + + sqlite3Fts5BufferAppendPrintf(&rc, &buf, "T.%Q", p->zContentRowid); + if( p->eContent!=FTS5_CONTENT_NONE ){ + for(i=0; inCol; i++){ + if( p->eContent==FTS5_CONTENT_EXTERNAL ){ + sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.%Q", p->azCol[i]); + }else{ + sqlite3Fts5BufferAppendPrintf(&rc, &buf, ", T.c%d", i); + } + } + } + + assert( p->zContentExprlist==0 ); + p->zContentExprlist = (char*)buf.p; + return rc; +} + +/* +** Arguments nArg/azArg contain the string arguments passed to the xCreate +** or xConnect method of the virtual table. This function attempts to +** allocate an instance of Fts5Config containing the results of parsing +** those arguments. +** +** If successful, SQLITE_OK is returned and *ppOut is set to point to the +** new Fts5Config object. If an error occurs, an SQLite error code is +** returned, *ppOut is set to NULL and an error message may be left in +** *pzErr. It is the responsibility of the caller to eventually free any +** such error message using sqlite3_free(). +*/ +int sqlite3Fts5ConfigParse( + Fts5Global *pGlobal, + sqlite3 *db, + int nArg, /* Number of arguments */ + const char **azArg, /* Array of nArg CREATE VIRTUAL TABLE args */ + Fts5Config **ppOut, /* OUT: Results of parse */ + char **pzErr /* OUT: Error message */ +){ + int rc = SQLITE_OK; /* Return code */ + Fts5Config *pRet; /* New object to return */ + int i; + int nByte; + + *ppOut = pRet = (Fts5Config*)sqlite3_malloc(sizeof(Fts5Config)); + if( pRet==0 ) return SQLITE_NOMEM; + memset(pRet, 0, sizeof(Fts5Config)); + pRet->db = db; + pRet->iCookie = -1; + + nByte = nArg * (sizeof(char*) + sizeof(u8)); + pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte); + pRet->abUnindexed = (u8*)&pRet->azCol[nArg]; + pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1); + pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1); + pRet->bColumnsize = 1; + pRet->eDetail = FTS5_DETAIL_FULL; +#ifdef SQLITE_DEBUG + pRet->bPrefixIndex = 1; +#endif + if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){ + *pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName); + rc = SQLITE_ERROR; + } + + for(i=3; rc==SQLITE_OK && ipTok==0 ){ + rc = fts5ConfigDefaultTokenizer(pGlobal, pRet); + } + + /* If no zContent option was specified, fill in the default values. */ + if( rc==SQLITE_OK && pRet->zContent==0 ){ + const char *zTail = 0; + assert( pRet->eContent==FTS5_CONTENT_NORMAL + || pRet->eContent==FTS5_CONTENT_NONE + ); + if( pRet->eContent==FTS5_CONTENT_NORMAL ){ + zTail = "content"; + }else if( pRet->bColumnsize ){ + zTail = "docsize"; + } + + if( zTail ){ + pRet->zContent = sqlite3Fts5Mprintf( + &rc, "%Q.'%q_%s'", pRet->zDb, pRet->zName, zTail + ); + } + } + + if( rc==SQLITE_OK && pRet->zContentRowid==0 ){ + pRet->zContentRowid = sqlite3Fts5Strndup(&rc, "rowid", -1); + } + + /* Formulate the zContentExprlist text */ + if( rc==SQLITE_OK ){ + rc = fts5ConfigMakeExprlist(pRet); + } + + if( rc!=SQLITE_OK ){ + sqlite3Fts5ConfigFree(pRet); + *ppOut = 0; + } + return rc; +} + +/* +** Free the configuration object passed as the only argument. +*/ +void sqlite3Fts5ConfigFree(Fts5Config *pConfig){ + if( pConfig ){ + int i; + if( pConfig->pTok ){ + pConfig->pTokApi->xDelete(pConfig->pTok); + } + sqlite3_free(pConfig->zDb); + sqlite3_free(pConfig->zName); + for(i=0; inCol; i++){ + sqlite3_free(pConfig->azCol[i]); + } + sqlite3_free(pConfig->azCol); + sqlite3_free(pConfig->aPrefix); + sqlite3_free(pConfig->zRank); + sqlite3_free(pConfig->zRankArgs); + sqlite3_free(pConfig->zContent); + sqlite3_free(pConfig->zContentRowid); + sqlite3_free(pConfig->zContentExprlist); + sqlite3_free(pConfig); + } +} + +/* +** Call sqlite3_declare_vtab() based on the contents of the configuration +** object passed as the only argument. Return SQLITE_OK if successful, or +** an SQLite error code if an error occurs. +*/ +int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig){ + int i; + int rc = SQLITE_OK; + char *zSql; + + zSql = sqlite3Fts5Mprintf(&rc, "CREATE TABLE x("); + for(i=0; zSql && inCol; i++){ + const char *zSep = (i==0?"":", "); + zSql = sqlite3Fts5Mprintf(&rc, "%z%s%Q", zSql, zSep, pConfig->azCol[i]); + } + zSql = sqlite3Fts5Mprintf(&rc, "%z, %Q HIDDEN, %s HIDDEN)", + zSql, pConfig->zName, FTS5_RANK_NAME + ); + + assert( zSql || rc==SQLITE_NOMEM ); + if( zSql ){ + rc = sqlite3_declare_vtab(pConfig->db, zSql); + sqlite3_free(zSql); + } + + return rc; +} + +/* +** Tokenize the text passed via the second and third arguments. +** +** The callback is invoked once for each token in the input text. The +** arguments passed to it are, in order: +** +** void *pCtx // Copy of 4th argument to sqlite3Fts5Tokenize() +** const char *pToken // Pointer to buffer containing token +** int nToken // Size of token in bytes +** int iStart // Byte offset of start of token within input text +** int iEnd // Byte offset of end of token within input text +** int iPos // Position of token in input (first token is 0) +** +** If the callback returns a non-zero value the tokenization is abandoned +** and no further callbacks are issued. +** +** This function returns SQLITE_OK if successful or an SQLite error code +** if an error occurs. If the tokenization was abandoned early because +** the callback returned SQLITE_DONE, this is not an error and this function +** still returns SQLITE_OK. Or, if the tokenization was abandoned early +** because the callback returned another non-zero value, it is assumed +** to be an SQLite error code and returned to the caller. +*/ +int sqlite3Fts5Tokenize( + Fts5Config *pConfig, /* FTS5 Configuration object */ + int flags, /* FTS5_TOKENIZE_* flags */ + const char *pText, int nText, /* Text to tokenize */ + void *pCtx, /* Context passed to xToken() */ + int (*xToken)(void*, int, const char*, int, int, int) /* Callback */ +){ + if( pText==0 ) return SQLITE_OK; + return pConfig->pTokApi->xTokenize( + pConfig->pTok, pCtx, flags, pText, nText, xToken + ); +} + +/* +** Argument pIn points to the first character in what is expected to be +** a comma-separated list of SQL literals followed by a ')' character. +** If it actually is this, return a pointer to the ')'. Otherwise, return +** NULL to indicate a parse error. +*/ +static const char *fts5ConfigSkipArgs(const char *pIn){ + const char *p = pIn; + + while( 1 ){ + p = fts5ConfigSkipWhitespace(p); + p = fts5ConfigSkipLiteral(p); + p = fts5ConfigSkipWhitespace(p); + if( p==0 || *p==')' ) break; + if( *p!=',' ){ + p = 0; + break; + } + p++; + } + + return p; +} + +/* +** Parameter zIn contains a rank() function specification. The format of +** this is: +** +** + Bareword (function name) +** + Open parenthesis - "(" +** + Zero or more SQL literals in a comma separated list +** + Close parenthesis - ")" +*/ +int sqlite3Fts5ConfigParseRank( + const char *zIn, /* Input string */ + char **pzRank, /* OUT: Rank function name */ + char **pzRankArgs /* OUT: Rank function arguments */ +){ + const char *p = zIn; + const char *pRank; + char *zRank = 0; + char *zRankArgs = 0; + int rc = SQLITE_OK; + + *pzRank = 0; + *pzRankArgs = 0; + + if( p==0 ){ + rc = SQLITE_ERROR; + }else{ + p = fts5ConfigSkipWhitespace(p); + pRank = p; + p = fts5ConfigSkipBareword(p); + + if( p ){ + zRank = sqlite3Fts5MallocZero(&rc, 1 + p - pRank); + if( zRank ) memcpy(zRank, pRank, p-pRank); + }else{ + rc = SQLITE_ERROR; + } + + if( rc==SQLITE_OK ){ + p = fts5ConfigSkipWhitespace(p); + if( *p!='(' ) rc = SQLITE_ERROR; + p++; + } + if( rc==SQLITE_OK ){ + const char *pArgs; + p = fts5ConfigSkipWhitespace(p); + pArgs = p; + if( *p!=')' ){ + p = fts5ConfigSkipArgs(p); + if( p==0 ){ + rc = SQLITE_ERROR; + }else{ + zRankArgs = sqlite3Fts5MallocZero(&rc, 1 + p - pArgs); + if( zRankArgs ) memcpy(zRankArgs, pArgs, p-pArgs); + } + } + } + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(zRank); + assert( zRankArgs==0 ); + }else{ + *pzRank = zRank; + *pzRankArgs = zRankArgs; + } + return rc; +} + +int sqlite3Fts5ConfigSetValue( + Fts5Config *pConfig, + const char *zKey, + sqlite3_value *pVal, + int *pbBadkey +){ + int rc = SQLITE_OK; + + if( 0==sqlite3_stricmp(zKey, "pgsz") ){ + int pgsz = 0; + if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ + pgsz = sqlite3_value_int(pVal); + } + if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){ + *pbBadkey = 1; + }else{ + pConfig->pgsz = pgsz; + } + } + + else if( 0==sqlite3_stricmp(zKey, "hashsize") ){ + int nHashSize = -1; + if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ + nHashSize = sqlite3_value_int(pVal); + } + if( nHashSize<=0 ){ + *pbBadkey = 1; + }else{ + pConfig->nHashSize = nHashSize; + } + } + + else if( 0==sqlite3_stricmp(zKey, "automerge") ){ + int nAutomerge = -1; + if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ + nAutomerge = sqlite3_value_int(pVal); + } + if( nAutomerge<0 || nAutomerge>64 ){ + *pbBadkey = 1; + }else{ + if( nAutomerge==1 ) nAutomerge = FTS5_DEFAULT_AUTOMERGE; + pConfig->nAutomerge = nAutomerge; + } + } + + else if( 0==sqlite3_stricmp(zKey, "crisismerge") ){ + int nCrisisMerge = -1; + if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){ + nCrisisMerge = sqlite3_value_int(pVal); + } + if( nCrisisMerge<0 ){ + *pbBadkey = 1; + }else{ + if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE; + pConfig->nCrisisMerge = nCrisisMerge; + } + } + + else if( 0==sqlite3_stricmp(zKey, "rank") ){ + const char *zIn = (const char*)sqlite3_value_text(pVal); + char *zRank; + char *zRankArgs; + rc = sqlite3Fts5ConfigParseRank(zIn, &zRank, &zRankArgs); + if( rc==SQLITE_OK ){ + sqlite3_free(pConfig->zRank); + sqlite3_free(pConfig->zRankArgs); + pConfig->zRank = zRank; + pConfig->zRankArgs = zRankArgs; + }else if( rc==SQLITE_ERROR ){ + rc = SQLITE_OK; + *pbBadkey = 1; + } + }else{ + *pbBadkey = 1; + } + return rc; +} + +/* +** Load the contents of the %_config table into memory. +*/ +int sqlite3Fts5ConfigLoad(Fts5Config *pConfig, int iCookie){ + const char *zSelect = "SELECT k, v FROM %Q.'%q_config'"; + char *zSql; + sqlite3_stmt *p = 0; + int rc = SQLITE_OK; + int iVersion = 0; + + /* Set default values */ + pConfig->pgsz = FTS5_DEFAULT_PAGE_SIZE; + pConfig->nAutomerge = FTS5_DEFAULT_AUTOMERGE; + pConfig->nCrisisMerge = FTS5_DEFAULT_CRISISMERGE; + pConfig->nHashSize = FTS5_DEFAULT_HASHSIZE; + + zSql = sqlite3Fts5Mprintf(&rc, zSelect, pConfig->zDb, pConfig->zName); + if( zSql ){ + rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p, 0); + sqlite3_free(zSql); + } + + assert( rc==SQLITE_OK || p==0 ); + if( rc==SQLITE_OK ){ + while( SQLITE_ROW==sqlite3_step(p) ){ + const char *zK = (const char*)sqlite3_column_text(p, 0); + sqlite3_value *pVal = sqlite3_column_value(p, 1); + if( 0==sqlite3_stricmp(zK, "version") ){ + iVersion = sqlite3_value_int(pVal); + }else{ + int bDummy = 0; + sqlite3Fts5ConfigSetValue(pConfig, zK, pVal, &bDummy); + } + } + rc = sqlite3_finalize(p); + } + + if( rc==SQLITE_OK && iVersion!=FTS5_CURRENT_VERSION ){ + rc = SQLITE_ERROR; + if( pConfig->pzErrmsg ){ + assert( 0==*pConfig->pzErrmsg ); + *pConfig->pzErrmsg = sqlite3_mprintf( + "invalid fts5 file format (found %d, expected %d) - run 'rebuild'", + iVersion, FTS5_CURRENT_VERSION + ); + } + } + + if( rc==SQLITE_OK ){ + pConfig->iCookie = iCookie; + } + return rc; +} diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c new file mode 100644 index 0000000..d3f801b --- /dev/null +++ b/ext/fts5/fts5_expr.c @@ -0,0 +1,2560 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +** +*/ + + + +#include "fts5Int.h" +#include "fts5parse.h" + +/* +** All token types in the generated fts5parse.h file are greater than 0. +*/ +#define FTS5_EOF 0 + +#define FTS5_LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) + +typedef struct Fts5ExprTerm Fts5ExprTerm; + +/* +** Functions generated by lemon from fts5parse.y. +*/ +void *sqlite3Fts5ParserAlloc(void *(*mallocProc)(u64)); +void sqlite3Fts5ParserFree(void*, void (*freeProc)(void*)); +void sqlite3Fts5Parser(void*, int, Fts5Token, Fts5Parse*); +#ifndef NDEBUG +#include +void sqlite3Fts5ParserTrace(FILE*, char*); +#endif + + +struct Fts5Expr { + Fts5Index *pIndex; + Fts5Config *pConfig; + Fts5ExprNode *pRoot; + int bDesc; /* Iterate in descending rowid order */ + int nPhrase; /* Number of phrases in expression */ + Fts5ExprPhrase **apExprPhrase; /* Pointers to phrase objects */ +}; + +/* +** eType: +** Expression node type. Always one of: +** +** FTS5_AND (nChild, apChild valid) +** FTS5_OR (nChild, apChild valid) +** FTS5_NOT (nChild, apChild valid) +** FTS5_STRING (pNear valid) +** FTS5_TERM (pNear valid) +*/ +struct Fts5ExprNode { + int eType; /* Node type */ + int bEof; /* True at EOF */ + int bNomatch; /* True if entry is not a match */ + + /* Next method for this node. */ + int (*xNext)(Fts5Expr*, Fts5ExprNode*, int, i64); + + i64 iRowid; /* Current rowid */ + Fts5ExprNearset *pNear; /* For FTS5_STRING - cluster of phrases */ + + /* 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[1]; /* Array of child nodes */ +}; + +#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING) + +/* +** Invoke the xNext method of an Fts5ExprNode object. This macro should be +** used as if it has the same signature as the xNext() methods themselves. +*/ +#define fts5ExprNodeNext(a,b,c,d) (b)->xNext((a), (b), (c), (d)) + +/* +** An instance of the following structure represents a single search term +** or term prefix. +*/ +struct Fts5ExprTerm { + int bPrefix; /* True for a prefix term */ + char *zTerm; /* nul-terminated term */ + Fts5IndexIter *pIter; /* Iterator for this term */ + Fts5ExprTerm *pSynonym; /* Pointer to first in list of synonyms */ +}; + +/* +** A phrase. One or more terms that must appear in a contiguous sequence +** within a document for it to match. +*/ +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[1]; /* Terms that make up this phrase */ +}; + +/* +** One or more phrases that must appear within a certain token distance of +** each other within each matching document. +*/ +struct Fts5ExprNearset { + int nNear; /* NEAR parameter */ + Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */ + int nPhrase; /* Number of entries in aPhrase[] array */ + Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */ +}; + + +/* +** Parse context. +*/ +struct Fts5Parse { + Fts5Config *pConfig; + char *zErr; + int rc; + int nPhrase; /* Size of apPhrase array */ + Fts5ExprPhrase **apPhrase; /* Array of all phrases */ + Fts5ExprNode *pExpr; /* Result of a successful parse */ +}; + +void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){ + va_list ap; + va_start(ap, zFmt); + if( pParse->rc==SQLITE_OK ){ + pParse->zErr = sqlite3_vmprintf(zFmt, ap); + pParse->rc = SQLITE_ERROR; + } + va_end(ap); +} + +static int fts5ExprIsspace(char t){ + return t==' ' || t=='\t' || t=='\n' || t=='\r'; +} + +/* +** Read the first token from the nul-terminated string at *pz. +*/ +static int fts5ExprGetToken( + Fts5Parse *pParse, + const char **pz, /* IN/OUT: Pointer into buffer */ + Fts5Token *pToken +){ + const char *z = *pz; + int tok; + + /* Skip past any whitespace */ + while( fts5ExprIsspace(*z) ) z++; + + pToken->p = z; + pToken->n = 1; + switch( *z ){ + case '(': tok = FTS5_LP; break; + case ')': tok = FTS5_RP; break; + case '{': tok = FTS5_LCP; break; + case '}': tok = FTS5_RCP; break; + case ':': tok = FTS5_COLON; break; + case ',': tok = FTS5_COMMA; break; + case '+': tok = FTS5_PLUS; break; + case '*': tok = FTS5_STAR; break; + case '\0': tok = FTS5_EOF; break; + + case '"': { + const char *z2; + tok = FTS5_STRING; + + for(z2=&z[1]; 1; z2++){ + if( z2[0]=='"' ){ + z2++; + if( z2[0]!='"' ) break; + } + if( z2[0]=='\0' ){ + sqlite3Fts5ParseError(pParse, "unterminated string"); + return FTS5_EOF; + } + } + pToken->n = (z2 - z); + break; + } + + default: { + const char *z2; + if( sqlite3Fts5IsBareword(z[0])==0 ){ + sqlite3Fts5ParseError(pParse, "fts5: syntax error near \"%.1s\"", z); + return FTS5_EOF; + } + tok = FTS5_STRING; + for(z2=&z[1]; sqlite3Fts5IsBareword(*z2); z2++); + pToken->n = (z2 - z); + if( pToken->n==2 && memcmp(pToken->p, "OR", 2)==0 ) tok = FTS5_OR; + if( pToken->n==3 && memcmp(pToken->p, "NOT", 3)==0 ) tok = FTS5_NOT; + if( pToken->n==3 && memcmp(pToken->p, "AND", 3)==0 ) tok = FTS5_AND; + break; + } + } + + *pz = &pToken->p[pToken->n]; + return tok; +} + +static void *fts5ParseAlloc(u64 t){ return sqlite3_malloc((int)t); } +static void fts5ParseFree(void *p){ sqlite3_free(p); } + +int sqlite3Fts5ExprNew( + Fts5Config *pConfig, /* FTS5 Configuration */ + const char *zExpr, /* Expression text */ + Fts5Expr **ppNew, + char **pzErr +){ + Fts5Parse sParse; + Fts5Token token; + const char *z = zExpr; + int t; /* Next token type */ + void *pEngine; + Fts5Expr *pNew; + + *ppNew = 0; + *pzErr = 0; + memset(&sParse, 0, sizeof(sParse)); + pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc); + if( pEngine==0 ){ return SQLITE_NOMEM; } + sParse.pConfig = pConfig; + + do { + t = fts5ExprGetToken(&sParse, &z, &token); + sqlite3Fts5Parser(pEngine, t, token, &sParse); + }while( sParse.rc==SQLITE_OK && t!=FTS5_EOF ); + sqlite3Fts5ParserFree(pEngine, fts5ParseFree); + + assert( sParse.rc!=SQLITE_OK || sParse.zErr==0 ); + if( sParse.rc==SQLITE_OK ){ + *ppNew = pNew = sqlite3_malloc(sizeof(Fts5Expr)); + if( pNew==0 ){ + sParse.rc = SQLITE_NOMEM; + sqlite3Fts5ParseNodeFree(sParse.pExpr); + }else{ + if( !sParse.pExpr ){ + const int nByte = sizeof(Fts5ExprNode); + pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&sParse.rc, nByte); + if( pNew->pRoot ){ + pNew->pRoot->bEof = 1; + } + }else{ + pNew->pRoot = sParse.pExpr; + } + pNew->pIndex = 0; + pNew->pConfig = pConfig; + pNew->apExprPhrase = sParse.apPhrase; + pNew->nPhrase = sParse.nPhrase; + sParse.apPhrase = 0; + } + } + + sqlite3_free(sParse.apPhrase); + *pzErr = sParse.zErr; + return sParse.rc; +} + +/* +** Free the expression node object passed as the only argument. +*/ +void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){ + if( p ){ + int i; + for(i=0; inChild; i++){ + sqlite3Fts5ParseNodeFree(p->apChild[i]); + } + sqlite3Fts5ParseNearsetFree(p->pNear); + sqlite3_free(p); + } +} + +/* +** Free the expression object passed as the only argument. +*/ +void sqlite3Fts5ExprFree(Fts5Expr *p){ + if( p ){ + sqlite3Fts5ParseNodeFree(p->pRoot); + sqlite3_free(p->apExprPhrase); + sqlite3_free(p); + } +} + +/* +** Argument pTerm must be a synonym iterator. Return the current rowid +** that it points to. +*/ +static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){ + i64 iRet = 0; + int bRetValid = 0; + Fts5ExprTerm *p; + + assert( pTerm->pSynonym ); + assert( bDesc==0 || bDesc==1 ); + for(p=pTerm; p; p=p->pSynonym){ + if( 0==sqlite3Fts5IterEof(p->pIter) ){ + i64 iRowid = p->pIter->iRowid; + if( bRetValid==0 || (bDesc!=(iRowidpSynonym ); + for(p=pTerm; p; p=p->pSynonym){ + Fts5IndexIter *pIter = p->pIter; + if( sqlite3Fts5IterEof(pIter)==0 && pIter->iRowid==iRowid ){ + if( pIter->nData==0 ) continue; + if( nIter==nAlloc ){ + int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2; + Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte); + if( aNew==0 ){ + rc = SQLITE_NOMEM; + goto synonym_poslist_out; + } + memcpy(aNew, aIter, sizeof(Fts5PoslistReader) * nIter); + nAlloc = nAlloc*2; + if( aIter!=aStatic ) sqlite3_free(aIter); + aIter = aNew; + } + sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &aIter[nIter]); + assert( aIter[nIter].bEof==0 ); + nIter++; + } + } + + if( nIter==1 ){ + *pa = (u8*)aIter[0].a; + *pn = aIter[0].n; + }else{ + Fts5PoslistWriter writer = {0}; + i64 iPrev = -1; + fts5BufferZero(pBuf); + while( 1 ){ + int i; + i64 iMin = FTS5_LARGEST_INT64; + for(i=0; ip; + *pn = pBuf->n; + } + } + + synonym_poslist_out: + if( aIter!=aStatic ) sqlite3_free(aIter); + return rc; +} + + +/* +** All individual term iterators in pPhrase are guaranteed to be valid and +** pointing to the same rowid when this function is called. This function +** checks if the current rowid really is a match, and if so populates +** the pPhrase->poslist buffer accordingly. Output parameter *pbMatch +** is set to true if this is really a match, or false otherwise. +** +** SQLITE_OK is returned if an error occurs, or an SQLite error code +** otherwise. It is not considered an error code if the current rowid is +** not a match. +*/ +static int fts5ExprPhraseIsMatch( + Fts5ExprNode *pNode, /* Node pPhrase belongs to */ + Fts5ExprPhrase *pPhrase, /* Phrase object to initialize */ + int *pbMatch /* OUT: Set to true if really a match */ +){ + Fts5PoslistWriter writer = {0}; + Fts5PoslistReader aStatic[4]; + Fts5PoslistReader *aIter = aStatic; + int i; + int rc = SQLITE_OK; + + fts5BufferZero(&pPhrase->poslist); + + /* If the aStatic[] array is not large enough, allocate a large array + ** using sqlite3_malloc(). This approach could be improved upon. */ + if( pPhrase->nTerm>ArraySize(aStatic) ){ + int nByte = sizeof(Fts5PoslistReader) * pPhrase->nTerm; + aIter = (Fts5PoslistReader*)sqlite3_malloc(nByte); + if( !aIter ) return SQLITE_NOMEM; + } + memset(aIter, 0, sizeof(Fts5PoslistReader) * pPhrase->nTerm); + + /* Initialize a term iterator for each term in the phrase */ + for(i=0; inTerm; i++){ + Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; + int n = 0; + int bFlag = 0; + u8 *a = 0; + if( pTerm->pSynonym ){ + Fts5Buffer buf = {0, 0, 0}; + rc = fts5ExprSynonymList(pTerm, pNode->iRowid, &buf, &a, &n); + if( rc ){ + sqlite3_free(a); + goto ismatch_out; + } + if( a==buf.p ) bFlag = 1; + }else{ + a = (u8*)pTerm->pIter->pData; + n = pTerm->pIter->nData; + } + sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]); + aIter[i].bFlag = (u8)bFlag; + if( aIter[i].bEof ) goto ismatch_out; + } + + while( 1 ){ + int bMatch; + i64 iPos = aIter[0].iPos; + do { + bMatch = 1; + for(i=0; inTerm; i++){ + Fts5PoslistReader *pPos = &aIter[i]; + i64 iAdj = iPos + i; + if( pPos->iPos!=iAdj ){ + bMatch = 0; + while( pPos->iPosiPos>iAdj ) iPos = pPos->iPos-i; + } + } + }while( bMatch==0 ); + + /* Append position iPos to the output */ + rc = sqlite3Fts5PoslistWriterAppend(&pPhrase->poslist, &writer, iPos); + if( rc!=SQLITE_OK ) goto ismatch_out; + + for(i=0; inTerm; i++){ + if( sqlite3Fts5PoslistReaderNext(&aIter[i]) ) goto ismatch_out; + } + } + + ismatch_out: + *pbMatch = (pPhrase->poslist.n>0); + for(i=0; inTerm; i++){ + if( aIter[i].bFlag ) sqlite3_free((u8*)aIter[i].a); + } + if( aIter!=aStatic ) sqlite3_free(aIter); + return rc; +} + +typedef struct Fts5LookaheadReader Fts5LookaheadReader; +struct Fts5LookaheadReader { + const u8 *a; /* Buffer containing position list */ + int n; /* Size of buffer a[] in bytes */ + int i; /* Current offset in position list */ + i64 iPos; /* Current position */ + i64 iLookahead; /* Next position */ +}; + +#define FTS5_LOOKAHEAD_EOF (((i64)1) << 62) + +static int fts5LookaheadReaderNext(Fts5LookaheadReader *p){ + p->iPos = p->iLookahead; + if( sqlite3Fts5PoslistNext64(p->a, p->n, &p->i, &p->iLookahead) ){ + p->iLookahead = FTS5_LOOKAHEAD_EOF; + } + return (p->iPos==FTS5_LOOKAHEAD_EOF); +} + +static int fts5LookaheadReaderInit( + const u8 *a, int n, /* Buffer to read position list from */ + Fts5LookaheadReader *p /* Iterator object to initialize */ +){ + memset(p, 0, sizeof(Fts5LookaheadReader)); + p->a = a; + p->n = n; + fts5LookaheadReaderNext(p); + return fts5LookaheadReaderNext(p); +} + +typedef struct Fts5NearTrimmer Fts5NearTrimmer; +struct Fts5NearTrimmer { + Fts5LookaheadReader reader; /* Input iterator */ + Fts5PoslistWriter writer; /* Writer context */ + Fts5Buffer *pOut; /* Output poslist */ +}; + +/* +** The near-set object passed as the first argument contains more than +** one phrase. All phrases currently point to the same row. The +** Fts5ExprPhrase.poslist buffers are populated accordingly. This function +** tests if the current row contains instances of each phrase sufficiently +** close together to meet the NEAR constraint. Non-zero is returned if it +** does, or zero otherwise. +** +** If in/out parameter (*pRc) is set to other than SQLITE_OK when this +** function is called, it is a no-op. Or, if an error (e.g. SQLITE_NOMEM) +** occurs within this function (*pRc) is set accordingly before returning. +** The return value is undefined in both these cases. +** +** If no error occurs and non-zero (a match) is returned, the position-list +** of each phrase object is edited to contain only those entries that +** meet the constraint before returning. +*/ +static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){ + Fts5NearTrimmer aStatic[4]; + Fts5NearTrimmer *a = aStatic; + Fts5ExprPhrase **apPhrase = pNear->apPhrase; + + int i; + int rc = *pRc; + int bMatch; + + assert( pNear->nPhrase>1 ); + + /* If the aStatic[] array is not large enough, allocate a large array + ** using sqlite3_malloc(). This approach could be improved upon. */ + if( pNear->nPhrase>ArraySize(aStatic) ){ + int nByte = sizeof(Fts5NearTrimmer) * pNear->nPhrase; + a = (Fts5NearTrimmer*)sqlite3Fts5MallocZero(&rc, nByte); + }else{ + memset(aStatic, 0, sizeof(aStatic)); + } + if( rc!=SQLITE_OK ){ + *pRc = rc; + return 0; + } + + /* Initialize a lookahead iterator for each phrase. After passing the + ** buffer and buffer size to the lookaside-reader init function, zero + ** the phrase poslist buffer. The new poslist for the phrase (containing + ** the same entries as the original with some entries removed on account + ** of the NEAR constraint) is written over the original even as it is + ** being read. This is safe as the entries for the new poslist are a + ** subset of the old, so it is not possible for data yet to be read to + ** be overwritten. */ + for(i=0; inPhrase; i++){ + Fts5Buffer *pPoslist = &apPhrase[i]->poslist; + fts5LookaheadReaderInit(pPoslist->p, pPoslist->n, &a[i].reader); + pPoslist->n = 0; + a[i].pOut = pPoslist; + } + + while( 1 ){ + int iAdv; + i64 iMin; + i64 iMax; + + /* This block advances the phrase iterators until they point to a set of + ** entries that together comprise a match. */ + iMax = a[0].reader.iPos; + do { + bMatch = 1; + for(i=0; inPhrase; i++){ + Fts5LookaheadReader *pPos = &a[i].reader; + iMin = iMax - pNear->apPhrase[i]->nTerm - pNear->nNear; + if( pPos->iPosiPos>iMax ){ + bMatch = 0; + while( pPos->iPosiPos>iMax ) iMax = pPos->iPos; + } + } + }while( bMatch==0 ); + + /* Add an entry to each output position list */ + for(i=0; inPhrase; i++){ + i64 iPos = a[i].reader.iPos; + Fts5PoslistWriter *pWriter = &a[i].writer; + if( a[i].pOut->n==0 || iPos!=pWriter->iPrev ){ + sqlite3Fts5PoslistWriterAppend(a[i].pOut, pWriter, iPos); + } + } + + iAdv = 0; + iMin = a[0].reader.iLookahead; + for(i=0; inPhrase; i++){ + if( a[i].reader.iLookahead < iMin ){ + iMin = a[i].reader.iLookahead; + iAdv = i; + } + } + if( fts5LookaheadReaderNext(&a[iAdv].reader) ) goto ismatch_out; + } + + ismatch_out: { + int bRet = a[0].pOut->n>0; + *pRc = rc; + if( a!=aStatic ) sqlite3_free(a); + return bRet; + } +} + +/* +** Advance iterator pIter until it points to a value equal to or laster +** than the initial value of *piLast. If this means the iterator points +** to a value laster than *piLast, update *piLast to the new lastest value. +** +** If the iterator reaches EOF, set *pbEof to true before returning. If +** an error occurs, set *pRc to an error code. If either *pbEof or *pRc +** are set, return a non-zero value. Otherwise, return zero. +*/ +static int fts5ExprAdvanceto( + Fts5IndexIter *pIter, /* Iterator to advance */ + int bDesc, /* True if iterator is "rowid DESC" */ + i64 *piLast, /* IN/OUT: Lastest rowid seen so far */ + int *pRc, /* OUT: Error code */ + int *pbEof /* OUT: Set to true if EOF */ +){ + i64 iLast = *piLast; + i64 iRowid; + + iRowid = pIter->iRowid; + if( (bDesc==0 && iLast>iRowid) || (bDesc && iLastiRowid; + assert( (bDesc==0 && iRowid>=iLast) || (bDesc==1 && iRowid<=iLast) ); + } + *piLast = iRowid; + + return 0; +} + +static int fts5ExprSynonymAdvanceto( + Fts5ExprTerm *pTerm, /* Term iterator to advance */ + int bDesc, /* True if iterator is "rowid DESC" */ + i64 *piLast, /* IN/OUT: Lastest rowid seen so far */ + int *pRc /* OUT: Error code */ +){ + int rc = SQLITE_OK; + i64 iLast = *piLast; + Fts5ExprTerm *p; + int bEof = 0; + + for(p=pTerm; rc==SQLITE_OK && p; p=p->pSynonym){ + if( sqlite3Fts5IterEof(p->pIter)==0 ){ + i64 iRowid = p->pIter->iRowid; + if( (bDesc==0 && iLast>iRowid) || (bDesc && iLastpIter, iLast); + } + } + } + + if( rc!=SQLITE_OK ){ + *pRc = rc; + bEof = 1; + }else{ + *piLast = fts5ExprSynonymRowid(pTerm, bDesc, &bEof); + } + return bEof; +} + + +static int fts5ExprNearTest( + int *pRc, + Fts5Expr *pExpr, /* Expression that pNear is a part of */ + Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */ +){ + Fts5ExprNearset *pNear = pNode->pNear; + int rc = *pRc; + + if( pExpr->pConfig->eDetail!=FTS5_DETAIL_FULL ){ + Fts5ExprTerm *pTerm; + Fts5ExprPhrase *pPhrase = pNear->apPhrase[0]; + pPhrase->poslist.n = 0; + for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ + Fts5IndexIter *pIter = pTerm->pIter; + if( sqlite3Fts5IterEof(pIter)==0 ){ + if( pIter->iRowid==pNode->iRowid && pIter->nData>0 ){ + pPhrase->poslist.n = 1; + } + } + } + return pPhrase->poslist.n; + }else{ + int i; + + /* Check that each phrase in the nearset matches the current row. + ** Populate the pPhrase->poslist buffers at the same time. If any + ** phrase is not a match, break out of the loop early. */ + for(i=0; rc==SQLITE_OK && inPhrase; i++){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; + if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){ + int bMatch = 0; + rc = fts5ExprPhraseIsMatch(pNode, pPhrase, &bMatch); + if( bMatch==0 ) break; + }else{ + Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; + fts5BufferSet(&rc, &pPhrase->poslist, pIter->nData, pIter->pData); + } + } + + *pRc = rc; + if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){ + return 1; + } + return 0; + } +} + + +/* +** Initialize all term iterators in the pNear object. If any term is found +** to match no documents at all, return immediately without initializing any +** further iterators. +*/ +static int fts5ExprNearInitAll( + Fts5Expr *pExpr, + Fts5ExprNode *pNode +){ + Fts5ExprNearset *pNear = pNode->pNear; + int i, j; + int rc = SQLITE_OK; + + assert( pNode->bNomatch==0 ); + for(i=0; rc==SQLITE_OK && inPhrase; i++){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; + for(j=0; jnTerm; j++){ + Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; + Fts5ExprTerm *p; + int bEof = 1; + + for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){ + if( p->pIter ){ + sqlite3Fts5IterClose(p->pIter); + p->pIter = 0; + } + rc = sqlite3Fts5IndexQuery( + pExpr->pIndex, p->zTerm, (int)strlen(p->zTerm), + (pTerm->bPrefix ? FTS5INDEX_QUERY_PREFIX : 0) | + (pExpr->bDesc ? FTS5INDEX_QUERY_DESC : 0), + pNear->pColset, + &p->pIter + ); + assert( rc==SQLITE_OK || p->pIter==0 ); + if( p->pIter && 0==sqlite3Fts5IterEof(p->pIter) ){ + bEof = 0; + } + } + + if( bEof ){ + pNode->bEof = 1; + return rc; + } + } + } + + return rc; +} + +/* +** If pExpr is an ASC iterator, this function returns a value with the +** same sign as: +** +** (iLhs - iRhs) +** +** Otherwise, if this is a DESC iterator, the opposite is returned: +** +** (iRhs - iLhs) +*/ +static int fts5RowidCmp( + Fts5Expr *pExpr, + i64 iLhs, + i64 iRhs +){ + assert( pExpr->bDesc==0 || pExpr->bDesc==1 ); + if( pExpr->bDesc==0 ){ + if( iLhs iRhs); + }else{ + if( iLhs>iRhs ) return -1; + return (iLhs < iRhs); + } +} + +static void fts5ExprSetEof(Fts5ExprNode *pNode){ + int i; + pNode->bEof = 1; + pNode->bNomatch = 0; + for(i=0; inChild; i++){ + fts5ExprSetEof(pNode->apChild[i]); + } +} + +static void fts5ExprNodeZeroPoslist(Fts5ExprNode *pNode){ + if( pNode->eType==FTS5_STRING || pNode->eType==FTS5_TERM ){ + Fts5ExprNearset *pNear = pNode->pNear; + int i; + for(i=0; inPhrase; i++){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; + pPhrase->poslist.n = 0; + } + }else{ + int i; + for(i=0; inChild; i++){ + fts5ExprNodeZeroPoslist(pNode->apChild[i]); + } + } +} + + + +/* +** Compare the values currently indicated by the two nodes as follows: +** +** res = (*p1) - (*p2) +** +** Nodes that point to values that come later in the iteration order are +** considered to be larger. Nodes at EOF are the largest of all. +** +** This means that if the iteration order is ASC, then numerically larger +** rowids are considered larger. Or if it is the default DESC, numerically +** smaller rowids are larger. +*/ +static int fts5NodeCompare( + Fts5Expr *pExpr, + Fts5ExprNode *p1, + Fts5ExprNode *p2 +){ + if( p2->bEof ) return -1; + if( p1->bEof ) return +1; + return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); +} + +/* +** All individual term iterators in pNear are guaranteed to be valid when +** this function is called. This function checks if all term iterators +** point to the same rowid, and if not, advances them until they do. +** If an EOF is reached before this happens, *pbEof is set to true before +** returning. +** +** SQLITE_OK is returned if an error occurs, or an SQLite error code +** otherwise. It is not considered an error code if an iterator reaches +** EOF. +*/ +static int fts5ExprNodeTest_STRING( + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ + Fts5ExprNode *pNode +){ + Fts5ExprNearset *pNear = pNode->pNear; + Fts5ExprPhrase *pLeft = pNear->apPhrase[0]; + int rc = SQLITE_OK; + i64 iLast; /* Lastest rowid any iterator points to */ + int i, j; /* Phrase and token index, respectively */ + int bMatch; /* True if all terms are at the same rowid */ + const int bDesc = pExpr->bDesc; + + /* Check that this node should not be FTS5_TERM */ + assert( pNear->nPhrase>1 + || pNear->apPhrase[0]->nTerm>1 + || pNear->apPhrase[0]->aTerm[0].pSynonym + ); + + /* Initialize iLast, the "lastest" rowid any iterator points to. If the + ** iterator skips through rowids in the default ascending order, this means + ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it + ** means the minimum rowid. */ + if( pLeft->aTerm[0].pSynonym ){ + iLast = fts5ExprSynonymRowid(&pLeft->aTerm[0], bDesc, 0); + }else{ + iLast = pLeft->aTerm[0].pIter->iRowid; + } + + do { + bMatch = 1; + for(i=0; inPhrase; i++){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; + for(j=0; jnTerm; j++){ + Fts5ExprTerm *pTerm = &pPhrase->aTerm[j]; + if( pTerm->pSynonym ){ + i64 iRowid = fts5ExprSynonymRowid(pTerm, bDesc, 0); + if( iRowid==iLast ) continue; + bMatch = 0; + if( fts5ExprSynonymAdvanceto(pTerm, bDesc, &iLast, &rc) ){ + pNode->bNomatch = 0; + pNode->bEof = 1; + return rc; + } + }else{ + Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; + if( pIter->iRowid==iLast ) continue; + bMatch = 0; + if( fts5ExprAdvanceto(pIter, bDesc, &iLast, &rc, &pNode->bEof) ){ + return rc; + } + } + } + } + }while( bMatch==0 ); + + pNode->iRowid = iLast; + pNode->bNomatch = ((0==fts5ExprNearTest(&rc, pExpr, pNode)) && rc==SQLITE_OK); + assert( pNode->bEof==0 || pNode->bNomatch==0 ); + + return rc; +} + +/* +** Advance the first term iterator in the first phrase of pNear. Set output +** variable *pbEof to true if it reaches EOF or if an error occurs. +** +** Return SQLITE_OK if successful, or an SQLite error code if an error +** occurs. +*/ +static int fts5ExprNodeNext_STRING( + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ + Fts5ExprNode *pNode, /* FTS5_STRING or FTS5_TERM node */ + int bFromValid, + i64 iFrom +){ + Fts5ExprTerm *pTerm = &pNode->pNear->apPhrase[0]->aTerm[0]; + int rc = SQLITE_OK; + + pNode->bNomatch = 0; + if( pTerm->pSynonym ){ + int bEof = 1; + Fts5ExprTerm *p; + + /* Find the firstest rowid any synonym points to. */ + i64 iRowid = fts5ExprSynonymRowid(pTerm, pExpr->bDesc, 0); + + /* Advance each iterator that currently points to iRowid. Or, if iFrom + ** is valid - each iterator that points to a rowid before iFrom. */ + for(p=pTerm; p; p=p->pSynonym){ + if( sqlite3Fts5IterEof(p->pIter)==0 ){ + i64 ii = p->pIter->iRowid; + if( ii==iRowid + || (bFromValid && ii!=iFrom && (ii>iFrom)==pExpr->bDesc) + ){ + if( bFromValid ){ + rc = sqlite3Fts5IterNextFrom(p->pIter, iFrom); + }else{ + rc = sqlite3Fts5IterNext(p->pIter); + } + if( rc!=SQLITE_OK ) break; + if( sqlite3Fts5IterEof(p->pIter)==0 ){ + bEof = 0; + } + }else{ + bEof = 0; + } + } + } + + /* Set the EOF flag if either all synonym iterators are at EOF or an + ** error has occurred. */ + pNode->bEof = (rc || bEof); + }else{ + Fts5IndexIter *pIter = pTerm->pIter; + + assert( Fts5NodeIsString(pNode) ); + if( bFromValid ){ + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); + }else{ + rc = sqlite3Fts5IterNext(pIter); + } + + pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); + } + + if( pNode->bEof==0 ){ + assert( rc==SQLITE_OK ); + rc = fts5ExprNodeTest_STRING(pExpr, pNode); + } + + return rc; +} + + +static int fts5ExprNodeTest_TERM( + Fts5Expr *pExpr, /* Expression that pNear is a part of */ + Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */ +){ + /* As this "NEAR" object is actually a single phrase that consists + ** of a single term only, grab pointers into the poslist managed by the + ** fts5_index.c iterator object. This is much faster than synthesizing + ** a new poslist the way we have to for more complicated phrase or NEAR + ** expressions. */ + Fts5ExprPhrase *pPhrase = pNode->pNear->apPhrase[0]; + Fts5IndexIter *pIter = pPhrase->aTerm[0].pIter; + + assert( pNode->eType==FTS5_TERM ); + assert( pNode->pNear->nPhrase==1 && pPhrase->nTerm==1 ); + assert( pPhrase->aTerm[0].pSynonym==0 ); + + pPhrase->poslist.n = pIter->nData; + if( pExpr->pConfig->eDetail==FTS5_DETAIL_FULL ){ + pPhrase->poslist.p = (u8*)pIter->pData; + } + pNode->iRowid = pIter->iRowid; + pNode->bNomatch = (pPhrase->poslist.n==0); + return SQLITE_OK; +} + +/* +** xNext() method for a node of type FTS5_TERM. +*/ +static int fts5ExprNodeNext_TERM( + Fts5Expr *pExpr, + Fts5ExprNode *pNode, + int bFromValid, + i64 iFrom +){ + int rc; + Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; + + assert( pNode->bEof==0 ); + if( bFromValid ){ + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); + }else{ + rc = sqlite3Fts5IterNext(pIter); + } + if( rc==SQLITE_OK && sqlite3Fts5IterEof(pIter)==0 ){ + rc = fts5ExprNodeTest_TERM(pExpr, pNode); + }else{ + pNode->bEof = 1; + pNode->bNomatch = 0; + } + return rc; +} + +static void fts5ExprNodeTest_OR( + Fts5Expr *pExpr, /* Expression of which pNode is a part */ + Fts5ExprNode *pNode /* Expression node to test */ +){ + Fts5ExprNode *pNext = pNode->apChild[0]; + int i; + + for(i=1; inChild; i++){ + Fts5ExprNode *pChild = pNode->apChild[i]; + int cmp = fts5NodeCompare(pExpr, pNext, pChild); + if( cmp>0 || (cmp==0 && pChild->bNomatch==0) ){ + pNext = pChild; + } + } + pNode->iRowid = pNext->iRowid; + pNode->bEof = pNext->bEof; + pNode->bNomatch = pNext->bNomatch; +} + +static int fts5ExprNodeNext_OR( + Fts5Expr *pExpr, + Fts5ExprNode *pNode, + int bFromValid, + i64 iFrom +){ + int i; + i64 iLast = pNode->iRowid; + + for(i=0; inChild; i++){ + Fts5ExprNode *p1 = pNode->apChild[i]; + assert( p1->bEof || fts5RowidCmp(pExpr, p1->iRowid, iLast)>=0 ); + if( p1->bEof==0 ){ + if( (p1->iRowid==iLast) + || (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0) + ){ + int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); + if( rc!=SQLITE_OK ) return rc; + } + } + } + + fts5ExprNodeTest_OR(pExpr, pNode); + return SQLITE_OK; +} + +/* +** Argument pNode is an FTS5_AND node. +*/ +static int fts5ExprNodeTest_AND( + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ + Fts5ExprNode *pAnd /* FTS5_AND node to advance */ +){ + int iChild; + i64 iLast = pAnd->iRowid; + int rc = SQLITE_OK; + int bMatch; + + assert( pAnd->bEof==0 ); + do { + pAnd->bNomatch = 0; + bMatch = 1; + for(iChild=0; iChildnChild; iChild++){ + Fts5ExprNode *pChild = pAnd->apChild[iChild]; + int cmp = fts5RowidCmp(pExpr, iLast, pChild->iRowid); + if( cmp>0 ){ + /* Advance pChild until it points to iLast or laster */ + rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast); + if( rc!=SQLITE_OK ) return rc; + } + + /* If the child node is now at EOF, so is the parent AND node. Otherwise, + ** the child node is guaranteed to have advanced at least as far as + ** rowid iLast. So if it is not at exactly iLast, pChild->iRowid is the + ** new lastest rowid seen so far. */ + assert( pChild->bEof || fts5RowidCmp(pExpr, iLast, pChild->iRowid)<=0 ); + if( pChild->bEof ){ + fts5ExprSetEof(pAnd); + bMatch = 1; + break; + }else if( iLast!=pChild->iRowid ){ + bMatch = 0; + iLast = pChild->iRowid; + } + + if( pChild->bNomatch ){ + pAnd->bNomatch = 1; + } + } + }while( bMatch==0 ); + + if( pAnd->bNomatch && pAnd!=pExpr->pRoot ){ + fts5ExprNodeZeroPoslist(pAnd); + } + pAnd->iRowid = iLast; + return SQLITE_OK; +} + +static int fts5ExprNodeNext_AND( + Fts5Expr *pExpr, + Fts5ExprNode *pNode, + int bFromValid, + i64 iFrom +){ + int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); + if( rc==SQLITE_OK ){ + rc = fts5ExprNodeTest_AND(pExpr, pNode); + } + return rc; +} + +static int fts5ExprNodeTest_NOT( + Fts5Expr *pExpr, /* Expression pPhrase belongs to */ + Fts5ExprNode *pNode /* FTS5_NOT node to advance */ +){ + int rc = SQLITE_OK; + Fts5ExprNode *p1 = pNode->apChild[0]; + Fts5ExprNode *p2 = pNode->apChild[1]; + assert( pNode->nChild==2 ); + + while( rc==SQLITE_OK && p1->bEof==0 ){ + int cmp = fts5NodeCompare(pExpr, p1, p2); + if( cmp>0 ){ + rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); + cmp = fts5NodeCompare(pExpr, p1, p2); + } + assert( rc!=SQLITE_OK || cmp<=0 ); + if( cmp || p2->bNomatch ) break; + rc = fts5ExprNodeNext(pExpr, p1, 0, 0); + } + pNode->bEof = p1->bEof; + pNode->bNomatch = p1->bNomatch; + pNode->iRowid = p1->iRowid; + if( p1->bEof ){ + fts5ExprNodeZeroPoslist(p2); + } + return rc; +} + +static int fts5ExprNodeNext_NOT( + Fts5Expr *pExpr, + Fts5ExprNode *pNode, + int bFromValid, + i64 iFrom +){ + int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom); + if( rc==SQLITE_OK ){ + rc = fts5ExprNodeTest_NOT(pExpr, pNode); + } + return rc; +} + +/* +** If pNode currently points to a match, this function returns SQLITE_OK +** without modifying it. Otherwise, pNode is advanced until it does point +** to a match or EOF is reached. +*/ +static int fts5ExprNodeTest( + Fts5Expr *pExpr, /* Expression of which pNode is a part */ + Fts5ExprNode *pNode /* Expression node to test */ +){ + int rc = SQLITE_OK; + if( pNode->bEof==0 ){ + switch( pNode->eType ){ + + case FTS5_STRING: { + rc = fts5ExprNodeTest_STRING(pExpr, pNode); + break; + } + + case FTS5_TERM: { + rc = fts5ExprNodeTest_TERM(pExpr, pNode); + break; + } + + case FTS5_AND: { + rc = fts5ExprNodeTest_AND(pExpr, pNode); + break; + } + + case FTS5_OR: { + fts5ExprNodeTest_OR(pExpr, pNode); + break; + } + + default: assert( pNode->eType==FTS5_NOT ); { + rc = fts5ExprNodeTest_NOT(pExpr, pNode); + break; + } + } + } + return rc; +} + + +/* +** Set node pNode, which is part of expression pExpr, to point to the first +** match. If there are no matches, set the Node.bEof flag to indicate EOF. +** +** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. +** It is not an error if there are no matches. +*/ +static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ + int rc = SQLITE_OK; + pNode->bEof = 0; + pNode->bNomatch = 0; + + if( Fts5NodeIsString(pNode) ){ + /* Initialize all term iterators in the NEAR object. */ + rc = fts5ExprNearInitAll(pExpr, pNode); + }else{ + int i; + int nEof = 0; + for(i=0; inChild && rc==SQLITE_OK; i++){ + Fts5ExprNode *pChild = pNode->apChild[i]; + rc = fts5ExprNodeFirst(pExpr, pNode->apChild[i]); + assert( pChild->bEof==0 || pChild->bEof==1 ); + nEof += pChild->bEof; + } + pNode->iRowid = pNode->apChild[0]->iRowid; + + switch( pNode->eType ){ + case FTS5_AND: + if( nEof>0 ) fts5ExprSetEof(pNode); + break; + + case FTS5_OR: + if( pNode->nChild==nEof ) fts5ExprSetEof(pNode); + break; + + default: + assert( pNode->eType==FTS5_NOT ); + pNode->bEof = pNode->apChild[0]->bEof; + break; + } + } + + if( rc==SQLITE_OK ){ + rc = fts5ExprNodeTest(pExpr, pNode); + } + return rc; +} + + +/* +** Begin iterating through the set of documents in index pIdx matched by +** the MATCH expression passed as the first argument. If the "bDesc" +** parameter is passed a non-zero value, iteration is in descending rowid +** order. Or, if it is zero, in ascending order. +** +** If iterating in ascending rowid order (bDesc==0), the first document +** visited is that with the smallest rowid that is larger than or equal +** to parameter iFirst. Or, if iterating in ascending order (bDesc==1), +** then the first document visited must have a rowid smaller than or +** equal to iFirst. +** +** 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, int bDesc){ + Fts5ExprNode *pRoot = p->pRoot; + int rc = SQLITE_OK; + if( pRoot->xNext ){ + p->pIndex = pIdx; + p->bDesc = bDesc; + rc = fts5ExprNodeFirst(p, pRoot); + + /* If not at EOF but the current rowid occurs earlier than iFirst in + ** the iteration order, move to document iFirst or later. */ + if( pRoot->bEof==0 && fts5RowidCmp(p, pRoot->iRowid, iFirst)<0 ){ + rc = fts5ExprNodeNext(p, pRoot, 1, iFirst); + } + + /* If the iterator is not at a real match, skip forward until it is. */ + while( pRoot->bNomatch ){ + assert( pRoot->bEof==0 && rc==SQLITE_OK ); + rc = fts5ExprNodeNext(p, pRoot, 0, 0); + } + } + return rc; +} + +/* +** Move to the next document +** +** 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 sqlite3Fts5ExprNext(Fts5Expr *p, i64 iLast){ + int rc; + Fts5ExprNode *pRoot = p->pRoot; + assert( pRoot->bEof==0 && pRoot->bNomatch==0 ); + do { + rc = fts5ExprNodeNext(p, pRoot, 0, 0); + assert( pRoot->bNomatch==0 || (rc==SQLITE_OK && pRoot->bEof==0) ); + }while( pRoot->bNomatch ); + if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){ + pRoot->bEof = 1; + } + return rc; +} + +int sqlite3Fts5ExprEof(Fts5Expr *p){ + return p->pRoot->bEof; +} + +i64 sqlite3Fts5ExprRowid(Fts5Expr *p){ + return p->pRoot->iRowid; +} + +static int fts5ParseStringFromToken(Fts5Token *pToken, char **pz){ + int rc = SQLITE_OK; + *pz = sqlite3Fts5Strndup(&rc, pToken->p, pToken->n); + return rc; +} + +/* +** Free the phrase object passed as the only argument. +*/ +static void fts5ExprPhraseFree(Fts5ExprPhrase *pPhrase){ + if( pPhrase ){ + int i; + for(i=0; inTerm; i++){ + Fts5ExprTerm *pSyn; + Fts5ExprTerm *pNext; + Fts5ExprTerm *pTerm = &pPhrase->aTerm[i]; + sqlite3_free(pTerm->zTerm); + sqlite3Fts5IterClose(pTerm->pIter); + for(pSyn=pTerm->pSynonym; pSyn; pSyn=pNext){ + pNext = pSyn->pSynonym; + sqlite3Fts5IterClose(pSyn->pIter); + fts5BufferFree((Fts5Buffer*)&pSyn[1]); + sqlite3_free(pSyn); + } + } + if( pPhrase->poslist.nSpace>0 ) fts5BufferFree(&pPhrase->poslist); + sqlite3_free(pPhrase); + } +} + +/* +** If argument pNear is NULL, then a new Fts5ExprNearset object is allocated +** and populated with pPhrase. Or, if pNear is not NULL, phrase pPhrase is +** appended to it and the results returned. +** +** If an OOM error occurs, both the pNear and pPhrase objects are freed and +** NULL returned. +*/ +Fts5ExprNearset *sqlite3Fts5ParseNearset( + Fts5Parse *pParse, /* Parse context */ + Fts5ExprNearset *pNear, /* Existing nearset, or NULL */ + Fts5ExprPhrase *pPhrase /* Recently parsed phrase */ +){ + const int SZALLOC = 8; + Fts5ExprNearset *pRet = 0; + + if( pParse->rc==SQLITE_OK ){ + if( pPhrase==0 ){ + return pNear; + } + if( pNear==0 ){ + int nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*); + pRet = sqlite3_malloc(nByte); + if( pRet==0 ){ + pParse->rc = SQLITE_NOMEM; + }else{ + memset(pRet, 0, nByte); + } + }else if( (pNear->nPhrase % SZALLOC)==0 ){ + int nNew = pNear->nPhrase + SZALLOC; + int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*); + + pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte); + if( pRet==0 ){ + pParse->rc = SQLITE_NOMEM; + } + }else{ + pRet = pNear; + } + } + + if( pRet==0 ){ + assert( pParse->rc!=SQLITE_OK ); + sqlite3Fts5ParseNearsetFree(pNear); + sqlite3Fts5ParsePhraseFree(pPhrase); + }else{ + pRet->apPhrase[pRet->nPhrase++] = pPhrase; + } + return pRet; +} + +typedef struct TokenCtx TokenCtx; +struct TokenCtx { + Fts5ExprPhrase *pPhrase; + int rc; +}; + +/* +** Callback for tokenizing terms used by ParseTerm(). +*/ +static int fts5ParseTokenize( + void *pContext, /* Pointer to Fts5InsertCtx object */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Buffer containing token */ + int nToken, /* Size of token in bytes */ + int iUnused1, /* Start offset of token */ + int iUnused2 /* End offset of token */ +){ + int rc = SQLITE_OK; + const int SZALLOC = 8; + TokenCtx *pCtx = (TokenCtx*)pContext; + Fts5ExprPhrase *pPhrase = pCtx->pPhrase; + + UNUSED_PARAM2(iUnused1, iUnused2); + + /* If an error has already occurred, this is a no-op */ + if( pCtx->rc!=SQLITE_OK ) return pCtx->rc; + + assert( pPhrase==0 || pPhrase->nTerm>0 ); + if( pPhrase && (tflags & FTS5_TOKEN_COLOCATED) ){ + Fts5ExprTerm *pSyn; + int nByte = sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer) + nToken+1; + pSyn = (Fts5ExprTerm*)sqlite3_malloc(nByte); + if( pSyn==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pSyn, 0, nByte); + pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); + memcpy(pSyn->zTerm, pToken, nToken); + pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; + pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn; + } + }else{ + Fts5ExprTerm *pTerm; + if( pPhrase==0 || (pPhrase->nTerm % SZALLOC)==0 ){ + Fts5ExprPhrase *pNew; + int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0); + + pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase, + sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew + ); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase)); + pCtx->pPhrase = pPhrase = pNew; + pNew->nTerm = nNew - SZALLOC; + } + } + + if( rc==SQLITE_OK ){ + pTerm = &pPhrase->aTerm[pPhrase->nTerm++]; + memset(pTerm, 0, sizeof(Fts5ExprTerm)); + pTerm->zTerm = sqlite3Fts5Strndup(&rc, pToken, nToken); + } + } + + pCtx->rc = rc; + return rc; +} + + +/* +** Free the phrase object passed as the only argument. +*/ +void sqlite3Fts5ParsePhraseFree(Fts5ExprPhrase *pPhrase){ + fts5ExprPhraseFree(pPhrase); +} + +/* +** Free the phrase object passed as the second argument. +*/ +void sqlite3Fts5ParseNearsetFree(Fts5ExprNearset *pNear){ + if( pNear ){ + int i; + for(i=0; inPhrase; i++){ + fts5ExprPhraseFree(pNear->apPhrase[i]); + } + sqlite3_free(pNear->pColset); + sqlite3_free(pNear); + } +} + +void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){ + assert( pParse->pExpr==0 ); + pParse->pExpr = p; +} + +/* +** This function is called by the parser to process a string token. The +** string may or may not be quoted. In any case it is tokenized and a +** phrase object consisting of all tokens returned. +*/ +Fts5ExprPhrase *sqlite3Fts5ParseTerm( + Fts5Parse *pParse, /* Parse context */ + Fts5ExprPhrase *pAppend, /* Phrase to append to */ + Fts5Token *pToken, /* String to tokenize */ + int bPrefix /* True if there is a trailing "*" */ +){ + Fts5Config *pConfig = pParse->pConfig; + TokenCtx sCtx; /* Context object passed to callback */ + int rc; /* Tokenize return code */ + char *z = 0; + + memset(&sCtx, 0, sizeof(TokenCtx)); + sCtx.pPhrase = pAppend; + + rc = fts5ParseStringFromToken(pToken, &z); + if( rc==SQLITE_OK ){ + int flags = FTS5_TOKENIZE_QUERY | (bPrefix ? FTS5_TOKENIZE_QUERY : 0); + int n; + sqlite3Fts5Dequote(z); + n = (int)strlen(z); + rc = sqlite3Fts5Tokenize(pConfig, flags, z, n, &sCtx, fts5ParseTokenize); + } + sqlite3_free(z); + if( rc || (rc = sCtx.rc) ){ + pParse->rc = rc; + fts5ExprPhraseFree(sCtx.pPhrase); + sCtx.pPhrase = 0; + }else if( sCtx.pPhrase ){ + + if( pAppend==0 ){ + if( (pParse->nPhrase % 8)==0 ){ + int nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8); + Fts5ExprPhrase **apNew; + apNew = (Fts5ExprPhrase**)sqlite3_realloc(pParse->apPhrase, nByte); + if( apNew==0 ){ + pParse->rc = SQLITE_NOMEM; + fts5ExprPhraseFree(sCtx.pPhrase); + return 0; + } + pParse->apPhrase = apNew; + } + pParse->nPhrase++; + } + + pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase; + assert( sCtx.pPhrase->nTerm>0 ); + sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix; + } + + return sCtx.pPhrase; +} + +/* +** Create a new FTS5 expression by cloning phrase iPhrase of the +** expression passed as the second argument. +*/ +int sqlite3Fts5ExprClonePhrase( + Fts5Expr *pExpr, + int iPhrase, + Fts5Expr **ppNew +){ + int rc = SQLITE_OK; /* Return code */ + Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */ + int i; /* Used to iterate through phrase terms */ + Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ + TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */ + + pOrig = pExpr->apExprPhrase[iPhrase]; + pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); + if( rc==SQLITE_OK ){ + pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, + sizeof(Fts5ExprPhrase*)); + } + if( rc==SQLITE_OK ){ + pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, + sizeof(Fts5ExprNode)); + } + if( rc==SQLITE_OK ){ + pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, + sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*)); + } + + for(i=0; rc==SQLITE_OK && inTerm; i++){ + int tflags = 0; + Fts5ExprTerm *p; + for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){ + const char *zTerm = p->zTerm; + rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm), + 0, 0); + tflags = FTS5_TOKEN_COLOCATED; + } + if( rc==SQLITE_OK ){ + sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; + } + } + + if( rc==SQLITE_OK ){ + /* All the allocations succeeded. Put the expression object together. */ + pNew->pIndex = pExpr->pIndex; + pNew->pConfig = pExpr->pConfig; + pNew->nPhrase = 1; + pNew->apExprPhrase[0] = sCtx.pPhrase; + pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase; + pNew->pRoot->pNear->nPhrase = 1; + sCtx.pPhrase->pNode = pNew->pRoot; + + if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){ + pNew->pRoot->eType = FTS5_TERM; + pNew->pRoot->xNext = fts5ExprNodeNext_TERM; + }else{ + pNew->pRoot->eType = FTS5_STRING; + pNew->pRoot->xNext = fts5ExprNodeNext_STRING; + } + }else{ + sqlite3Fts5ExprFree(pNew); + fts5ExprPhraseFree(sCtx.pPhrase); + pNew = 0; + } + + *ppNew = pNew; + return rc; +} + + +/* +** Token pTok has appeared in a MATCH expression where the NEAR operator +** is expected. If token pTok does not contain "NEAR", store an error +** in the pParse object. +*/ +void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token *pTok){ + if( pTok->n!=4 || memcmp("NEAR", pTok->p, 4) ){ + sqlite3Fts5ParseError( + pParse, "fts5: syntax error near \"%.*s\"", pTok->n, pTok->p + ); + } +} + +void sqlite3Fts5ParseSetDistance( + Fts5Parse *pParse, + Fts5ExprNearset *pNear, + Fts5Token *p +){ + int nNear = 0; + int i; + if( p->n ){ + for(i=0; in; i++){ + char c = (char)p->p[i]; + if( c<'0' || c>'9' ){ + sqlite3Fts5ParseError( + pParse, "expected integer, got \"%.*s\"", p->n, p->p + ); + return; + } + nNear = nNear * 10 + (p->p[i] - '0'); + } + }else{ + nNear = FTS5_DEFAULT_NEARDIST; + } + pNear->nNear = nNear; +} + +/* +** The second argument passed to this function may be NULL, or it may be +** an existing Fts5Colset object. This function returns a pointer to +** a new colset object containing the contents of (p) with new value column +** number iCol appended. +** +** If an OOM error occurs, store an error code in pParse and return NULL. +** The old colset object (if any) is not freed in this case. +*/ +static Fts5Colset *fts5ParseColset( + Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */ + Fts5Colset *p, /* Existing colset object */ + int iCol /* New column to add to colset object */ +){ + int nCol = p ? p->nCol : 0; /* Num. columns already in colset object */ + Fts5Colset *pNew; /* New colset object to return */ + + assert( pParse->rc==SQLITE_OK ); + assert( iCol>=0 && iColpConfig->nCol ); + + pNew = sqlite3_realloc(p, sizeof(Fts5Colset) + sizeof(int)*nCol); + if( pNew==0 ){ + pParse->rc = SQLITE_NOMEM; + }else{ + int *aiCol = pNew->aiCol; + int i, j; + for(i=0; iiCol ) break; + } + for(j=nCol; j>i; j--){ + aiCol[j] = aiCol[j-1]; + } + aiCol[i] = iCol; + pNew->nCol = nCol+1; + +#ifndef NDEBUG + /* Check that the array is in order and contains no duplicate entries. */ + for(i=1; inCol; i++) assert( pNew->aiCol[i]>pNew->aiCol[i-1] ); +#endif + } + + return pNew; +} + +Fts5Colset *sqlite3Fts5ParseColset( + Fts5Parse *pParse, /* Store SQLITE_NOMEM here if required */ + Fts5Colset *pColset, /* Existing colset object */ + Fts5Token *p +){ + Fts5Colset *pRet = 0; + int iCol; + char *z; /* Dequoted copy of token p */ + + z = sqlite3Fts5Strndup(&pParse->rc, p->p, p->n); + if( pParse->rc==SQLITE_OK ){ + Fts5Config *pConfig = pParse->pConfig; + sqlite3Fts5Dequote(z); + for(iCol=0; iColnCol; iCol++){ + if( 0==sqlite3_stricmp(pConfig->azCol[iCol], z) ) break; + } + if( iCol==pConfig->nCol ){ + sqlite3Fts5ParseError(pParse, "no such column: %s", z); + }else{ + pRet = fts5ParseColset(pParse, pColset, iCol); + } + sqlite3_free(z); + } + + if( pRet==0 ){ + assert( pParse->rc!=SQLITE_OK ); + sqlite3_free(pColset); + } + + return pRet; +} + +void sqlite3Fts5ParseSetColset( + Fts5Parse *pParse, + Fts5ExprNearset *pNear, + Fts5Colset *pColset +){ + if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){ + pParse->rc = SQLITE_ERROR; + pParse->zErr = sqlite3_mprintf( + "fts5: column queries are not supported (detail=none)" + ); + sqlite3_free(pColset); + return; + } + + if( pNear ){ + pNear->pColset = pColset; + }else{ + sqlite3_free(pColset); + } +} + +static void fts5ExprAssignXNext(Fts5ExprNode *pNode){ + switch( pNode->eType ){ + case FTS5_STRING: { + Fts5ExprNearset *pNear = pNode->pNear; + if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 + && pNear->apPhrase[0]->aTerm[0].pSynonym==0 + ){ + pNode->eType = FTS5_TERM; + pNode->xNext = fts5ExprNodeNext_TERM; + }else{ + pNode->xNext = fts5ExprNodeNext_STRING; + } + break; + }; + + case FTS5_OR: { + pNode->xNext = fts5ExprNodeNext_OR; + break; + }; + + case FTS5_AND: { + pNode->xNext = fts5ExprNodeNext_AND; + break; + }; + + default: assert( pNode->eType==FTS5_NOT ); { + pNode->xNext = fts5ExprNodeNext_NOT; + break; + }; + } +} + +static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){ + if( p->eType!=FTS5_NOT && pSub->eType==p->eType ){ + int nByte = sizeof(Fts5ExprNode*) * pSub->nChild; + memcpy(&p->apChild[p->nChild], pSub->apChild, nByte); + p->nChild += pSub->nChild; + sqlite3_free(pSub); + }else{ + p->apChild[p->nChild++] = pSub; + } +} + +/* +** Allocate and return a new expression object. If anything goes wrong (i.e. +** OOM error), leave an error code in pParse and return NULL. +*/ +Fts5ExprNode *sqlite3Fts5ParseNode( + Fts5Parse *pParse, /* Parse context */ + int eType, /* FTS5_STRING, AND, OR or NOT */ + Fts5ExprNode *pLeft, /* Left hand child expression */ + Fts5ExprNode *pRight, /* Right hand child expression */ + Fts5ExprNearset *pNear /* For STRING expressions, the near cluster */ +){ + Fts5ExprNode *pRet = 0; + + if( pParse->rc==SQLITE_OK ){ + int nChild = 0; /* Number of children of returned node */ + int nByte; /* Bytes of space to allocate for this node */ + + assert( (eType!=FTS5_STRING && !pNear) + || (eType==FTS5_STRING && !pLeft && !pRight) + ); + if( eType==FTS5_STRING && pNear==0 ) return 0; + if( eType!=FTS5_STRING && pLeft==0 ) return pRight; + if( eType!=FTS5_STRING && pRight==0 ) return pLeft; + + if( eType==FTS5_NOT ){ + nChild = 2; + }else if( eType==FTS5_AND || eType==FTS5_OR ){ + nChild = 2; + if( pLeft->eType==eType ) nChild += pLeft->nChild-1; + if( pRight->eType==eType ) nChild += pRight->nChild-1; + } + + nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1); + pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte); + + if( pRet ){ + pRet->eType = eType; + pRet->pNear = pNear; + fts5ExprAssignXNext(pRet); + if( eType==FTS5_STRING ){ + int iPhrase; + for(iPhrase=0; iPhrasenPhrase; iPhrase++){ + pNear->apPhrase[iPhrase]->pNode = pRet; + } + + if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL + && (pNear->nPhrase!=1 || pNear->apPhrase[0]->nTerm!=1) + ){ + assert( pParse->rc==SQLITE_OK ); + pParse->rc = SQLITE_ERROR; + assert( pParse->zErr==0 ); + pParse->zErr = sqlite3_mprintf( + "fts5: %s queries are not supported (detail!=full)", + pNear->nPhrase==1 ? "phrase": "NEAR" + ); + sqlite3_free(pRet); + pRet = 0; + } + + }else{ + fts5ExprAddChildren(pRet, pLeft); + fts5ExprAddChildren(pRet, pRight); + } + } + } + + if( pRet==0 ){ + assert( pParse->rc!=SQLITE_OK ); + sqlite3Fts5ParseNodeFree(pLeft); + sqlite3Fts5ParseNodeFree(pRight); + sqlite3Fts5ParseNearsetFree(pNear); + } + return pRet; +} + +static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){ + int nByte = 0; + Fts5ExprTerm *p; + char *zQuoted; + + /* Determine the maximum amount of space required. */ + for(p=pTerm; p; p=p->pSynonym){ + nByte += (int)strlen(pTerm->zTerm) * 2 + 3 + 2; + } + zQuoted = sqlite3_malloc(nByte); + + if( zQuoted ){ + int i = 0; + for(p=pTerm; p; p=p->pSynonym){ + char *zIn = p->zTerm; + zQuoted[i++] = '"'; + while( *zIn ){ + if( *zIn=='"' ) zQuoted[i++] = '"'; + zQuoted[i++] = *zIn++; + } + zQuoted[i++] = '"'; + if( p->pSynonym ) zQuoted[i++] = '|'; + } + if( pTerm->bPrefix ){ + zQuoted[i++] = ' '; + zQuoted[i++] = '*'; + } + zQuoted[i++] = '\0'; + } + return zQuoted; +} + +static char *fts5PrintfAppend(char *zApp, const char *zFmt, ...){ + char *zNew; + va_list ap; + va_start(ap, zFmt); + zNew = sqlite3_vmprintf(zFmt, ap); + va_end(ap); + if( zApp && zNew ){ + char *zNew2 = sqlite3_mprintf("%s%s", zApp, zNew); + sqlite3_free(zNew); + zNew = zNew2; + } + sqlite3_free(zApp); + return zNew; +} + +/* +** Compose a tcl-readable representation of expression pExpr. Return a +** pointer to a buffer containing that representation. It is the +** responsibility of the caller to at some point free the buffer using +** sqlite3_free(). +*/ +static char *fts5ExprPrintTcl( + Fts5Config *pConfig, + const char *zNearsetCmd, + Fts5ExprNode *pExpr +){ + char *zRet = 0; + if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){ + Fts5ExprNearset *pNear = pExpr->pNear; + int i; + int iTerm; + + zRet = fts5PrintfAppend(zRet, "%s ", zNearsetCmd); + if( zRet==0 ) return 0; + if( pNear->pColset ){ + int *aiCol = pNear->pColset->aiCol; + int nCol = pNear->pColset->nCol; + if( nCol==1 ){ + zRet = fts5PrintfAppend(zRet, "-col %d ", aiCol[0]); + }else{ + zRet = fts5PrintfAppend(zRet, "-col {%d", aiCol[0]); + for(i=1; ipColset->nCol; i++){ + zRet = fts5PrintfAppend(zRet, " %d", aiCol[i]); + } + zRet = fts5PrintfAppend(zRet, "} "); + } + if( zRet==0 ) return 0; + } + + if( pNear->nPhrase>1 ){ + zRet = fts5PrintfAppend(zRet, "-near %d ", pNear->nNear); + if( zRet==0 ) return 0; + } + + zRet = fts5PrintfAppend(zRet, "--"); + if( zRet==0 ) return 0; + + for(i=0; inPhrase; i++){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; + + zRet = fts5PrintfAppend(zRet, " {"); + for(iTerm=0; zRet && iTermnTerm; iTerm++){ + char *zTerm = pPhrase->aTerm[iTerm].zTerm; + zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm); + if( pPhrase->aTerm[iTerm].bPrefix ){ + zRet = fts5PrintfAppend(zRet, "*"); + } + } + + if( zRet ) zRet = fts5PrintfAppend(zRet, "}"); + if( zRet==0 ) return 0; + } + + }else{ + char const *zOp = 0; + int i; + switch( pExpr->eType ){ + case FTS5_AND: zOp = "AND"; break; + case FTS5_NOT: zOp = "NOT"; break; + default: + assert( pExpr->eType==FTS5_OR ); + zOp = "OR"; + break; + } + + zRet = sqlite3_mprintf("%s", zOp); + for(i=0; zRet && inChild; i++){ + char *z = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->apChild[i]); + if( !z ){ + sqlite3_free(zRet); + zRet = 0; + }else{ + zRet = fts5PrintfAppend(zRet, " [%z]", z); + } + } + } + + return zRet; +} + +static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){ + char *zRet = 0; + if( pExpr->eType==FTS5_STRING || pExpr->eType==FTS5_TERM ){ + Fts5ExprNearset *pNear = pExpr->pNear; + int i; + int iTerm; + + if( pNear->pColset ){ + int iCol = pNear->pColset->aiCol[0]; + zRet = fts5PrintfAppend(zRet, "%s : ", pConfig->azCol[iCol]); + if( zRet==0 ) return 0; + } + + if( pNear->nPhrase>1 ){ + zRet = fts5PrintfAppend(zRet, "NEAR("); + if( zRet==0 ) return 0; + } + + for(i=0; inPhrase; i++){ + Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; + if( i!=0 ){ + zRet = fts5PrintfAppend(zRet, " "); + if( zRet==0 ) return 0; + } + for(iTerm=0; iTermnTerm; iTerm++){ + char *zTerm = fts5ExprTermPrint(&pPhrase->aTerm[iTerm]); + if( zTerm ){ + zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" + ", zTerm); + sqlite3_free(zTerm); + } + if( zTerm==0 || zRet==0 ){ + sqlite3_free(zRet); + return 0; + } + } + } + + if( pNear->nPhrase>1 ){ + zRet = fts5PrintfAppend(zRet, ", %d)", pNear->nNear); + if( zRet==0 ) return 0; + } + + }else{ + char const *zOp = 0; + int i; + + switch( pExpr->eType ){ + case FTS5_AND: zOp = " AND "; break; + case FTS5_NOT: zOp = " NOT "; break; + default: + assert( pExpr->eType==FTS5_OR ); + zOp = " OR "; + break; + } + + for(i=0; inChild; i++){ + char *z = fts5ExprPrint(pConfig, pExpr->apChild[i]); + if( z==0 ){ + sqlite3_free(zRet); + zRet = 0; + }else{ + int e = pExpr->apChild[i]->eType; + int b = (e!=FTS5_STRING && e!=FTS5_TERM); + zRet = fts5PrintfAppend(zRet, "%s%s%z%s", + (i==0 ? "" : zOp), + (b?"(":""), z, (b?")":"") + ); + } + if( zRet==0 ) break; + } + } + + return zRet; +} + +/* +** The implementation of user-defined scalar functions fts5_expr() (bTcl==0) +** and fts5_expr_tcl() (bTcl!=0). +*/ +static void fts5ExprFunction( + sqlite3_context *pCtx, /* Function call context */ + int nArg, /* Number of args */ + sqlite3_value **apVal, /* Function arguments */ + int bTcl +){ + Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx); + sqlite3 *db = sqlite3_context_db_handle(pCtx); + const char *zExpr = 0; + char *zErr = 0; + Fts5Expr *pExpr = 0; + int rc; + int i; + + const char **azConfig; /* Array of arguments for Fts5Config */ + const char *zNearsetCmd = "nearset"; + int nConfig; /* Size of azConfig[] */ + Fts5Config *pConfig = 0; + int iArg = 1; + + if( nArg<1 ){ + zErr = sqlite3_mprintf("wrong number of arguments to function %s", + bTcl ? "fts5_expr_tcl" : "fts5_expr" + ); + sqlite3_result_error(pCtx, zErr, -1); + sqlite3_free(zErr); + return; + } + + if( bTcl && nArg>1 ){ + zNearsetCmd = (const char*)sqlite3_value_text(apVal[1]); + iArg = 2; + } + + nConfig = 3 + (nArg-iArg); + azConfig = (const char**)sqlite3_malloc(sizeof(char*) * nConfig); + if( azConfig==0 ){ + sqlite3_result_error_nomem(pCtx); + return; + } + azConfig[0] = 0; + azConfig[1] = "main"; + azConfig[2] = "tbl"; + for(i=3; iArgpRoot->xNext==0 ){ + zText = sqlite3_mprintf(""); + }else if( bTcl ){ + zText = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRoot); + }else{ + zText = fts5ExprPrint(pConfig, pExpr->pRoot); + } + if( zText==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_result_text(pCtx, zText, -1, SQLITE_TRANSIENT); + sqlite3_free(zText); + } + } + + if( rc!=SQLITE_OK ){ + if( zErr ){ + sqlite3_result_error(pCtx, zErr, -1); + sqlite3_free(zErr); + }else{ + sqlite3_result_error_code(pCtx, rc); + } + } + sqlite3_free((void *)azConfig); + sqlite3Fts5ConfigFree(pConfig); + sqlite3Fts5ExprFree(pExpr); +} + +static void fts5ExprFunctionHr( + sqlite3_context *pCtx, /* Function call context */ + int nArg, /* Number of args */ + sqlite3_value **apVal /* Function arguments */ +){ + fts5ExprFunction(pCtx, nArg, apVal, 0); +} +static void fts5ExprFunctionTcl( + sqlite3_context *pCtx, /* Function call context */ + int nArg, /* Number of args */ + sqlite3_value **apVal /* Function arguments */ +){ + fts5ExprFunction(pCtx, nArg, apVal, 1); +} + +/* +** The implementation of an SQLite user-defined-function that accepts a +** single integer as an argument. If the integer is an alpha-numeric +** unicode code point, 1 is returned. Otherwise 0. +*/ +static void fts5ExprIsAlnum( + sqlite3_context *pCtx, /* Function call context */ + int nArg, /* Number of args */ + sqlite3_value **apVal /* Function arguments */ +){ + int iCode; + if( nArg!=1 ){ + sqlite3_result_error(pCtx, + "wrong number of arguments to function fts5_isalnum", -1 + ); + return; + } + iCode = sqlite3_value_int(apVal[0]); + sqlite3_result_int(pCtx, sqlite3Fts5UnicodeIsalnum(iCode)); +} + +static void fts5ExprFold( + sqlite3_context *pCtx, /* Function call context */ + int nArg, /* Number of args */ + sqlite3_value **apVal /* Function arguments */ +){ + if( nArg!=1 && nArg!=2 ){ + sqlite3_result_error(pCtx, + "wrong number of arguments to function fts5_fold", -1 + ); + }else{ + int iCode; + int bRemoveDiacritics = 0; + iCode = sqlite3_value_int(apVal[0]); + if( nArg==2 ) bRemoveDiacritics = sqlite3_value_int(apVal[1]); + sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics)); + } +} + +/* +** This is called during initialization to register the fts5_expr() scalar +** UDF with the SQLite handle passed as the only argument. +*/ +int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){ + struct Fts5ExprFunc { + const char *z; + void (*x)(sqlite3_context*,int,sqlite3_value**); + } aFunc[] = { + { "fts5_expr", fts5ExprFunctionHr }, + { "fts5_expr_tcl", fts5ExprFunctionTcl }, + { "fts5_isalnum", fts5ExprIsAlnum }, + { "fts5_fold", fts5ExprFold }, + }; + int i; + int rc = SQLITE_OK; + void *pCtx = (void*)pGlobal; + + for(i=0; rc==SQLITE_OK && iz, -1, SQLITE_UTF8, pCtx, p->x, 0, 0); + } + + /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */ +#ifndef NDEBUG + (void)sqlite3Fts5ParserTrace; +#endif + + return rc; +} + +/* +** Return the number of phrases in expression pExpr. +*/ +int sqlite3Fts5ExprPhraseCount(Fts5Expr *pExpr){ + return (pExpr ? pExpr->nPhrase : 0); +} + +/* +** Return the number of terms in the iPhrase'th phrase in pExpr. +*/ +int sqlite3Fts5ExprPhraseSize(Fts5Expr *pExpr, int iPhrase){ + if( iPhrase<0 || iPhrase>=pExpr->nPhrase ) return 0; + return pExpr->apExprPhrase[iPhrase]->nTerm; +} + +/* +** This function is used to access the current position list for phrase +** iPhrase. +*/ +int sqlite3Fts5ExprPoslist(Fts5Expr *pExpr, int iPhrase, const u8 **pa){ + int nRet; + Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase]; + Fts5ExprNode *pNode = pPhrase->pNode; + if( pNode->bEof==0 && pNode->iRowid==pExpr->pRoot->iRowid ){ + *pa = pPhrase->poslist.p; + nRet = pPhrase->poslist.n; + }else{ + *pa = 0; + nRet = 0; + } + return nRet; +} + +struct Fts5PoslistPopulator { + Fts5PoslistWriter writer; + int bOk; /* True if ok to populate */ + int bMiss; +}; + +Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){ + Fts5PoslistPopulator *pRet; + pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase); + if( pRet ){ + int i; + memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase); + for(i=0; inPhrase; i++){ + Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist; + Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode; + assert( pExpr->apExprPhrase[i]->nTerm==1 ); + if( bLive && + (pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof) + ){ + pRet[i].bMiss = 1; + }else{ + pBuf->n = 0; + } + } + } + return pRet; +} + +struct Fts5ExprCtx { + Fts5Expr *pExpr; + Fts5PoslistPopulator *aPopulator; + i64 iOff; +}; +typedef struct Fts5ExprCtx Fts5ExprCtx; + +/* +** TODO: Make this more efficient! +*/ +static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){ + int i; + for(i=0; inCol; i++){ + if( pColset->aiCol[i]==iCol ) return 1; + } + return 0; +} + +static int fts5ExprPopulatePoslistsCb( + void *pCtx, /* Copy of 2nd argument to xTokenize() */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Pointer to buffer containing token */ + int nToken, /* Size of token in bytes */ + int iUnused1, /* Byte offset of token within input text */ + int iUnused2 /* Byte offset of end of token within input text */ +){ + Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx; + Fts5Expr *pExpr = p->pExpr; + int i; + + UNUSED_PARAM2(iUnused1, iUnused2); + + if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++; + for(i=0; inPhrase; i++){ + Fts5ExprTerm *pTerm; + if( p->aPopulator[i].bOk==0 ) continue; + for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){ + int nTerm = strlen(pTerm->zTerm); + if( (nTerm==nToken || (nTermbPrefix)) + && memcmp(pTerm->zTerm, pToken, nTerm)==0 + ){ + int rc = sqlite3Fts5PoslistWriterAppend( + &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff + ); + if( rc ) return rc; + break; + } + } + } + return SQLITE_OK; +} + +int sqlite3Fts5ExprPopulatePoslists( + Fts5Config *pConfig, + Fts5Expr *pExpr, + Fts5PoslistPopulator *aPopulator, + int iCol, + const char *z, int n +){ + int i; + Fts5ExprCtx sCtx; + sCtx.pExpr = pExpr; + sCtx.aPopulator = aPopulator; + sCtx.iOff = (((i64)iCol) << 32) - 1; + + for(i=0; inPhrase; i++){ + Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode; + Fts5Colset *pColset = pNode->pNear->pColset; + if( (pColset && 0==fts5ExprColsetTest(pColset, iCol)) + || aPopulator[i].bMiss + ){ + aPopulator[i].bOk = 0; + }else{ + aPopulator[i].bOk = 1; + } + } + + return sqlite3Fts5Tokenize(pConfig, + FTS5_TOKENIZE_DOCUMENT, z, n, (void*)&sCtx, fts5ExprPopulatePoslistsCb + ); +} + +static void fts5ExprClearPoslists(Fts5ExprNode *pNode){ + if( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING ){ + pNode->pNear->apPhrase[0]->poslist.n = 0; + }else{ + int i; + for(i=0; inChild; i++){ + fts5ExprClearPoslists(pNode->apChild[i]); + } + } +} + +static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){ + pNode->iRowid = iRowid; + pNode->bEof = 0; + switch( pNode->eType ){ + case FTS5_TERM: + case FTS5_STRING: + return (pNode->pNear->apPhrase[0]->poslist.n>0); + + case FTS5_AND: { + int i; + for(i=0; inChild; i++){ + if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid)==0 ){ + fts5ExprClearPoslists(pNode); + return 0; + } + } + break; + } + + case FTS5_OR: { + int i; + int bRet = 0; + for(i=0; inChild; i++){ + if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid) ){ + bRet = 1; + } + } + return bRet; + } + + default: { + assert( pNode->eType==FTS5_NOT ); + if( 0==fts5ExprCheckPoslists(pNode->apChild[0], iRowid) + || 0!=fts5ExprCheckPoslists(pNode->apChild[1], iRowid) + ){ + fts5ExprClearPoslists(pNode); + return 0; + } + break; + } + } + return 1; +} + +void sqlite3Fts5ExprCheckPoslists(Fts5Expr *pExpr, i64 iRowid){ + fts5ExprCheckPoslists(pExpr->pRoot, iRowid); +} + +static void fts5ExprClearEof(Fts5ExprNode *pNode){ + int i; + for(i=0; inChild; i++){ + fts5ExprClearEof(pNode->apChild[i]); + } + pNode->bEof = 0; +} +void sqlite3Fts5ExprClearEof(Fts5Expr *pExpr){ + fts5ExprClearEof(pExpr->pRoot); +} + +/* +** This function is only called for detail=columns tables. +*/ +int sqlite3Fts5ExprPhraseCollist( + Fts5Expr *pExpr, + int iPhrase, + const u8 **ppCollist, + int *pnCollist +){ + Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase]; + Fts5ExprNode *pNode = pPhrase->pNode; + int rc = SQLITE_OK; + + assert( iPhrase>=0 && iPhrasenPhrase ); + assert( pExpr->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + + if( pNode->bEof==0 + && pNode->iRowid==pExpr->pRoot->iRowid + && pPhrase->poslist.n>0 + ){ + Fts5ExprTerm *pTerm = &pPhrase->aTerm[0]; + if( pTerm->pSynonym ){ + Fts5Buffer *pBuf = (Fts5Buffer*)&pTerm->pSynonym[1]; + rc = fts5ExprSynonymList( + pTerm, pNode->iRowid, pBuf, (u8**)ppCollist, pnCollist + ); + }else{ + *ppCollist = pPhrase->aTerm[0].pIter->pData; + *pnCollist = pPhrase->aTerm[0].pIter->nData; + } + }else{ + *ppCollist = 0; + *pnCollist = 0; + } + + return rc; +} + diff --git a/ext/fts5/fts5_hash.c b/ext/fts5/fts5_hash.c new file mode 100644 index 0000000..ada8bb1 --- /dev/null +++ b/ext/fts5/fts5_hash.c @@ -0,0 +1,527 @@ +/* +** 2014 August 11 +** +** 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. +** +****************************************************************************** +** +*/ + + + +#include "fts5Int.h" + +typedef struct Fts5HashEntry Fts5HashEntry; + +/* +** This file contains the implementation of an in-memory hash table used +** to accumuluate "term -> doclist" content before it is flused to a level-0 +** segment. +*/ + + +struct Fts5Hash { + int eDetail; /* Copy of Fts5Config.eDetail */ + int *pnByte; /* Pointer to bytes counter */ + int nEntry; /* Number of entries currently in hash */ + int nSlot; /* Size of aSlot[] array */ + Fts5HashEntry *pScan; /* Current ordered scan item */ + Fts5HashEntry **aSlot; /* Array of hash slots */ +}; + +/* +** Each entry in the hash table is represented by an object of the +** following type. Each object, its key (zKey[]) and its current data +** are stored in a single memory allocation. The position list data +** immediately follows the key data in memory. +** +** The data that follows the key is in a similar, but not identical format +** to the doclist data stored in the database. It is: +** +** * Rowid, as a varint +** * Position list, without 0x00 terminator. +** * Size of previous position list and rowid, as a 4 byte +** big-endian integer. +** +** iRowidOff: +** Offset of last rowid written to data area. Relative to first byte of +** structure. +** +** nData: +** Bytes of data written since iRowidOff. +*/ +struct Fts5HashEntry { + Fts5HashEntry *pHashNext; /* Next hash entry with same hash-key */ + Fts5HashEntry *pScanNext; /* Next entry in sorted order */ + + int nAlloc; /* Total size of allocation */ + int iSzPoslist; /* Offset of space for 4-byte poslist size */ + int nData; /* Total bytes of data (incl. structure) */ + int nKey; /* Length of zKey[] in bytes */ + u8 bDel; /* Set delete-flag @ iSzPoslist */ + u8 bContent; /* Set content-flag (detail=none mode) */ + i16 iCol; /* Column of last value written */ + int iPos; /* Position of last value written */ + i64 iRowid; /* Rowid of last value written */ + char zKey[8]; /* Nul-terminated entry key */ +}; + +/* +** Size of Fts5HashEntry without the zKey[] array. +*/ +#define FTS5_HASHENTRYSIZE (sizeof(Fts5HashEntry)-8) + + + +/* +** Allocate a new hash table. +*/ +int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){ + int rc = SQLITE_OK; + Fts5Hash *pNew; + + *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash)); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + int nByte; + memset(pNew, 0, sizeof(Fts5Hash)); + pNew->pnByte = pnByte; + pNew->eDetail = pConfig->eDetail; + + pNew->nSlot = 1024; + nByte = sizeof(Fts5HashEntry*) * pNew->nSlot; + pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte); + if( pNew->aSlot==0 ){ + sqlite3_free(pNew); + *ppNew = 0; + rc = SQLITE_NOMEM; + }else{ + memset(pNew->aSlot, 0, nByte); + } + } + return rc; +} + +/* +** Free a hash table object. +*/ +void sqlite3Fts5HashFree(Fts5Hash *pHash){ + if( pHash ){ + sqlite3Fts5HashClear(pHash); + sqlite3_free(pHash->aSlot); + sqlite3_free(pHash); + } +} + +/* +** Empty (but do not delete) a hash table. +*/ +void sqlite3Fts5HashClear(Fts5Hash *pHash){ + int i; + for(i=0; inSlot; i++){ + Fts5HashEntry *pNext; + Fts5HashEntry *pSlot; + for(pSlot=pHash->aSlot[i]; pSlot; pSlot=pNext){ + pNext = pSlot->pHashNext; + sqlite3_free(pSlot); + } + } + memset(pHash->aSlot, 0, pHash->nSlot * sizeof(Fts5HashEntry*)); + pHash->nEntry = 0; +} + +static unsigned int fts5HashKey(int nSlot, const u8 *p, int n){ + int i; + unsigned int h = 13; + for(i=n-1; i>=0; i--){ + h = (h << 3) ^ h ^ p[i]; + } + return (h % nSlot); +} + +static unsigned int fts5HashKey2(int nSlot, u8 b, const u8 *p, int n){ + int i; + unsigned int h = 13; + for(i=n-1; i>=0; i--){ + h = (h << 3) ^ h ^ p[i]; + } + h = (h << 3) ^ h ^ b; + return (h % nSlot); +} + +/* +** Resize the hash table by doubling the number of slots. +*/ +static int fts5HashResize(Fts5Hash *pHash){ + int nNew = pHash->nSlot*2; + int i; + Fts5HashEntry **apNew; + Fts5HashEntry **apOld = pHash->aSlot; + + apNew = (Fts5HashEntry**)sqlite3_malloc(nNew*sizeof(Fts5HashEntry*)); + if( !apNew ) return SQLITE_NOMEM; + memset(apNew, 0, nNew*sizeof(Fts5HashEntry*)); + + for(i=0; inSlot; i++){ + while( apOld[i] ){ + int iHash; + Fts5HashEntry *p = apOld[i]; + apOld[i] = p->pHashNext; + iHash = fts5HashKey(nNew, (u8*)p->zKey, (int)strlen(p->zKey)); + p->pHashNext = apNew[iHash]; + apNew[iHash] = p; + } + } + + sqlite3_free(apOld); + pHash->nSlot = nNew; + pHash->aSlot = apNew; + return SQLITE_OK; +} + +static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){ + if( p->iSzPoslist ){ + u8 *pPtr = (u8*)p; + if( pHash->eDetail==FTS5_DETAIL_NONE ){ + assert( p->nData==p->iSzPoslist ); + if( p->bDel ){ + pPtr[p->nData++] = 0x00; + if( p->bContent ){ + pPtr[p->nData++] = 0x00; + } + } + }else{ + int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */ + int nPos = nSz*2 + p->bDel; /* Value of nPos field */ + + assert( p->bDel==0 || p->bDel==1 ); + if( nPos<=127 ){ + pPtr[p->iSzPoslist] = (u8)nPos; + }else{ + int nByte = sqlite3Fts5GetVarintLen((u32)nPos); + memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz); + sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos); + p->nData += (nByte-1); + } + } + + p->iSzPoslist = 0; + p->bDel = 0; + p->bContent = 0; + } +} + +/* +** Add an entry to the in-memory hash table. The key is the concatenation +** of bByte and (pToken/nToken). The value is (iRowid/iCol/iPos). +** +** (bByte || pToken) -> (iRowid,iCol,iPos) +** +** Or, if iCol is negative, then the value is a delete marker. +*/ +int sqlite3Fts5HashWrite( + Fts5Hash *pHash, + i64 iRowid, /* Rowid for this entry */ + int iCol, /* Column token appears in (-ve -> delete) */ + int iPos, /* Position of token within column */ + char bByte, /* First byte of token */ + const char *pToken, int nToken /* Token to add or remove to or from index */ +){ + unsigned int iHash; + Fts5HashEntry *p; + u8 *pPtr; + int nIncr = 0; /* Amount to increment (*pHash->pnByte) by */ + int bNew; /* If non-delete entry should be written */ + + bNew = (pHash->eDetail==FTS5_DETAIL_FULL); + + /* Attempt to locate an existing hash entry */ + iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken); + for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ + if( p->zKey[0]==bByte + && p->nKey==nToken + && memcmp(&p->zKey[1], pToken, nToken)==0 + ){ + break; + } + } + + /* If an existing hash entry cannot be found, create a new one. */ + if( p==0 ){ + /* Figure out how much space to allocate */ + int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64; + if( nByte<128 ) nByte = 128; + + /* Grow the Fts5Hash.aSlot[] array if necessary. */ + if( (pHash->nEntry*2)>=pHash->nSlot ){ + int rc = fts5HashResize(pHash); + if( rc!=SQLITE_OK ) return rc; + iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken); + } + + /* Allocate new Fts5HashEntry and add it to the hash table. */ + p = (Fts5HashEntry*)sqlite3_malloc(nByte); + if( !p ) return SQLITE_NOMEM; + memset(p, 0, FTS5_HASHENTRYSIZE); + p->nAlloc = nByte; + p->zKey[0] = bByte; + memcpy(&p->zKey[1], pToken, nToken); + assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) ); + p->nKey = nToken; + p->zKey[nToken+1] = '\0'; + p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE; + p->pHashNext = pHash->aSlot[iHash]; + pHash->aSlot[iHash] = p; + pHash->nEntry++; + + /* Add the first rowid field to the hash-entry */ + p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid); + p->iRowid = iRowid; + + p->iSzPoslist = p->nData; + if( pHash->eDetail!=FTS5_DETAIL_NONE ){ + p->nData += 1; + p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1); + } + + nIncr += p->nData; + }else{ + + /* Appending to an existing hash-entry. Check that there is enough + ** space to append the largest possible new entry. Worst case scenario + ** is: + ** + ** + 9 bytes for a new rowid, + ** + 4 byte reserved for the "poslist size" varint. + ** + 1 byte for a "new column" byte, + ** + 3 bytes for a new column number (16-bit max) as a varint, + ** + 5 bytes for the new position offset (32-bit max). + */ + if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){ + int nNew = p->nAlloc * 2; + Fts5HashEntry *pNew; + Fts5HashEntry **pp; + pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew); + if( pNew==0 ) return SQLITE_NOMEM; + pNew->nAlloc = nNew; + for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext); + *pp = pNew; + p = pNew; + } + nIncr -= p->nData; + } + assert( (p->nAlloc - p->nData) >= (9 + 4 + 1 + 3 + 5) ); + + pPtr = (u8*)p; + + /* If this is a new rowid, append the 4-byte size field for the previous + ** entry, and the new rowid for this entry. */ + if( iRowid!=p->iRowid ){ + fts5HashAddPoslistSize(pHash, p); + p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid); + p->iRowid = iRowid; + bNew = 1; + p->iSzPoslist = p->nData; + if( pHash->eDetail!=FTS5_DETAIL_NONE ){ + p->nData += 1; + p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1); + p->iPos = 0; + } + } + + if( iCol>=0 ){ + if( pHash->eDetail==FTS5_DETAIL_NONE ){ + p->bContent = 1; + }else{ + /* Append a new column value, if necessary */ + assert( iCol>=p->iCol ); + if( iCol!=p->iCol ){ + if( pHash->eDetail==FTS5_DETAIL_FULL ){ + pPtr[p->nData++] = 0x01; + p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol); + p->iCol = iCol; + p->iPos = 0; + }else{ + bNew = 1; + p->iCol = iPos = iCol; + } + } + + /* Append the new position offset, if necessary */ + if( bNew ){ + p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iPos - p->iPos + 2); + p->iPos = iPos; + } + } + }else{ + /* This is a delete. Set the delete flag. */ + p->bDel = 1; + } + + nIncr += p->nData; + *pHash->pnByte += nIncr; + return SQLITE_OK; +} + + +/* +** Arguments pLeft and pRight point to linked-lists of hash-entry objects, +** each sorted in key order. This function merges the two lists into a +** single list and returns a pointer to its first element. +*/ +static Fts5HashEntry *fts5HashEntryMerge( + Fts5HashEntry *pLeft, + Fts5HashEntry *pRight +){ + Fts5HashEntry *p1 = pLeft; + Fts5HashEntry *p2 = pRight; + Fts5HashEntry *pRet = 0; + Fts5HashEntry **ppOut = &pRet; + + while( p1 || p2 ){ + if( p1==0 ){ + *ppOut = p2; + p2 = 0; + }else if( p2==0 ){ + *ppOut = p1; + p1 = 0; + }else{ + int i = 0; + while( p1->zKey[i]==p2->zKey[i] ) i++; + + if( ((u8)p1->zKey[i])>((u8)p2->zKey[i]) ){ + /* p2 is smaller */ + *ppOut = p2; + ppOut = &p2->pScanNext; + p2 = p2->pScanNext; + }else{ + /* p1 is smaller */ + *ppOut = p1; + ppOut = &p1->pScanNext; + p1 = p1->pScanNext; + } + *ppOut = 0; + } + } + + return pRet; +} + +/* +** Extract all tokens from hash table iHash and link them into a list +** in sorted order. The hash table is cleared before returning. It is +** the responsibility of the caller to free the elements of the returned +** list. +*/ +static int fts5HashEntrySort( + Fts5Hash *pHash, + const char *pTerm, int nTerm, /* Query prefix, if any */ + Fts5HashEntry **ppSorted +){ + const int nMergeSlot = 32; + Fts5HashEntry **ap; + Fts5HashEntry *pList; + int iSlot; + int i; + + *ppSorted = 0; + ap = sqlite3_malloc(sizeof(Fts5HashEntry*) * nMergeSlot); + if( !ap ) return SQLITE_NOMEM; + memset(ap, 0, sizeof(Fts5HashEntry*) * nMergeSlot); + + for(iSlot=0; iSlotnSlot; iSlot++){ + Fts5HashEntry *pIter; + for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){ + if( pTerm==0 || 0==memcmp(pIter->zKey, pTerm, nTerm) ){ + Fts5HashEntry *pEntry = pIter; + pEntry->pScanNext = 0; + for(i=0; ap[i]; i++){ + pEntry = fts5HashEntryMerge(pEntry, ap[i]); + ap[i] = 0; + } + ap[i] = pEntry; + } + } + } + + pList = 0; + for(i=0; inEntry = 0; + sqlite3_free(ap); + *ppSorted = pList; + return SQLITE_OK; +} + +/* +** Query the hash table for a doclist associated with term pTerm/nTerm. +*/ +int sqlite3Fts5HashQuery( + Fts5Hash *pHash, /* Hash table to query */ + const char *pTerm, int nTerm, /* Query term */ + const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ + int *pnDoclist /* OUT: Size of doclist in bytes */ +){ + unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm); + Fts5HashEntry *p; + + for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){ + if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break; + } + + if( p ){ + fts5HashAddPoslistSize(pHash, p); + *ppDoclist = (const u8*)&p->zKey[nTerm+1]; + *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1); + }else{ + *ppDoclist = 0; + *pnDoclist = 0; + } + + return SQLITE_OK; +} + +int sqlite3Fts5HashScanInit( + Fts5Hash *p, /* Hash table to query */ + const char *pTerm, int nTerm /* Query prefix */ +){ + return fts5HashEntrySort(p, pTerm, nTerm, &p->pScan); +} + +void sqlite3Fts5HashScanNext(Fts5Hash *p){ + assert( !sqlite3Fts5HashScanEof(p) ); + p->pScan = p->pScan->pScanNext; +} + +int sqlite3Fts5HashScanEof(Fts5Hash *p){ + return (p->pScan==0); +} + +void sqlite3Fts5HashScanEntry( + Fts5Hash *pHash, + const char **pzTerm, /* OUT: term (nul-terminated) */ + const u8 **ppDoclist, /* OUT: pointer to doclist */ + int *pnDoclist /* OUT: size of doclist in bytes */ +){ + Fts5HashEntry *p; + if( (p = pHash->pScan) ){ + int nTerm = (int)strlen(p->zKey); + fts5HashAddPoslistSize(pHash, p); + *pzTerm = p->zKey; + *ppDoclist = (const u8*)&p->zKey[nTerm+1]; + *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1); + }else{ + *pzTerm = 0; + *ppDoclist = 0; + *pnDoclist = 0; + } +} + diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c new file mode 100644 index 0000000..c40ffbc --- /dev/null +++ b/ext/fts5/fts5_index.c @@ -0,0 +1,6281 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +** +** Low level access to the FTS index stored in the database file. The +** routines in this file file implement all read and write access to the +** %_data table. Other parts of the system access this functionality via +** the interface defined in fts5Int.h. +*/ + + +#include "fts5Int.h" + +/* +** Overview: +** +** The %_data table contains all the FTS indexes for an FTS5 virtual table. +** As well as the main term index, there may be up to 31 prefix indexes. +** The format is similar to FTS3/4, except that: +** +** * all segment b-tree leaf data is stored in fixed size page records +** (e.g. 1000 bytes). A single doclist may span multiple pages. Care is +** taken to ensure it is possible to iterate in either direction through +** the entries in a doclist, or to seek to a specific entry within a +** doclist, without loading it into memory. +** +** * large doclists that span many pages have associated "doclist index" +** records that contain a copy of the first rowid on each page spanned by +** the doclist. This is used to speed up seek operations, and merges of +** large doclists with very small doclists. +** +** * extra fields in the "structure record" record the state of ongoing +** incremental merge operations. +** +*/ + + +#define FTS5_OPT_WORK_UNIT 1000 /* Number of leaf pages per optimize step */ +#define FTS5_WORK_UNIT 64 /* Number of leaf pages in unit of work */ + +#define FTS5_MIN_DLIDX_SIZE 4 /* Add dlidx if this many empty pages */ + +#define FTS5_MAIN_PREFIX '0' + +#if FTS5_MAX_PREFIX_INDEXES > 31 +# error "FTS5_MAX_PREFIX_INDEXES is too large" +#endif + +/* +** Details: +** +** The %_data table managed by this module, +** +** CREATE TABLE %_data(id INTEGER PRIMARY KEY, block BLOB); +** +** , contains the following 5 types of records. See the comments surrounding +** the FTS5_*_ROWID macros below for a description of how %_data rowids are +** assigned to each fo them. +** +** 1. Structure Records: +** +** The set of segments that make up an index - the index structure - are +** recorded in a single record within the %_data table. The record consists +** of a single 32-bit configuration cookie value followed by a list of +** SQLite varints. If the FTS table features more than one index (because +** there are one or more prefix indexes), it is guaranteed that all share +** the same cookie value. +** +** Immediately following the configuration cookie, the record begins with +** three varints: +** +** + number of levels, +** + total number of segments on all levels, +** + value of write counter. +** +** Then, for each level from 0 to nMax: +** +** + number of input segments in ongoing merge. +** + total number of segments in level. +** + for each segment from oldest to newest: +** + segment id (always > 0) +** + first leaf page number (often 1, always greater than 0) +** + final leaf page number +** +** 2. The Averages Record: +** +** A single record within the %_data table. The data is a list of varints. +** The first value is the number of rows in the index. Then, for each column +** from left to right, the total number of tokens in the column for all +** rows of the table. +** +** 3. Segment leaves: +** +** TERM/DOCLIST FORMAT: +** +** Most of each segment leaf is taken up by term/doclist data. The +** general format of term/doclist, starting with the first term +** on the leaf page, is: +** +** varint : size of first term +** blob: first term data +** doclist: first doclist +** zero-or-more { +** varint: number of bytes in common with previous term +** varint: number of bytes of new term data (nNew) +** blob: nNew bytes of new term data +** doclist: next doclist +** } +** +** doclist format: +** +** varint: first rowid +** poslist: first poslist +** zero-or-more { +** varint: rowid delta (always > 0) +** poslist: next poslist +** } +** +** poslist format: +** +** varint: size of poslist in bytes multiplied by 2, not including +** this field. Plus 1 if this entry carries the "delete" flag. +** collist: collist for column 0 +** zero-or-more { +** 0x01 byte +** varint: column number (I) +** collist: collist for column I +** } +** +** collist format: +** +** varint: first offset + 2 +** zero-or-more { +** varint: offset delta + 2 +** } +** +** PAGE FORMAT +** +** Each leaf page begins with a 4-byte header containing 2 16-bit +** unsigned integer fields in big-endian format. They are: +** +** * The byte offset of the first rowid on the page, if it exists +** and occurs before the first term (otherwise 0). +** +** * The byte offset of the start of the page footer. If the page +** footer is 0 bytes in size, then this field is the same as the +** size of the leaf page in bytes. +** +** The page footer consists of a single varint for each term located +** on the page. Each varint is the byte offset of the current term +** within the page, delta-compressed against the previous value. In +** other words, the first varint in the footer is the byte offset of +** the first term, the second is the byte offset of the second less that +** of the first, and so on. +** +** The term/doclist format described above is accurate if the entire +** term/doclist data fits on a single leaf page. If this is not the case, +** the format is changed in two ways: +** +** + if the first rowid on a page occurs before the first term, it +** is stored as a literal value: +** +** varint: first rowid +** +** + the first term on each page is stored in the same way as the +** very first term of the segment: +** +** varint : size of first term +** blob: first term data +** +** 5. Segment doclist indexes: +** +** Doclist indexes are themselves b-trees, however they usually consist of +** a single leaf record only. The format of each doclist index leaf page +** is: +** +** * Flags byte. Bits are: +** 0x01: Clear if leaf is also the root page, otherwise set. +** +** * Page number of fts index leaf page. As a varint. +** +** * First rowid on page indicated by previous field. As a varint. +** +** * A list of varints, one for each subsequent termless page. A +** positive delta if the termless page contains at least one rowid, +** or an 0x00 byte otherwise. +** +** Internal doclist index nodes are: +** +** * Flags byte. Bits are: +** 0x01: Clear for root page, otherwise set. +** +** * Page number of first child page. As a varint. +** +** * Copy of first rowid on page indicated by previous field. As a varint. +** +** * A list of delta-encoded varints - the first rowid on each subsequent +** child page. +** +*/ + +/* +** Rowids for the averages and structure records in the %_data table. +*/ +#define FTS5_AVERAGES_ROWID 1 /* Rowid used for the averages record */ +#define FTS5_STRUCTURE_ROWID 10 /* The structure record */ + +/* +** Macros determining the rowids used by segment leaves and dlidx leaves +** and nodes. All nodes and leaves are stored in the %_data table with large +** positive rowids. +** +** Each segment has a unique non-zero 16-bit id. +** +** The rowid for each segment leaf is found by passing the segment id and +** the leaf page number to the FTS5_SEGMENT_ROWID macro. Leaves are numbered +** sequentially starting from 1. +*/ +#define FTS5_DATA_ID_B 16 /* Max seg id number 65535 */ +#define FTS5_DATA_DLI_B 1 /* Doclist-index flag (1 bit) */ +#define FTS5_DATA_HEIGHT_B 5 /* Max dlidx tree height of 32 */ +#define FTS5_DATA_PAGE_B 31 /* Max page number of 2147483648 */ + +#define fts5_dri(segid, dlidx, height, pgno) ( \ + ((i64)(segid) << (FTS5_DATA_PAGE_B+FTS5_DATA_HEIGHT_B+FTS5_DATA_DLI_B)) + \ + ((i64)(dlidx) << (FTS5_DATA_PAGE_B + FTS5_DATA_HEIGHT_B)) + \ + ((i64)(height) << (FTS5_DATA_PAGE_B)) + \ + ((i64)(pgno)) \ +) + +#define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno) +#define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno) + +/* +** Maximum segments permitted in a single index +*/ +#define FTS5_MAX_SEGMENT 2000 + +#ifdef SQLITE_DEBUG +int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; } +#endif + + +/* +** Each time a blob is read from the %_data table, it is padded with this +** many zero bytes. This makes it easier to decode the various record formats +** without overreading if the records are corrupt. +*/ +#define FTS5_DATA_ZERO_PADDING 8 +#define FTS5_DATA_PADDING 20 + +typedef struct Fts5Data Fts5Data; +typedef struct Fts5DlidxIter Fts5DlidxIter; +typedef struct Fts5DlidxLvl Fts5DlidxLvl; +typedef struct Fts5DlidxWriter Fts5DlidxWriter; +typedef struct Fts5Iter Fts5Iter; +typedef struct Fts5PageWriter Fts5PageWriter; +typedef struct Fts5SegIter Fts5SegIter; +typedef struct Fts5DoclistIter Fts5DoclistIter; +typedef struct Fts5SegWriter Fts5SegWriter; +typedef struct Fts5Structure Fts5Structure; +typedef struct Fts5StructureLevel Fts5StructureLevel; +typedef struct Fts5StructureSegment Fts5StructureSegment; + +struct Fts5Data { + u8 *p; /* Pointer to buffer containing record */ + int nn; /* Size of record in bytes */ + int szLeaf; /* Size of leaf without page-index */ +}; + +/* +** One object per %_data table. +*/ +struct Fts5Index { + Fts5Config *pConfig; /* Virtual table configuration */ + char *zDataTbl; /* Name of %_data table */ + int nWorkUnit; /* Leaf pages in a "unit" of work */ + + /* + ** Variables related to the accumulation of tokens and doclists within the + ** in-memory hash tables before they are flushed to disk. + */ + Fts5Hash *pHash; /* Hash table for in-memory data */ + int nPendingData; /* Current bytes of pending data */ + i64 iWriteRowid; /* Rowid for current doc being written */ + int bDelete; /* Current write is a delete */ + + /* Error state. */ + int rc; /* Current error code */ + + /* State used by the fts5DataXXX() functions. */ + sqlite3_blob *pReader; /* RO incr-blob open on %_data table */ + sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ + sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ + sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ + sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=? */ + sqlite3_stmt *pIdxSelect; + int nRead; /* Total number of blocks read */ +}; + +struct Fts5DoclistIter { + u8 *aEof; /* Pointer to 1 byte past end of doclist */ + + /* Output variables. aPoslist==0 at EOF */ + i64 iRowid; + u8 *aPoslist; + int nPoslist; + int nSize; +}; + +/* +** The contents of the "structure" record for each index are represented +** using an Fts5Structure record in memory. Which uses instances of the +** other Fts5StructureXXX types as components. +*/ +struct Fts5StructureSegment { + int iSegid; /* Segment id */ + int pgnoFirst; /* First leaf page number in segment */ + int pgnoLast; /* Last leaf page number in segment */ +}; +struct Fts5StructureLevel { + int nMerge; /* Number of segments in incr-merge */ + int nSeg; /* Total number of segments on level */ + Fts5StructureSegment *aSeg; /* Array of segments. aSeg[0] is oldest. */ +}; +struct Fts5Structure { + int nRef; /* Object reference count */ + u64 nWriteCounter; /* Total leaves written to level 0 */ + int nSegment; /* Total segments in this structure */ + int nLevel; /* Number of levels in this index */ + Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */ +}; + +/* +** An object of type Fts5SegWriter is used to write to segments. +*/ +struct Fts5PageWriter { + int pgno; /* Page number for this page */ + int iPrevPgidx; /* Previous value written into pgidx */ + Fts5Buffer buf; /* Buffer containing leaf data */ + Fts5Buffer pgidx; /* Buffer containing page-index */ + Fts5Buffer term; /* Buffer containing previous term on page */ +}; +struct Fts5DlidxWriter { + int pgno; /* Page number for this page */ + int bPrevValid; /* True if iPrev is valid */ + i64 iPrev; /* Previous rowid value written to page */ + Fts5Buffer buf; /* Buffer containing page data */ +}; +struct Fts5SegWriter { + int iSegid; /* Segid to write to */ + Fts5PageWriter writer; /* PageWriter object */ + i64 iPrevRowid; /* Previous rowid written to current leaf */ + u8 bFirstRowidInDoclist; /* True if next rowid is first in doclist */ + u8 bFirstRowidInPage; /* True if next rowid is first in page */ + /* TODO1: Can use (writer.pgidx.n==0) instead of bFirstTermInPage */ + u8 bFirstTermInPage; /* True if next term will be first in leaf */ + int nLeafWritten; /* Number of leaf pages written */ + int nEmpty; /* Number of contiguous term-less nodes */ + + int nDlidx; /* Allocated size of aDlidx[] array */ + Fts5DlidxWriter *aDlidx; /* Array of Fts5DlidxWriter objects */ + + /* Values to insert into the %_idx table */ + Fts5Buffer btterm; /* Next term to insert into %_idx table */ + int iBtPage; /* Page number corresponding to btterm */ +}; + +typedef struct Fts5CResult Fts5CResult; +struct Fts5CResult { + u16 iFirst; /* aSeg[] index of firstest iterator */ + u8 bTermEq; /* True if the terms are equal */ +}; + +/* +** Object for iterating through a single segment, visiting each term/rowid +** pair in the segment. +** +** pSeg: +** The segment to iterate through. +** +** iLeafPgno: +** Current leaf page number within segment. +** +** iLeafOffset: +** Byte offset within the current leaf that is the first byte of the +** position list data (one byte passed the position-list size field). +** rowid field of the current entry. Usually this is the size field of the +** position list data. The exception is if the rowid for the current entry +** is the last thing on the leaf page. +** +** pLeaf: +** Buffer containing current leaf page data. Set to NULL at EOF. +** +** iTermLeafPgno, iTermLeafOffset: +** Leaf page number containing the last term read from the segment. And +** the offset immediately following the term data. +** +** flags: +** Mask of FTS5_SEGITER_XXX values. Interpreted as follows: +** +** FTS5_SEGITER_ONETERM: +** If set, set the iterator to point to EOF after the current doclist +** has been exhausted. Do not proceed to the next term in the segment. +** +** FTS5_SEGITER_REVERSE: +** This flag is only ever set if FTS5_SEGITER_ONETERM is also set. If +** it is set, iterate through rowid in descending order instead of the +** default ascending order. +** +** iRowidOffset/nRowidOffset/aRowidOffset: +** These are used if the FTS5_SEGITER_REVERSE flag is set. +** +** For each rowid on the page corresponding to the current term, the +** corresponding aRowidOffset[] entry is set to the byte offset of the +** start of the "position-list-size" field within the page. +** +** iTermIdx: +** Index of current term on iTermLeafPgno. +*/ +struct Fts5SegIter { + Fts5StructureSegment *pSeg; /* Segment to iterate through */ + int flags; /* Mask of configuration flags */ + int iLeafPgno; /* Current leaf page number */ + Fts5Data *pLeaf; /* Current leaf data */ + Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */ + int iLeafOffset; /* Byte offset within current leaf */ + + /* Next method */ + void (*xNext)(Fts5Index*, Fts5SegIter*, int*); + + /* The page and offset from which the current term was read. The offset + ** is the offset of the first rowid in the current doclist. */ + int iTermLeafPgno; + int iTermLeafOffset; + + int iPgidxOff; /* Next offset in pgidx */ + int iEndofDoclist; + + /* The following are only used if the FTS5_SEGITER_REVERSE flag is set. */ + int iRowidOffset; /* Current entry in aRowidOffset[] */ + int nRowidOffset; /* Allocated size of aRowidOffset[] array */ + int *aRowidOffset; /* Array of offset to rowid fields */ + + Fts5DlidxIter *pDlidx; /* If there is a doclist-index */ + + /* Variables populated based on current entry. */ + Fts5Buffer term; /* Current term */ + i64 iRowid; /* Current rowid */ + int nPos; /* Number of bytes in current position list */ + u8 bDel; /* True if the delete flag is set */ +}; + +/* +** Argument is a pointer to an Fts5Data structure that contains a +** leaf page. +*/ +#define ASSERT_SZLEAF_OK(x) assert( \ + (x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \ +) + +#define FTS5_SEGITER_ONETERM 0x01 +#define FTS5_SEGITER_REVERSE 0x02 + +/* +** Argument is a pointer to an Fts5Data structure that contains a leaf +** page. This macro evaluates to true if the leaf contains no terms, or +** false if it contains at least one term. +*/ +#define fts5LeafIsTermless(x) ((x)->szLeaf >= (x)->nn) + +#define fts5LeafTermOff(x, i) (fts5GetU16(&(x)->p[(x)->szLeaf + (i)*2])) + +#define fts5LeafFirstRowidOff(x) (fts5GetU16((x)->p)) + +/* +** Object for iterating through the merged results of one or more segments, +** visiting each term/rowid pair in the merged data. +** +** nSeg is always a power of two greater than or equal to the number of +** segments that this object is merging data from. Both the aSeg[] and +** aFirst[] arrays are sized at nSeg entries. The aSeg[] array is padded +** with zeroed objects - these are handled as if they were iterators opened +** on empty segments. +** +** The results of comparing segments aSeg[N] and aSeg[N+1], where N is an +** even number, is stored in aFirst[(nSeg+N)/2]. The "result" of the +** comparison in this context is the index of the iterator that currently +** points to the smaller term/rowid combination. Iterators at EOF are +** considered to be greater than all other iterators. +** +** aFirst[1] contains the index in aSeg[] of the iterator that points to +** the smallest key overall. aFirst[0] is unused. +** +** poslist: +** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered. +** There is no way to tell if this is populated or not. +*/ +struct Fts5Iter { + Fts5IndexIter base; /* Base class containing output vars */ + + Fts5Index *pIndex; /* Index that owns this iterator */ + Fts5Structure *pStruct; /* Database structure for this iterator */ + Fts5Buffer poslist; /* Buffer containing current poslist */ + Fts5Colset *pColset; /* Restrict matches to these columns */ + + /* Invoked to set output variables. */ + void (*xSetOutputs)(Fts5Iter*, Fts5SegIter*); + + int nSeg; /* Size of aSeg[] array */ + int bRev; /* True to iterate in reverse order */ + u8 bSkipEmpty; /* True to skip deleted entries */ + + i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */ + Fts5CResult *aFirst; /* Current merge state (see above) */ + Fts5SegIter aSeg[1]; /* Array of segment iterators */ +}; + + +/* +** An instance of the following type is used to iterate through the contents +** of a doclist-index record. +** +** pData: +** Record containing the doclist-index data. +** +** bEof: +** Set to true once iterator has reached EOF. +** +** iOff: +** Set to the current offset within record pData. +*/ +struct Fts5DlidxLvl { + Fts5Data *pData; /* Data for current page of this level */ + int iOff; /* Current offset into pData */ + int bEof; /* At EOF already */ + int iFirstOff; /* Used by reverse iterators */ + + /* Output variables */ + int iLeafPgno; /* Page number of current leaf page */ + i64 iRowid; /* First rowid on leaf iLeafPgno */ +}; +struct Fts5DlidxIter { + int nLvl; + int iSegid; + Fts5DlidxLvl aLvl[1]; +}; + +static void fts5PutU16(u8 *aOut, u16 iVal){ + aOut[0] = (iVal>>8); + aOut[1] = (iVal&0xFF); +} + +static u16 fts5GetU16(const u8 *aIn){ + return ((u16)aIn[0] << 8) + aIn[1]; +} + +/* +** Allocate and return a buffer at least nByte bytes in size. +** +** If an OOM error is encountered, return NULL and set the error code in +** the Fts5Index handle passed as the first argument. +*/ +static void *fts5IdxMalloc(Fts5Index *p, int nByte){ + return sqlite3Fts5MallocZero(&p->rc, nByte); +} + +/* +** Compare the contents of the pLeft buffer with the pRight/nRight blob. +** +** Return -ve if pLeft is smaller than pRight, 0 if they are equal or +** +ve if pRight is smaller than pLeft. In other words: +** +** res = *pLeft - *pRight +*/ +#ifdef SQLITE_DEBUG +static int fts5BufferCompareBlob( + Fts5Buffer *pLeft, /* Left hand side of comparison */ + const u8 *pRight, int nRight /* Right hand side of comparison */ +){ + int nCmp = MIN(pLeft->n, nRight); + int res = memcmp(pLeft->p, pRight, nCmp); + return (res==0 ? (pLeft->n - nRight) : res); +} +#endif + +/* +** Compare the contents of the two buffers using memcmp(). If one buffer +** is a prefix of the other, it is considered the lesser. +** +** Return -ve if pLeft is smaller than pRight, 0 if they are equal or +** +ve if pRight is smaller than pLeft. In other words: +** +** res = *pLeft - *pRight +*/ +static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){ + int nCmp = MIN(pLeft->n, pRight->n); + int res = memcmp(pLeft->p, pRight->p, nCmp); + return (res==0 ? (pLeft->n - pRight->n) : res); +} + +static int fts5LeafFirstTermOff(Fts5Data *pLeaf){ + int ret; + fts5GetVarint32(&pLeaf->p[pLeaf->szLeaf], ret); + return ret; +} + +/* +** Close the read-only blob handle, if it is open. +*/ +static void fts5CloseReader(Fts5Index *p){ + if( p->pReader ){ + sqlite3_blob *pReader = p->pReader; + p->pReader = 0; + sqlite3_blob_close(pReader); + } +} + + +/* +** Retrieve a record from the %_data table. +** +** If an error occurs, NULL is returned and an error left in the +** Fts5Index object. +*/ +static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ + Fts5Data *pRet = 0; + if( p->rc==SQLITE_OK ){ + int rc = SQLITE_OK; + + if( p->pReader ){ + /* This call may return SQLITE_ABORT if there has been a savepoint + ** rollback since it was last used. In this case a new blob handle + ** is required. */ + sqlite3_blob *pBlob = p->pReader; + p->pReader = 0; + rc = sqlite3_blob_reopen(pBlob, iRowid); + assert( p->pReader==0 ); + p->pReader = pBlob; + if( rc!=SQLITE_OK ){ + fts5CloseReader(p); + } + if( rc==SQLITE_ABORT ) rc = SQLITE_OK; + } + + /* If the blob handle is not open at this point, open it and seek + ** to the requested entry. */ + if( p->pReader==0 && rc==SQLITE_OK ){ + Fts5Config *pConfig = p->pConfig; + rc = sqlite3_blob_open(pConfig->db, + pConfig->zDb, p->zDataTbl, "block", iRowid, 0, &p->pReader + ); + } + + /* If either of the sqlite3_blob_open() or sqlite3_blob_reopen() calls + ** above returned SQLITE_ERROR, return SQLITE_CORRUPT_VTAB instead. + ** 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; + + if( rc==SQLITE_OK ){ + u8 *aOut = 0; /* Read blob data into this buffer */ + int nByte = sqlite3_blob_bytes(p->pReader); + int nAlloc = sizeof(Fts5Data) + nByte + FTS5_DATA_PADDING; + pRet = (Fts5Data*)sqlite3_malloc(nAlloc); + if( pRet ){ + pRet->nn = nByte; + aOut = pRet->p = (u8*)&pRet[1]; + }else{ + rc = SQLITE_NOMEM; + } + + if( rc==SQLITE_OK ){ + rc = sqlite3_blob_read(p->pReader, aOut, nByte, 0); + } + if( rc!=SQLITE_OK ){ + sqlite3_free(pRet); + pRet = 0; + }else{ + /* TODO1: Fix this */ + pRet->szLeaf = fts5GetU16(&pRet->p[2]); + } + } + p->rc = rc; + p->nRead++; + } + + assert( (pRet==0)==(p->rc!=SQLITE_OK) ); + return pRet; +} + +/* +** Release a reference to data record returned by an earlier call to +** fts5DataRead(). +*/ +static void fts5DataRelease(Fts5Data *pData){ + sqlite3_free(pData); +} + +static int fts5IndexPrepareStmt( + Fts5Index *p, + sqlite3_stmt **ppStmt, + char *zSql +){ + if( p->rc==SQLITE_OK ){ + if( zSql ){ + p->rc = sqlite3_prepare_v2(p->pConfig->db, zSql, -1, ppStmt, 0); + }else{ + p->rc = SQLITE_NOMEM; + } + } + sqlite3_free(zSql); + return p->rc; +} + + +/* +** INSERT OR REPLACE a record into the %_data table. +*/ +static void fts5DataWrite(Fts5Index *p, i64 iRowid, const u8 *pData, int nData){ + if( p->rc!=SQLITE_OK ) return; + + if( p->pWriter==0 ){ + Fts5Config *pConfig = p->pConfig; + fts5IndexPrepareStmt(p, &p->pWriter, sqlite3_mprintf( + "REPLACE INTO '%q'.'%q_data'(id, block) VALUES(?,?)", + pConfig->zDb, pConfig->zName + )); + if( p->rc ) return; + } + + sqlite3_bind_int64(p->pWriter, 1, iRowid); + sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC); + sqlite3_step(p->pWriter); + p->rc = sqlite3_reset(p->pWriter); +} + +/* +** Execute the following SQL: +** +** DELETE FROM %_data WHERE id BETWEEN $iFirst AND $iLast +*/ +static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){ + if( p->rc!=SQLITE_OK ) return; + + if( p->pDeleter==0 ){ + int rc; + Fts5Config *pConfig = p->pConfig; + char *zSql = sqlite3_mprintf( + "DELETE FROM '%q'.'%q_data' WHERE id>=? AND id<=?", + pConfig->zDb, pConfig->zName + ); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p->pDeleter, 0); + sqlite3_free(zSql); + } + if( rc!=SQLITE_OK ){ + p->rc = rc; + return; + } + } + + sqlite3_bind_int64(p->pDeleter, 1, iFirst); + sqlite3_bind_int64(p->pDeleter, 2, iLast); + sqlite3_step(p->pDeleter); + p->rc = sqlite3_reset(p->pDeleter); +} + +/* +** Remove all records associated with segment iSegid. +*/ +static void fts5DataRemoveSegment(Fts5Index *p, int iSegid){ + i64 iFirst = FTS5_SEGMENT_ROWID(iSegid, 0); + i64 iLast = FTS5_SEGMENT_ROWID(iSegid+1, 0)-1; + fts5DataDelete(p, iFirst, iLast); + if( p->pIdxDeleter==0 ){ + Fts5Config *pConfig = p->pConfig; + fts5IndexPrepareStmt(p, &p->pIdxDeleter, sqlite3_mprintf( + "DELETE FROM '%q'.'%q_idx' WHERE segid=?", + pConfig->zDb, pConfig->zName + )); + } + if( p->rc==SQLITE_OK ){ + sqlite3_bind_int(p->pIdxDeleter, 1, iSegid); + sqlite3_step(p->pIdxDeleter); + p->rc = sqlite3_reset(p->pIdxDeleter); + } +} + +/* +** Release a reference to an Fts5Structure object returned by an earlier +** call to fts5StructureRead() or fts5StructureDecode(). +*/ +static void fts5StructureRelease(Fts5Structure *pStruct){ + if( pStruct && 0>=(--pStruct->nRef) ){ + int i; + assert( pStruct->nRef==0 ); + for(i=0; inLevel; i++){ + sqlite3_free(pStruct->aLevel[i].aSeg); + } + sqlite3_free(pStruct); + } +} + +static void fts5StructureRef(Fts5Structure *pStruct){ + pStruct->nRef++; +} + +/* +** Deserialize and return the structure record currently stored in serialized +** form within buffer pData/nData. +** +** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array +** are over-allocated by one slot. This allows the structure contents +** to be more easily edited. +** +** If an error occurs, *ppOut is set to NULL and an SQLite error code +** returned. Otherwise, *ppOut is set to point to the new object and +** SQLITE_OK returned. +*/ +static int fts5StructureDecode( + const u8 *pData, /* Buffer containing serialized structure */ + int nData, /* Size of buffer pData in bytes */ + int *piCookie, /* Configuration cookie value */ + Fts5Structure **ppOut /* OUT: Deserialized object */ +){ + int rc = SQLITE_OK; + int i = 0; + int iLvl; + int nLevel = 0; + int nSegment = 0; + int nByte; /* Bytes of space to allocate at pRet */ + Fts5Structure *pRet = 0; /* Structure object to return */ + + /* Grab the cookie value */ + if( piCookie ) *piCookie = sqlite3Fts5Get32(pData); + i = 4; + + /* Read the total number of levels and segments from the start of the + ** structure record. */ + i += fts5GetVarint32(&pData[i], nLevel); + i += fts5GetVarint32(&pData[i], nSegment); + nByte = ( + sizeof(Fts5Structure) + /* Main structure */ + sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */ + ); + pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte); + + if( pRet ){ + pRet->nRef = 1; + pRet->nLevel = nLevel; + pRet->nSegment = nSegment; + i += sqlite3Fts5GetVarint(&pData[i], &pRet->nWriteCounter); + + for(iLvl=0; rc==SQLITE_OK && iLvlaLevel[iLvl]; + int nTotal; + int iSeg; + + if( i>=nData ){ + rc = FTS5_CORRUPT; + }else{ + i += fts5GetVarint32(&pData[i], pLvl->nMerge); + i += fts5GetVarint32(&pData[i], nTotal); + assert( nTotal>=pLvl->nMerge ); + pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc, + nTotal * sizeof(Fts5StructureSegment) + ); + } + + if( rc==SQLITE_OK ){ + pLvl->nSeg = nTotal; + for(iSeg=0; iSeg=nData ){ + rc = FTS5_CORRUPT; + break; + } + i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].iSegid); + i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoFirst); + i += fts5GetVarint32(&pData[i], pLvl->aSeg[iSeg].pgnoLast); + } + } + } + if( rc!=SQLITE_OK ){ + fts5StructureRelease(pRet); + pRet = 0; + } + } + + *ppOut = pRet; + return rc; +} + +/* +** +*/ +static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){ + if( *pRc==SQLITE_OK ){ + Fts5Structure *pStruct = *ppStruct; + int nLevel = pStruct->nLevel; + int nByte = ( + sizeof(Fts5Structure) + /* Main structure */ + sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */ + ); + + pStruct = sqlite3_realloc(pStruct, nByte); + if( pStruct ){ + memset(&pStruct->aLevel[nLevel], 0, sizeof(Fts5StructureLevel)); + pStruct->nLevel++; + *ppStruct = pStruct; + }else{ + *pRc = SQLITE_NOMEM; + } + } +} + +/* +** Extend level iLvl so that there is room for at least nExtra more +** segments. +*/ +static void fts5StructureExtendLevel( + int *pRc, + Fts5Structure *pStruct, + int iLvl, + int nExtra, + int bInsert +){ + if( *pRc==SQLITE_OK ){ + Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; + Fts5StructureSegment *aNew; + int nByte; + + nByte = (pLvl->nSeg + nExtra) * sizeof(Fts5StructureSegment); + aNew = sqlite3_realloc(pLvl->aSeg, nByte); + if( aNew ){ + if( bInsert==0 ){ + memset(&aNew[pLvl->nSeg], 0, sizeof(Fts5StructureSegment) * nExtra); + }else{ + int nMove = pLvl->nSeg * sizeof(Fts5StructureSegment); + memmove(&aNew[nExtra], aNew, nMove); + memset(aNew, 0, sizeof(Fts5StructureSegment) * nExtra); + } + pLvl->aSeg = aNew; + }else{ + *pRc = SQLITE_NOMEM; + } + } +} + +/* +** Read, deserialize and return the structure record. +** +** The Fts5Structure.aLevel[] and each Fts5StructureLevel.aSeg[] array +** are over-allocated as described for function fts5StructureDecode() +** above. +** +** If an error occurs, NULL is returned and an error code left in the +** Fts5Index handle. If an error has already occurred when this function +** is called, it is a no-op. +*/ +static Fts5Structure *fts5StructureRead(Fts5Index *p){ + Fts5Config *pConfig = p->pConfig; + Fts5Structure *pRet = 0; /* Object to return */ + int iCookie; /* Configuration cookie */ + Fts5Data *pData; + + pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID); + if( p->rc ) return 0; + /* 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 && pConfig->iCookie!=iCookie ){ + p->rc = sqlite3Fts5ConfigLoad(pConfig, iCookie); + } + + fts5DataRelease(pData); + if( p->rc!=SQLITE_OK ){ + fts5StructureRelease(pRet); + pRet = 0; + } + return pRet; +} + +/* +** Return the total number of segments in index structure pStruct. This +** function is only ever used as part of assert() conditions. +*/ +#ifdef SQLITE_DEBUG +static int fts5StructureCountSegments(Fts5Structure *pStruct){ + int nSegment = 0; /* Total number of segments */ + if( pStruct ){ + int iLvl; /* Used to iterate through levels */ + for(iLvl=0; iLvlnLevel; iLvl++){ + nSegment += pStruct->aLevel[iLvl].nSeg; + } + } + + return nSegment; +} +#endif + +#define fts5BufferSafeAppendBlob(pBuf, pBlob, nBlob) { \ + assert( (pBuf)->nSpace>=((pBuf)->n+nBlob) ); \ + memcpy(&(pBuf)->p[(pBuf)->n], pBlob, nBlob); \ + (pBuf)->n += nBlob; \ +} + +#define fts5BufferSafeAppendVarint(pBuf, iVal) { \ + (pBuf)->n += sqlite3Fts5PutVarint(&(pBuf)->p[(pBuf)->n], (iVal)); \ + assert( (pBuf)->nSpace>=(pBuf)->n ); \ +} + + +/* +** Serialize and store the "structure" record. +** +** If an error occurs, leave an error code in the Fts5Index object. If an +** error has already occurred, this function is a no-op. +*/ +static void fts5StructureWrite(Fts5Index *p, Fts5Structure *pStruct){ + if( p->rc==SQLITE_OK ){ + Fts5Buffer buf; /* Buffer to serialize record into */ + int iLvl; /* Used to iterate through levels */ + int iCookie; /* Cookie value to store */ + + assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); + memset(&buf, 0, sizeof(Fts5Buffer)); + + /* Append the current configuration cookie */ + iCookie = p->pConfig->iCookie; + if( iCookie<0 ) iCookie = 0; + + if( 0==sqlite3Fts5BufferSize(&p->rc, &buf, 4+9+9+9) ){ + sqlite3Fts5Put32(buf.p, iCookie); + buf.n = 4; + fts5BufferSafeAppendVarint(&buf, pStruct->nLevel); + fts5BufferSafeAppendVarint(&buf, pStruct->nSegment); + fts5BufferSafeAppendVarint(&buf, (i64)pStruct->nWriteCounter); + } + + for(iLvl=0; iLvlnLevel; iLvl++){ + int iSeg; /* Used to iterate through segments */ + Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; + fts5BufferAppendVarint(&p->rc, &buf, pLvl->nMerge); + fts5BufferAppendVarint(&p->rc, &buf, pLvl->nSeg); + assert( pLvl->nMerge<=pLvl->nSeg ); + + for(iSeg=0; iSegnSeg; iSeg++){ + fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].iSegid); + fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoFirst); + fts5BufferAppendVarint(&p->rc, &buf, pLvl->aSeg[iSeg].pgnoLast); + } + } + + fts5DataWrite(p, FTS5_STRUCTURE_ROWID, buf.p, buf.n); + fts5BufferFree(&buf); + } +} + +#if 0 +static void fts5DebugStructure(int*,Fts5Buffer*,Fts5Structure*); +static void fts5PrintStructure(const char *zCaption, Fts5Structure *pStruct){ + int rc = SQLITE_OK; + Fts5Buffer buf; + memset(&buf, 0, sizeof(buf)); + fts5DebugStructure(&rc, &buf, pStruct); + fprintf(stdout, "%s: %s\n", zCaption, buf.p); + fflush(stdout); + fts5BufferFree(&buf); +} +#else +# define fts5PrintStructure(x,y) +#endif + +static int fts5SegmentSize(Fts5StructureSegment *pSeg){ + return 1 + pSeg->pgnoLast - pSeg->pgnoFirst; +} + +/* +** Return a copy of index structure pStruct. Except, promote as many +** segments as possible to level iPromote. If an OOM occurs, NULL is +** returned. +*/ +static void fts5StructurePromoteTo( + Fts5Index *p, + int iPromote, + int szPromote, + Fts5Structure *pStruct +){ + int il, is; + Fts5StructureLevel *pOut = &pStruct->aLevel[iPromote]; + + if( pOut->nMerge==0 ){ + for(il=iPromote+1; ilnLevel; il++){ + Fts5StructureLevel *pLvl = &pStruct->aLevel[il]; + if( pLvl->nMerge ) return; + for(is=pLvl->nSeg-1; is>=0; is--){ + int sz = fts5SegmentSize(&pLvl->aSeg[is]); + if( sz>szPromote ) return; + fts5StructureExtendLevel(&p->rc, pStruct, iPromote, 1, 1); + if( p->rc ) return; + memcpy(pOut->aSeg, &pLvl->aSeg[is], sizeof(Fts5StructureSegment)); + pOut->nSeg++; + pLvl->nSeg--; + } + } + } +} + +/* +** A new segment has just been written to level iLvl of index structure +** pStruct. This function determines if any segments should be promoted +** as a result. Segments are promoted in two scenarios: +** +** a) If the segment just written is smaller than one or more segments +** within the previous populated level, it is promoted to the previous +** populated level. +** +** b) If the segment just written is larger than the newest segment on +** the next populated level, then that segment, and any other adjacent +** segments that are also smaller than the one just written, are +** promoted. +** +** If one or more segments are promoted, the structure object is updated +** to reflect this. +*/ +static void fts5StructurePromote( + Fts5Index *p, /* FTS5 backend object */ + int iLvl, /* Index level just updated */ + Fts5Structure *pStruct /* Index structure */ +){ + if( p->rc==SQLITE_OK ){ + int iTst; + int iPromote = -1; + int szPromote = 0; /* Promote anything this size or smaller */ + Fts5StructureSegment *pSeg; /* Segment just written */ + int szSeg; /* Size of segment just written */ + int nSeg = pStruct->aLevel[iLvl].nSeg; + + if( nSeg==0 ) return; + pSeg = &pStruct->aLevel[iLvl].aSeg[pStruct->aLevel[iLvl].nSeg-1]; + szSeg = (1 + pSeg->pgnoLast - pSeg->pgnoFirst); + + /* Check for condition (a) */ + for(iTst=iLvl-1; iTst>=0 && pStruct->aLevel[iTst].nSeg==0; iTst--); + if( iTst>=0 ){ + int i; + int szMax = 0; + Fts5StructureLevel *pTst = &pStruct->aLevel[iTst]; + assert( pTst->nMerge==0 ); + for(i=0; inSeg; i++){ + int sz = pTst->aSeg[i].pgnoLast - pTst->aSeg[i].pgnoFirst + 1; + if( sz>szMax ) szMax = sz; + } + if( szMax>=szSeg ){ + /* Condition (a) is true. Promote the newest segment on level + ** iLvl to level iTst. */ + iPromote = iTst; + szPromote = szMax; + } + } + + /* If condition (a) is not met, assume (b) is true. StructurePromoteTo() + ** is a no-op if it is not. */ + if( iPromote<0 ){ + iPromote = iLvl; + szPromote = szSeg; + } + fts5StructurePromoteTo(p, iPromote, szPromote, pStruct); + } +} + + +/* +** Advance the iterator passed as the only argument. If the end of the +** doclist-index page is reached, return non-zero. +*/ +static int fts5DlidxLvlNext(Fts5DlidxLvl *pLvl){ + Fts5Data *pData = pLvl->pData; + + if( pLvl->iOff==0 ){ + assert( pLvl->bEof==0 ); + pLvl->iOff = 1; + pLvl->iOff += fts5GetVarint32(&pData->p[1], pLvl->iLeafPgno); + pLvl->iOff += fts5GetVarint(&pData->p[pLvl->iOff], (u64*)&pLvl->iRowid); + pLvl->iFirstOff = pLvl->iOff; + }else{ + int iOff; + for(iOff=pLvl->iOff; iOffnn; iOff++){ + if( pData->p[iOff] ) break; + } + + if( iOffnn ){ + i64 iVal; + pLvl->iLeafPgno += (iOff - pLvl->iOff) + 1; + iOff += fts5GetVarint(&pData->p[iOff], (u64*)&iVal); + pLvl->iRowid += iVal; + pLvl->iOff = iOff; + }else{ + pLvl->bEof = 1; + } + } + + return pLvl->bEof; +} + +/* +** Advance the iterator passed as the only argument. +*/ +static int fts5DlidxIterNextR(Fts5Index *p, Fts5DlidxIter *pIter, int iLvl){ + Fts5DlidxLvl *pLvl = &pIter->aLvl[iLvl]; + + assert( iLvlnLvl ); + if( fts5DlidxLvlNext(pLvl) ){ + if( (iLvl+1) < pIter->nLvl ){ + fts5DlidxIterNextR(p, pIter, iLvl+1); + if( pLvl[1].bEof==0 ){ + fts5DataRelease(pLvl->pData); + memset(pLvl, 0, sizeof(Fts5DlidxLvl)); + pLvl->pData = fts5DataRead(p, + FTS5_DLIDX_ROWID(pIter->iSegid, iLvl, pLvl[1].iLeafPgno) + ); + if( pLvl->pData ) fts5DlidxLvlNext(pLvl); + } + } + } + + return pIter->aLvl[0].bEof; +} +static int fts5DlidxIterNext(Fts5Index *p, Fts5DlidxIter *pIter){ + return fts5DlidxIterNextR(p, pIter, 0); +} + +/* +** The iterator passed as the first argument has the following fields set +** as follows. This function sets up the rest of the iterator so that it +** points to the first rowid in the doclist-index. +** +** pData: +** pointer to doclist-index record, +** +** When this function is called pIter->iLeafPgno is the page number the +** doclist is associated with (the one featuring the term). +*/ +static int fts5DlidxIterFirst(Fts5DlidxIter *pIter){ + int i; + for(i=0; inLvl; i++){ + fts5DlidxLvlNext(&pIter->aLvl[i]); + } + return pIter->aLvl[0].bEof; +} + + +static int fts5DlidxIterEof(Fts5Index *p, Fts5DlidxIter *pIter){ + return p->rc!=SQLITE_OK || pIter->aLvl[0].bEof; +} + +static void fts5DlidxIterLast(Fts5Index *p, Fts5DlidxIter *pIter){ + int i; + + /* Advance each level to the last entry on the last page */ + for(i=pIter->nLvl-1; p->rc==SQLITE_OK && i>=0; i--){ + Fts5DlidxLvl *pLvl = &pIter->aLvl[i]; + while( fts5DlidxLvlNext(pLvl)==0 ); + pLvl->bEof = 0; + + if( i>0 ){ + Fts5DlidxLvl *pChild = &pLvl[-1]; + fts5DataRelease(pChild->pData); + memset(pChild, 0, sizeof(Fts5DlidxLvl)); + pChild->pData = fts5DataRead(p, + FTS5_DLIDX_ROWID(pIter->iSegid, i-1, pLvl->iLeafPgno) + ); + } + } +} + +/* +** Move the iterator passed as the only argument to the previous entry. +*/ +static int fts5DlidxLvlPrev(Fts5DlidxLvl *pLvl){ + int iOff = pLvl->iOff; + + assert( pLvl->bEof==0 ); + if( iOff<=pLvl->iFirstOff ){ + pLvl->bEof = 1; + }else{ + u8 *a = pLvl->pData->p; + i64 iVal; + int iLimit; + int ii; + int nZero = 0; + + /* Currently iOff points to the first byte of a varint. This block + ** decrements iOff until it points to the first byte of the previous + ** varint. Taking care not to read any memory locations that occur + ** before the buffer in memory. */ + iLimit = (iOff>9 ? iOff-9 : 0); + for(iOff--; iOff>iLimit; iOff--){ + if( (a[iOff-1] & 0x80)==0 ) break; + } + + fts5GetVarint(&a[iOff], (u64*)&iVal); + pLvl->iRowid -= iVal; + pLvl->iLeafPgno--; + + /* Skip backwards past any 0x00 varints. */ + for(ii=iOff-1; ii>=pLvl->iFirstOff && a[ii]==0x00; ii--){ + nZero++; + } + if( ii>=pLvl->iFirstOff && (a[ii] & 0x80) ){ + /* The byte immediately before the last 0x00 byte has the 0x80 bit + ** set. So the last 0x00 is only a varint 0 if there are 8 more 0x80 + ** bytes before a[ii]. */ + int bZero = 0; /* True if last 0x00 counts */ + if( (ii-8)>=pLvl->iFirstOff ){ + int j; + for(j=1; j<=8 && (a[ii-j] & 0x80); j++); + bZero = (j>8); + } + if( bZero==0 ) nZero--; + } + pLvl->iLeafPgno -= nZero; + pLvl->iOff = iOff - nZero; + } + + return pLvl->bEof; +} + +static int fts5DlidxIterPrevR(Fts5Index *p, Fts5DlidxIter *pIter, int iLvl){ + Fts5DlidxLvl *pLvl = &pIter->aLvl[iLvl]; + + assert( iLvlnLvl ); + if( fts5DlidxLvlPrev(pLvl) ){ + if( (iLvl+1) < pIter->nLvl ){ + fts5DlidxIterPrevR(p, pIter, iLvl+1); + if( pLvl[1].bEof==0 ){ + fts5DataRelease(pLvl->pData); + memset(pLvl, 0, sizeof(Fts5DlidxLvl)); + pLvl->pData = fts5DataRead(p, + FTS5_DLIDX_ROWID(pIter->iSegid, iLvl, pLvl[1].iLeafPgno) + ); + if( pLvl->pData ){ + while( fts5DlidxLvlNext(pLvl)==0 ); + pLvl->bEof = 0; + } + } + } + } + + return pIter->aLvl[0].bEof; +} +static int fts5DlidxIterPrev(Fts5Index *p, Fts5DlidxIter *pIter){ + return fts5DlidxIterPrevR(p, pIter, 0); +} + +/* +** Free a doclist-index iterator object allocated by fts5DlidxIterInit(). +*/ +static void fts5DlidxIterFree(Fts5DlidxIter *pIter){ + if( pIter ){ + int i; + for(i=0; inLvl; i++){ + fts5DataRelease(pIter->aLvl[i].pData); + } + sqlite3_free(pIter); + } +} + +static Fts5DlidxIter *fts5DlidxIterInit( + Fts5Index *p, /* Fts5 Backend to iterate within */ + int bRev, /* True for ORDER BY ASC */ + int iSegid, /* Segment id */ + int iLeafPg /* Leaf page number to load dlidx for */ +){ + Fts5DlidxIter *pIter = 0; + int i; + int bDone = 0; + + for(i=0; p->rc==SQLITE_OK && bDone==0; i++){ + int nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl); + Fts5DlidxIter *pNew; + + pNew = (Fts5DlidxIter*)sqlite3_realloc(pIter, nByte); + if( pNew==0 ){ + p->rc = SQLITE_NOMEM; + }else{ + i64 iRowid = FTS5_DLIDX_ROWID(iSegid, i, iLeafPg); + Fts5DlidxLvl *pLvl = &pNew->aLvl[i]; + pIter = pNew; + memset(pLvl, 0, sizeof(Fts5DlidxLvl)); + pLvl->pData = fts5DataRead(p, iRowid); + if( pLvl->pData && (pLvl->pData->p[0] & 0x0001)==0 ){ + bDone = 1; + } + pIter->nLvl = i+1; + } + } + + if( p->rc==SQLITE_OK ){ + pIter->iSegid = iSegid; + if( bRev==0 ){ + fts5DlidxIterFirst(pIter); + }else{ + fts5DlidxIterLast(p, pIter); + } + } + + if( p->rc!=SQLITE_OK ){ + fts5DlidxIterFree(pIter); + pIter = 0; + } + + return pIter; +} + +static i64 fts5DlidxIterRowid(Fts5DlidxIter *pIter){ + return pIter->aLvl[0].iRowid; +} +static int fts5DlidxIterPgno(Fts5DlidxIter *pIter){ + return pIter->aLvl[0].iLeafPgno; +} + +/* +** Load the next leaf page into the segment iterator. +*/ +static void fts5SegIterNextPage( + Fts5Index *p, /* FTS5 backend object */ + Fts5SegIter *pIter /* Iterator to advance to next page */ +){ + Fts5Data *pLeaf; + Fts5StructureSegment *pSeg = pIter->pSeg; + fts5DataRelease(pIter->pLeaf); + pIter->iLeafPgno++; + if( pIter->pNextLeaf ){ + pIter->pLeaf = pIter->pNextLeaf; + pIter->pNextLeaf = 0; + }else if( pIter->iLeafPgno<=pSeg->pgnoLast ){ + pIter->pLeaf = fts5DataRead(p, + FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno) + ); + }else{ + pIter->pLeaf = 0; + } + pLeaf = pIter->pLeaf; + + if( pLeaf ){ + pIter->iPgidxOff = pLeaf->szLeaf; + if( fts5LeafIsTermless(pLeaf) ){ + pIter->iEndofDoclist = pLeaf->nn+1; + }else{ + pIter->iPgidxOff += fts5GetVarint32(&pLeaf->p[pIter->iPgidxOff], + pIter->iEndofDoclist + ); + } + } +} + +/* +** Argument p points to a buffer containing a varint to be interpreted as a +** position list size field. Read the varint and return the number of bytes +** read. Before returning, set *pnSz to the number of bytes in the position +** list, and *pbDel to true if the delete flag is set, or false otherwise. +*/ +static int fts5GetPoslistSize(const u8 *p, int *pnSz, int *pbDel){ + int nSz; + int n = 0; + fts5FastGetVarint32(p, n, nSz); + assert_nc( nSz>=0 ); + *pnSz = nSz/2; + *pbDel = nSz & 0x0001; + return n; +} + +/* +** Fts5SegIter.iLeafOffset currently points to the first byte of a +** position-list size field. Read the value of the field and store it +** in the following variables: +** +** Fts5SegIter.nPos +** Fts5SegIter.bDel +** +** Leave Fts5SegIter.iLeafOffset pointing to the first byte of the +** position list content (if any). +*/ +static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){ + if( p->rc==SQLITE_OK ){ + int iOff = pIter->iLeafOffset; /* Offset to read at */ + ASSERT_SZLEAF_OK(pIter->pLeaf); + if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ + int iEod = MIN(pIter->iEndofDoclist, pIter->pLeaf->szLeaf); + pIter->bDel = 0; + pIter->nPos = 1; + if( iOffpLeaf->p[iOff]==0 ){ + pIter->bDel = 1; + iOff++; + if( iOffpLeaf->p[iOff]==0 ){ + pIter->nPos = 1; + iOff++; + }else{ + pIter->nPos = 0; + } + } + }else{ + int nSz; + fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz); + pIter->bDel = (nSz & 0x0001); + pIter->nPos = nSz>>1; + assert_nc( pIter->nPos>=0 ); + } + pIter->iLeafOffset = iOff; + } +} + +static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ + u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ + int iOff = pIter->iLeafOffset; + + ASSERT_SZLEAF_OK(pIter->pLeaf); + if( iOff>=pIter->pLeaf->szLeaf ){ + fts5SegIterNextPage(p, pIter); + if( pIter->pLeaf==0 ){ + if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; + return; + } + iOff = 4; + a = pIter->pLeaf->p; + } + iOff += sqlite3Fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); + pIter->iLeafOffset = iOff; +} + +/* +** Fts5SegIter.iLeafOffset currently points to the first byte of the +** "nSuffix" field of a term. Function parameter nKeep contains the value +** of the "nPrefix" field (if there was one - it is passed 0 if this is +** the first term in the segment). +** +** This function populates: +** +** Fts5SegIter.term +** Fts5SegIter.rowid +** +** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the content of +** the first position list. The position list belonging to document +** (Fts5SegIter.iRowid). +*/ +static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){ + u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ + int iOff = pIter->iLeafOffset; /* Offset to read at */ + int nNew; /* Bytes of new data */ + + iOff += fts5GetVarint32(&a[iOff], nNew); + if( iOff+nNew>pIter->pLeaf->nn ){ + p->rc = FTS5_CORRUPT; + return; + } + pIter->term.n = nKeep; + fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]); + iOff += nNew; + pIter->iTermLeafOffset = iOff; + pIter->iTermLeafPgno = pIter->iLeafPgno; + pIter->iLeafOffset = iOff; + + if( pIter->iPgidxOff>=pIter->pLeaf->nn ){ + pIter->iEndofDoclist = pIter->pLeaf->nn+1; + }else{ + int nExtra; + pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], nExtra); + pIter->iEndofDoclist += nExtra; + } + + fts5SegIterLoadRowid(p, pIter); +} + +static void fts5SegIterNext(Fts5Index*, Fts5SegIter*, int*); +static void fts5SegIterNext_Reverse(Fts5Index*, Fts5SegIter*, int*); +static void fts5SegIterNext_None(Fts5Index*, Fts5SegIter*, int*); + +static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){ + if( pIter->flags & FTS5_SEGITER_REVERSE ){ + pIter->xNext = fts5SegIterNext_Reverse; + }else if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ + pIter->xNext = fts5SegIterNext_None; + }else{ + pIter->xNext = fts5SegIterNext; + } +} + +/* +** Initialize the iterator object pIter to iterate through the entries in +** segment pSeg. The iterator is left pointing to the first entry when +** this function returns. +** +** If an error occurs, Fts5Index.rc is set to an appropriate error code. If +** an error has already occurred when this function is called, it is a no-op. +*/ +static void fts5SegIterInit( + Fts5Index *p, /* FTS index object */ + Fts5StructureSegment *pSeg, /* Description of segment */ + Fts5SegIter *pIter /* Object to populate */ +){ + if( pSeg->pgnoFirst==0 ){ + /* This happens if the segment is being used as an input to an incremental + ** merge and all data has already been "trimmed". See function + ** fts5TrimSegments() for details. In this case leave the iterator empty. + ** The caller will see the (pIter->pLeaf==0) and assume the iterator is + ** at EOF already. */ + assert( pIter->pLeaf==0 ); + return; + } + + if( p->rc==SQLITE_OK ){ + memset(pIter, 0, sizeof(*pIter)); + fts5SegIterSetNext(p, pIter); + pIter->pSeg = pSeg; + pIter->iLeafPgno = pSeg->pgnoFirst-1; + fts5SegIterNextPage(p, pIter); + } + + if( p->rc==SQLITE_OK ){ + pIter->iLeafOffset = 4; + assert_nc( pIter->pLeaf->nn>4 ); + assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 ); + pIter->iPgidxOff = pIter->pLeaf->szLeaf+1; + fts5SegIterLoadTerm(p, pIter, 0); + fts5SegIterLoadNPos(p, pIter); + } +} + +/* +** This function is only ever called on iterators created by calls to +** Fts5IndexQuery() with the FTS5INDEX_QUERY_DESC flag set. +** +** The iterator is in an unusual state when this function is called: the +** Fts5SegIter.iLeafOffset variable is set to the offset of the start of +** the position-list size field for the first relevant rowid on the page. +** Fts5SegIter.rowid is set, but nPos and bDel are not. +** +** This function advances the iterator so that it points to the last +** relevant rowid on the page and, if necessary, initializes the +** aRowidOffset[] and iRowidOffset variables. At this point the iterator +** is in its regular state - Fts5SegIter.iLeafOffset points to the first +** byte of the position list content associated with said rowid. +*/ +static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){ + int eDetail = p->pConfig->eDetail; + int n = pIter->pLeaf->szLeaf; + int i = pIter->iLeafOffset; + u8 *a = pIter->pLeaf->p; + int iRowidOffset = 0; + + if( n>pIter->iEndofDoclist ){ + n = pIter->iEndofDoclist; + } + + ASSERT_SZLEAF_OK(pIter->pLeaf); + while( 1 ){ + i64 iDelta = 0; + + if( eDetail==FTS5_DETAIL_NONE ){ + /* todo */ + if( i=n ) break; + i += fts5GetVarint(&a[i], (u64*)&iDelta); + pIter->iRowid += iDelta; + + /* If necessary, grow the pIter->aRowidOffset[] array. */ + if( iRowidOffset>=pIter->nRowidOffset ){ + int nNew = pIter->nRowidOffset + 8; + int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int)); + if( aNew==0 ){ + p->rc = SQLITE_NOMEM; + break; + } + pIter->aRowidOffset = aNew; + pIter->nRowidOffset = nNew; + } + + pIter->aRowidOffset[iRowidOffset++] = pIter->iLeafOffset; + pIter->iLeafOffset = i; + } + pIter->iRowidOffset = iRowidOffset; + fts5SegIterLoadNPos(p, pIter); +} + +/* +** +*/ +static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){ + assert( pIter->flags & FTS5_SEGITER_REVERSE ); + assert( pIter->flags & FTS5_SEGITER_ONETERM ); + + fts5DataRelease(pIter->pLeaf); + pIter->pLeaf = 0; + while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){ + Fts5Data *pNew; + pIter->iLeafPgno--; + pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID( + pIter->pSeg->iSegid, pIter->iLeafPgno + )); + if( pNew ){ + /* iTermLeafOffset may be equal to szLeaf if the term is the last + ** thing on the page - i.e. the first rowid is on the following page. + ** In this case leave pIter->pLeaf==0, this iterator is at EOF. */ + if( pIter->iLeafPgno==pIter->iTermLeafPgno ){ + assert( pIter->pLeaf==0 ); + if( pIter->iTermLeafOffsetszLeaf ){ + pIter->pLeaf = pNew; + pIter->iLeafOffset = pIter->iTermLeafOffset; + } + }else{ + int iRowidOff; + iRowidOff = fts5LeafFirstRowidOff(pNew); + if( iRowidOff ){ + pIter->pLeaf = pNew; + pIter->iLeafOffset = iRowidOff; + } + } + + if( pIter->pLeaf ){ + u8 *a = &pIter->pLeaf->p[pIter->iLeafOffset]; + pIter->iLeafOffset += fts5GetVarint(a, (u64*)&pIter->iRowid); + break; + }else{ + fts5DataRelease(pNew); + } + } + } + + if( pIter->pLeaf ){ + pIter->iEndofDoclist = pIter->pLeaf->nn+1; + fts5SegIterReverseInitPage(p, pIter); + } +} + +/* +** Return true if the iterator passed as the second argument currently +** points to a delete marker. A delete marker is an entry with a 0 byte +** position-list. +*/ +static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5Iter *pIter){ + Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; + return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0); +} + +/* +** Advance iterator pIter to the next entry. +** +** This version of fts5SegIterNext() is only used by reverse iterators. +*/ +static void fts5SegIterNext_Reverse( + Fts5Index *p, /* FTS5 backend object */ + Fts5SegIter *pIter, /* Iterator to advance */ + int *pbUnused /* Unused */ +){ + assert( pIter->flags & FTS5_SEGITER_REVERSE ); + assert( pIter->pNextLeaf==0 ); + UNUSED_PARAM(pbUnused); + + if( pIter->iRowidOffset>0 ){ + u8 *a = pIter->pLeaf->p; + int iOff; + i64 iDelta; + + pIter->iRowidOffset--; + pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset]; + fts5SegIterLoadNPos(p, pIter); + iOff = pIter->iLeafOffset; + if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){ + iOff += pIter->nPos; + } + fts5GetVarint(&a[iOff], (u64*)&iDelta); + pIter->iRowid -= iDelta; + }else{ + fts5SegIterReverseNewPage(p, pIter); + } +} + +/* +** Advance iterator pIter to the next entry. +** +** This version of fts5SegIterNext() is only used if detail=none and the +** iterator is not a reverse direction iterator. +*/ +static void fts5SegIterNext_None( + Fts5Index *p, /* FTS5 backend object */ + Fts5SegIter *pIter, /* Iterator to advance */ + int *pbNewTerm /* OUT: Set for new term */ +){ + int iOff; + + assert( p->rc==SQLITE_OK ); + assert( (pIter->flags & FTS5_SEGITER_REVERSE)==0 ); + assert( p->pConfig->eDetail==FTS5_DETAIL_NONE ); + + ASSERT_SZLEAF_OK(pIter->pLeaf); + iOff = pIter->iLeafOffset; + + /* Next entry is on the next page */ + if( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){ + fts5SegIterNextPage(p, pIter); + if( p->rc || pIter->pLeaf==0 ) return; + pIter->iRowid = 0; + iOff = 4; + } + + if( iOffiEndofDoclist ){ + /* Next entry is on the current page */ + i64 iDelta; + iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta); + pIter->iLeafOffset = iOff; + pIter->iRowid += iDelta; + }else if( (pIter->flags & FTS5_SEGITER_ONETERM)==0 ){ + if( pIter->pSeg ){ + int nKeep = 0; + if( iOff!=fts5LeafFirstTermOff(pIter->pLeaf) ){ + iOff += fts5GetVarint32(&pIter->pLeaf->p[iOff], nKeep); + } + pIter->iLeafOffset = iOff; + fts5SegIterLoadTerm(p, pIter, nKeep); + }else{ + const u8 *pList = 0; + const char *zTerm = 0; + int nList; + sqlite3Fts5HashScanNext(p->pHash); + sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList); + if( pList==0 ) goto next_none_eof; + pIter->pLeaf->p = (u8*)pList; + pIter->pLeaf->nn = nList; + pIter->pLeaf->szLeaf = nList; + pIter->iEndofDoclist = nList; + sqlite3Fts5BufferSet(&p->rc,&pIter->term, (int)strlen(zTerm), (u8*)zTerm); + pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid); + } + + if( pbNewTerm ) *pbNewTerm = 1; + }else{ + goto next_none_eof; + } + + fts5SegIterLoadNPos(p, pIter); + + return; + next_none_eof: + fts5DataRelease(pIter->pLeaf); + pIter->pLeaf = 0; +} + + +/* +** Advance iterator pIter to the next entry. +** +** If an error occurs, Fts5Index.rc is set to an appropriate error code. It +** is not considered an error if the iterator reaches EOF. If an error has +** already occurred when this function is called, it is a no-op. +*/ +static void fts5SegIterNext( + Fts5Index *p, /* FTS5 backend object */ + Fts5SegIter *pIter, /* Iterator to advance */ + int *pbNewTerm /* OUT: Set for new term */ +){ + Fts5Data *pLeaf = pIter->pLeaf; + int iOff; + int bNewTerm = 0; + int nKeep = 0; + u8 *a; + int n; + + assert( pbNewTerm==0 || *pbNewTerm==0 ); + assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE ); + + /* Search for the end of the position list within the current page. */ + a = pLeaf->p; + n = pLeaf->szLeaf; + + ASSERT_SZLEAF_OK(pLeaf); + iOff = pIter->iLeafOffset + pIter->nPos; + + if( iOffiEndofDoclist ); + if( iOff>=pIter->iEndofDoclist ){ + bNewTerm = 1; + if( iOff!=fts5LeafFirstTermOff(pLeaf) ){ + iOff += fts5GetVarint32(&a[iOff], nKeep); + } + }else{ + u64 iDelta; + iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta); + pIter->iRowid += iDelta; + assert_nc( iDelta>0 ); + } + pIter->iLeafOffset = iOff; + + }else if( pIter->pSeg==0 ){ + const u8 *pList = 0; + const char *zTerm = 0; + int nList = 0; + assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm ); + if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){ + sqlite3Fts5HashScanNext(p->pHash); + sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList); + } + if( pList==0 ){ + fts5DataRelease(pIter->pLeaf); + pIter->pLeaf = 0; + }else{ + pIter->pLeaf->p = (u8*)pList; + pIter->pLeaf->nn = nList; + pIter->pLeaf->szLeaf = nList; + pIter->iEndofDoclist = nList+1; + sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm), + (u8*)zTerm); + pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid); + *pbNewTerm = 1; + } + }else{ + iOff = 0; + /* Next entry is not on the current page */ + while( iOff==0 ){ + fts5SegIterNextPage(p, pIter); + pLeaf = pIter->pLeaf; + if( pLeaf==0 ) break; + ASSERT_SZLEAF_OK(pLeaf); + if( (iOff = fts5LeafFirstRowidOff(pLeaf)) && iOffszLeaf ){ + iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid); + pIter->iLeafOffset = iOff; + + if( pLeaf->nn>pLeaf->szLeaf ){ + pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( + &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist + ); + } + + } + else if( pLeaf->nn>pLeaf->szLeaf ){ + pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( + &pLeaf->p[pLeaf->szLeaf], iOff + ); + pIter->iLeafOffset = iOff; + pIter->iEndofDoclist = iOff; + bNewTerm = 1; + } + assert_nc( iOffszLeaf ); + if( iOff>pLeaf->szLeaf ){ + p->rc = FTS5_CORRUPT; + return; + } + } + } + + /* Check if the iterator is now at EOF. If so, return early. */ + if( pIter->pLeaf ){ + if( bNewTerm ){ + if( pIter->flags & FTS5_SEGITER_ONETERM ){ + fts5DataRelease(pIter->pLeaf); + pIter->pLeaf = 0; + }else{ + fts5SegIterLoadTerm(p, pIter, nKeep); + fts5SegIterLoadNPos(p, pIter); + if( pbNewTerm ) *pbNewTerm = 1; + } + }else{ + /* The following could be done by calling fts5SegIterLoadNPos(). But + ** this block is particularly performance critical, so equivalent + ** code is inlined. + ** + ** Later: Switched back to fts5SegIterLoadNPos() because it supports + ** detail=none mode. Not ideal. + */ + int nSz; + assert( p->rc==SQLITE_OK ); + fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz); + pIter->bDel = (nSz & 0x0001); + pIter->nPos = nSz>>1; + assert_nc( pIter->nPos>=0 ); + } + } +} + +#define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; } + +#define fts5IndexSkipVarint(a, iOff) { \ + int iEnd = iOff+9; \ + while( (a[iOff++] & 0x80) && iOffpDlidx; + Fts5Data *pLast = 0; + int pgnoLast = 0; + + if( pDlidx ){ + int iSegid = pIter->pSeg->iSegid; + pgnoLast = fts5DlidxIterPgno(pDlidx); + pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast)); + }else{ + Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */ + + /* Currently, Fts5SegIter.iLeafOffset points to the first byte of + ** position-list content for the current rowid. Back it up so that it + ** points to the start of the position-list size field. */ + int iPoslist; + if( pIter->iTermLeafPgno==pIter->iLeafPgno ){ + iPoslist = pIter->iTermLeafOffset; + }else{ + iPoslist = 4; + } + fts5IndexSkipVarint(pLeaf->p, iPoslist); + pIter->iLeafOffset = iPoslist; + + /* If this condition is true then the largest rowid for the current + ** term may not be stored on the current page. So search forward to + ** see where said rowid really is. */ + if( pIter->iEndofDoclist>=pLeaf->szLeaf ){ + int pgno; + Fts5StructureSegment *pSeg = pIter->pSeg; + + /* The last rowid in the doclist may not be on the current page. Search + ** forward to find the page containing the last rowid. */ + for(pgno=pIter->iLeafPgno+1; !p->rc && pgno<=pSeg->pgnoLast; pgno++){ + i64 iAbs = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno); + Fts5Data *pNew = fts5DataRead(p, iAbs); + if( pNew ){ + int iRowid, bTermless; + iRowid = fts5LeafFirstRowidOff(pNew); + bTermless = fts5LeafIsTermless(pNew); + if( iRowid ){ + SWAPVAL(Fts5Data*, pNew, pLast); + pgnoLast = pgno; + } + fts5DataRelease(pNew); + if( bTermless==0 ) break; + } + } + } + } + + /* If pLast is NULL at this point, then the last rowid for this doclist + ** lies on the page currently indicated by the iterator. In this case + ** pIter->iLeafOffset is already set to point to the position-list size + ** field associated with the first relevant rowid on the page. + ** + ** Or, if pLast is non-NULL, then it is the page that contains the last + ** rowid. In this case configure the iterator so that it points to the + ** first rowid on this page. + */ + if( pLast ){ + int iOff; + fts5DataRelease(pIter->pLeaf); + pIter->pLeaf = pLast; + pIter->iLeafPgno = pgnoLast; + iOff = fts5LeafFirstRowidOff(pLast); + iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid); + pIter->iLeafOffset = iOff; + + if( fts5LeafIsTermless(pLast) ){ + pIter->iEndofDoclist = pLast->nn+1; + }else{ + pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast); + } + + } + + fts5SegIterReverseInitPage(p, pIter); +} + +/* +** Iterator pIter currently points to the first rowid of a doclist. +** There is a doclist-index associated with the final term on the current +** page. If the current term is the last term on the page, load the +** doclist-index from disk and initialize an iterator at (pIter->pDlidx). +*/ +static void fts5SegIterLoadDlidx(Fts5Index *p, Fts5SegIter *pIter){ + int iSeg = pIter->pSeg->iSegid; + int bRev = (pIter->flags & FTS5_SEGITER_REVERSE); + Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */ + + assert( pIter->flags & FTS5_SEGITER_ONETERM ); + assert( pIter->pDlidx==0 ); + + /* Check if the current doclist ends on this page. If it does, return + ** early without loading the doclist-index (as it belongs to a different + ** term. */ + if( pIter->iTermLeafPgno==pIter->iLeafPgno + && pIter->iEndofDoclistszLeaf + ){ + return; + } + + pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno); +} + +/* +** The iterator object passed as the second argument currently contains +** no valid values except for the Fts5SegIter.pLeaf member variable. This +** function searches the leaf page for a term matching (pTerm/nTerm). +** +** If the specified term is found on the page, then the iterator is left +** pointing to it. If argument bGe is zero and the term is not found, +** the iterator is left pointing at EOF. +** +** If bGe is non-zero and the specified term is not found, then the +** iterator is left pointing to the smallest term in the segment that +** is larger than the specified term, even if this term is not on the +** current page. +*/ +static void fts5LeafSeek( + Fts5Index *p, /* Leave any error code here */ + int bGe, /* True for a >= search */ + Fts5SegIter *pIter, /* Iterator to seek */ + const u8 *pTerm, int nTerm /* Term to search for */ +){ + int iOff; + const u8 *a = pIter->pLeaf->p; + int szLeaf = pIter->pLeaf->szLeaf; + int n = pIter->pLeaf->nn; + + int nMatch = 0; + int nKeep = 0; + int nNew = 0; + int iTermOff; + int iPgidx; /* Current offset in pgidx */ + int bEndOfPage = 0; + + assert( p->rc==SQLITE_OK ); + + iPgidx = szLeaf; + iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff); + iOff = iTermOff; + + while( 1 ){ + + /* Figure out how many new bytes are in this term */ + fts5FastGetVarint32(a, iOff, nNew); + if( nKeep=nMatch ); + if( nKeep==nMatch ){ + int nCmp; + int i; + nCmp = MIN(nNew, nTerm-nMatch); + for(i=0; ipTerm[nMatch] ){ + goto search_failed; + } + } + + if( iPgidx>=n ){ + bEndOfPage = 1; + break; + } + + iPgidx += fts5GetVarint32(&a[iPgidx], nKeep); + iTermOff += nKeep; + iOff = iTermOff; + + /* Read the nKeep field of the next term. */ + fts5FastGetVarint32(a, iOff, nKeep); + } + + search_failed: + if( bGe==0 ){ + fts5DataRelease(pIter->pLeaf); + pIter->pLeaf = 0; + return; + }else if( bEndOfPage ){ + do { + fts5SegIterNextPage(p, pIter); + if( pIter->pLeaf==0 ) return; + a = pIter->pLeaf->p; + if( fts5LeafIsTermless(pIter->pLeaf)==0 ){ + iPgidx = pIter->pLeaf->szLeaf; + iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff); + if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){ + p->rc = FTS5_CORRUPT; + }else{ + nKeep = 0; + iTermOff = iOff; + n = pIter->pLeaf->nn; + iOff += fts5GetVarint32(&a[iOff], nNew); + break; + } + } + }while( 1 ); + } + + search_success: + + pIter->iLeafOffset = iOff + nNew; + pIter->iTermLeafOffset = pIter->iLeafOffset; + pIter->iTermLeafPgno = pIter->iLeafPgno; + + fts5BufferSet(&p->rc, &pIter->term, nKeep, pTerm); + fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]); + + if( iPgidx>=n ){ + pIter->iEndofDoclist = pIter->pLeaf->nn+1; + }else{ + int nExtra; + iPgidx += fts5GetVarint32(&a[iPgidx], nExtra); + pIter->iEndofDoclist = iTermOff + nExtra; + } + pIter->iPgidxOff = iPgidx; + + fts5SegIterLoadRowid(p, pIter); + fts5SegIterLoadNPos(p, pIter); +} + +/* +** Initialize the object pIter to point to term pTerm/nTerm within segment +** pSeg. If there is no such term in the index, the iterator is set to EOF. +** +** If an error occurs, Fts5Index.rc is set to an appropriate error code. If +** an error has already occurred when this function is called, it is a no-op. +*/ +static void fts5SegIterSeekInit( + Fts5Index *p, /* FTS5 backend */ + const u8 *pTerm, int nTerm, /* Term to seek to */ + int flags, /* Mask of FTS5INDEX_XXX flags */ + Fts5StructureSegment *pSeg, /* Description of segment */ + Fts5SegIter *pIter /* Object to populate */ +){ + int iPg = 1; + int bGe = (flags & FTS5INDEX_QUERY_SCAN); + int bDlidx = 0; /* True if there is a doclist-index */ + + assert( bGe==0 || (flags & FTS5INDEX_QUERY_DESC)==0 ); + assert( pTerm && nTerm ); + memset(pIter, 0, sizeof(*pIter)); + pIter->pSeg = pSeg; + + /* This block sets stack variable iPg to the leaf page number that may + ** contain term (pTerm/nTerm), if it is present in the segment. */ + if( p->pIdxSelect==0 ){ + Fts5Config *pConfig = p->pConfig; + fts5IndexPrepareStmt(p, &p->pIdxSelect, sqlite3_mprintf( + "SELECT pgno FROM '%q'.'%q_idx' WHERE " + "segid=? AND term<=? ORDER BY term DESC LIMIT 1", + pConfig->zDb, pConfig->zName + )); + } + if( p->rc ) return; + sqlite3_bind_int(p->pIdxSelect, 1, pSeg->iSegid); + sqlite3_bind_blob(p->pIdxSelect, 2, pTerm, nTerm, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(p->pIdxSelect) ){ + i64 val = sqlite3_column_int(p->pIdxSelect, 0); + iPg = (int)(val>>1); + bDlidx = (val & 0x0001); + } + p->rc = sqlite3_reset(p->pIdxSelect); + + if( iPgpgnoFirst ){ + iPg = pSeg->pgnoFirst; + bDlidx = 0; + } + + pIter->iLeafPgno = iPg - 1; + fts5SegIterNextPage(p, pIter); + + if( pIter->pLeaf ){ + fts5LeafSeek(p, bGe, pIter, pTerm, nTerm); + } + + if( p->rc==SQLITE_OK && bGe==0 ){ + pIter->flags |= FTS5_SEGITER_ONETERM; + if( pIter->pLeaf ){ + if( flags & FTS5INDEX_QUERY_DESC ){ + pIter->flags |= FTS5_SEGITER_REVERSE; + } + if( bDlidx ){ + fts5SegIterLoadDlidx(p, pIter); + } + if( flags & FTS5INDEX_QUERY_DESC ){ + fts5SegIterReverse(p, pIter); + } + } + } + + fts5SegIterSetNext(p, pIter); + + /* Either: + ** + ** 1) an error has occurred, or + ** 2) the iterator points to EOF, or + ** 3) the iterator points to an entry with term (pTerm/nTerm), or + ** 4) the FTS5INDEX_QUERY_SCAN flag was set and the iterator points + ** to an entry with a term greater than or equal to (pTerm/nTerm). + */ + assert( p->rc!=SQLITE_OK /* 1 */ + || pIter->pLeaf==0 /* 2 */ + || fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)==0 /* 3 */ + || (bGe && fts5BufferCompareBlob(&pIter->term, pTerm, nTerm)>0) /* 4 */ + ); +} + +/* +** Initialize the object pIter to point to term pTerm/nTerm within the +** in-memory hash table. If there is no such term in the hash-table, the +** iterator is set to EOF. +** +** If an error occurs, Fts5Index.rc is set to an appropriate error code. If +** an error has already occurred when this function is called, it is a no-op. +*/ +static void fts5SegIterHashInit( + Fts5Index *p, /* FTS5 backend */ + const u8 *pTerm, int nTerm, /* Term to seek to */ + int flags, /* Mask of FTS5INDEX_XXX flags */ + Fts5SegIter *pIter /* Object to populate */ +){ + const u8 *pList = 0; + int nList = 0; + const u8 *z = 0; + int n = 0; + + assert( p->pHash ); + assert( p->rc==SQLITE_OK ); + + if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){ + p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm); + sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList); + n = (z ? (int)strlen((const char*)z) : 0); + }else{ + pIter->flags |= FTS5_SEGITER_ONETERM; + sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList); + z = pTerm; + n = nTerm; + } + + if( pList ){ + Fts5Data *pLeaf; + sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z); + pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); + if( pLeaf==0 ) return; + pLeaf->p = (u8*)pList; + pLeaf->nn = pLeaf->szLeaf = nList; + pIter->pLeaf = pLeaf; + pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid); + pIter->iEndofDoclist = pLeaf->nn; + + if( flags & FTS5INDEX_QUERY_DESC ){ + pIter->flags |= FTS5_SEGITER_REVERSE; + fts5SegIterReverseInitPage(p, pIter); + }else{ + fts5SegIterLoadNPos(p, pIter); + } + } + + fts5SegIterSetNext(p, pIter); +} + +/* +** Zero the iterator passed as the only argument. +*/ +static void fts5SegIterClear(Fts5SegIter *pIter){ + fts5BufferFree(&pIter->term); + fts5DataRelease(pIter->pLeaf); + fts5DataRelease(pIter->pNextLeaf); + fts5DlidxIterFree(pIter->pDlidx); + sqlite3_free(pIter->aRowidOffset); + memset(pIter, 0, sizeof(Fts5SegIter)); +} + +#ifdef SQLITE_DEBUG + +/* +** This function is used as part of the big assert() procedure implemented by +** fts5AssertMultiIterSetup(). It ensures that the result currently stored +** in *pRes is the correct result of comparing the current positions of the +** two iterators. +*/ +static void fts5AssertComparisonResult( + Fts5Iter *pIter, + Fts5SegIter *p1, + Fts5SegIter *p2, + Fts5CResult *pRes +){ + int i1 = p1 - pIter->aSeg; + int i2 = p2 - pIter->aSeg; + + if( p1->pLeaf || p2->pLeaf ){ + if( p1->pLeaf==0 ){ + assert( pRes->iFirst==i2 ); + }else if( p2->pLeaf==0 ){ + assert( pRes->iFirst==i1 ); + }else{ + int nMin = MIN(p1->term.n, p2->term.n); + int res = memcmp(p1->term.p, p2->term.p, nMin); + if( res==0 ) res = p1->term.n - p2->term.n; + + if( res==0 ){ + assert( pRes->bTermEq==1 ); + assert( p1->iRowid!=p2->iRowid ); + res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : 1; + }else{ + assert( pRes->bTermEq==0 ); + } + + if( res<0 ){ + assert( pRes->iFirst==i1 ); + }else{ + assert( pRes->iFirst==i2 ); + } + } + } +} + +/* +** This function is a no-op unless SQLITE_DEBUG is defined when this module +** is compiled. In that case, this function is essentially an assert() +** statement used to verify that the contents of the pIter->aFirst[] array +** are correct. +*/ +static void fts5AssertMultiIterSetup(Fts5Index *p, Fts5Iter *pIter){ + if( p->rc==SQLITE_OK ){ + Fts5SegIter *pFirst = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; + int i; + + assert( (pFirst->pLeaf==0)==pIter->base.bEof ); + + /* Check that pIter->iSwitchRowid is set correctly. */ + for(i=0; inSeg; i++){ + Fts5SegIter *p1 = &pIter->aSeg[i]; + assert( p1==pFirst + || p1->pLeaf==0 + || fts5BufferCompare(&pFirst->term, &p1->term) + || p1->iRowid==pIter->iSwitchRowid + || (p1->iRowidiSwitchRowid)==pIter->bRev + ); + } + + for(i=0; inSeg; i+=2){ + Fts5SegIter *p1 = &pIter->aSeg[i]; + Fts5SegIter *p2 = &pIter->aSeg[i+1]; + Fts5CResult *pRes = &pIter->aFirst[(pIter->nSeg + i) / 2]; + fts5AssertComparisonResult(pIter, p1, p2, pRes); + } + + for(i=1; i<(pIter->nSeg / 2); i+=2){ + Fts5SegIter *p1 = &pIter->aSeg[ pIter->aFirst[i*2].iFirst ]; + Fts5SegIter *p2 = &pIter->aSeg[ pIter->aFirst[i*2+1].iFirst ]; + Fts5CResult *pRes = &pIter->aFirst[i]; + fts5AssertComparisonResult(pIter, p1, p2, pRes); + } + } +} +#else +# define fts5AssertMultiIterSetup(x,y) +#endif + +/* +** Do the comparison necessary to populate pIter->aFirst[iOut]. +** +** If the returned value is non-zero, then it is the index of an entry +** in the pIter->aSeg[] array that is (a) not at EOF, and (b) pointing +** to a key that is a duplicate of another, higher priority, +** segment-iterator in the pSeg->aSeg[] array. +*/ +static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ + int i1; /* Index of left-hand Fts5SegIter */ + int i2; /* Index of right-hand Fts5SegIter */ + int iRes; + Fts5SegIter *p1; /* Left-hand Fts5SegIter */ + Fts5SegIter *p2; /* Right-hand Fts5SegIter */ + Fts5CResult *pRes = &pIter->aFirst[iOut]; + + assert( iOutnSeg && iOut>0 ); + assert( pIter->bRev==0 || pIter->bRev==1 ); + + if( iOut>=(pIter->nSeg/2) ){ + i1 = (iOut - pIter->nSeg/2) * 2; + i2 = i1 + 1; + }else{ + i1 = pIter->aFirst[iOut*2].iFirst; + i2 = pIter->aFirst[iOut*2+1].iFirst; + } + p1 = &pIter->aSeg[i1]; + p2 = &pIter->aSeg[i2]; + + pRes->bTermEq = 0; + if( p1->pLeaf==0 ){ /* If p1 is at EOF */ + iRes = i2; + }else if( p2->pLeaf==0 ){ /* If p2 is at EOF */ + iRes = i1; + }else{ + int res = fts5BufferCompare(&p1->term, &p2->term); + if( res==0 ){ + assert( i2>i1 ); + assert( i2!=0 ); + pRes->bTermEq = 1; + if( p1->iRowid==p2->iRowid ){ + p1->bDel = p2->bDel; + return i2; + } + res = ((p1->iRowid > p2->iRowid)==pIter->bRev) ? -1 : +1; + } + assert( res!=0 ); + if( res<0 ){ + iRes = i1; + }else{ + iRes = i2; + } + } + + pRes->iFirst = (u16)iRes; + return 0; +} + +/* +** Move the seg-iter so that it points to the first rowid on page iLeafPgno. +** It is an error if leaf iLeafPgno does not exist or contains no rowids. +*/ +static void fts5SegIterGotoPage( + Fts5Index *p, /* FTS5 backend object */ + Fts5SegIter *pIter, /* Iterator to advance */ + int iLeafPgno +){ + assert( iLeafPgno>pIter->iLeafPgno ); + + if( iLeafPgno>pIter->pSeg->pgnoLast ){ + p->rc = FTS5_CORRUPT; + }else{ + fts5DataRelease(pIter->pNextLeaf); + pIter->pNextLeaf = 0; + pIter->iLeafPgno = iLeafPgno-1; + fts5SegIterNextPage(p, pIter); + assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno ); + + if( p->rc==SQLITE_OK ){ + int iOff; + u8 *a = pIter->pLeaf->p; + int n = pIter->pLeaf->szLeaf; + + iOff = fts5LeafFirstRowidOff(pIter->pLeaf); + if( iOff<4 || iOff>=n ){ + p->rc = FTS5_CORRUPT; + }else{ + iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); + pIter->iLeafOffset = iOff; + fts5SegIterLoadNPos(p, pIter); + } + } + } +} + +/* +** Advance the iterator passed as the second argument until it is at or +** past rowid iFrom. Regardless of the value of iFrom, the iterator is +** always advanced at least once. +*/ +static void fts5SegIterNextFrom( + Fts5Index *p, /* FTS5 backend object */ + Fts5SegIter *pIter, /* Iterator to advance */ + i64 iMatch /* Advance iterator at least this far */ +){ + int bRev = (pIter->flags & FTS5_SEGITER_REVERSE); + Fts5DlidxIter *pDlidx = pIter->pDlidx; + int iLeafPgno = pIter->iLeafPgno; + int bMove = 1; + + assert( pIter->flags & FTS5_SEGITER_ONETERM ); + assert( pIter->pDlidx ); + assert( pIter->pLeaf ); + + if( bRev==0 ){ + while( !fts5DlidxIterEof(p, pDlidx) && iMatch>fts5DlidxIterRowid(pDlidx) ){ + iLeafPgno = fts5DlidxIterPgno(pDlidx); + fts5DlidxIterNext(p, pDlidx); + } + assert_nc( iLeafPgno>=pIter->iLeafPgno || p->rc ); + if( iLeafPgno>pIter->iLeafPgno ){ + fts5SegIterGotoPage(p, pIter, iLeafPgno); + bMove = 0; + } + }else{ + assert( pIter->pNextLeaf==0 ); + assert( iMatchiRowid ); + while( !fts5DlidxIterEof(p, pDlidx) && iMatchiLeafPgno ); + + if( iLeafPgnoiLeafPgno ){ + pIter->iLeafPgno = iLeafPgno+1; + fts5SegIterReverseNewPage(p, pIter); + bMove = 0; + } + } + + do{ + if( bMove && p->rc==SQLITE_OK ) pIter->xNext(p, pIter, 0); + if( pIter->pLeaf==0 ) break; + if( bRev==0 && pIter->iRowid>=iMatch ) break; + if( bRev!=0 && pIter->iRowid<=iMatch ) break; + bMove = 1; + }while( p->rc==SQLITE_OK ); +} + + +/* +** Free the iterator object passed as the second argument. +*/ +static void fts5MultiIterFree(Fts5Iter *pIter){ + if( pIter ){ + int i; + for(i=0; inSeg; i++){ + fts5SegIterClear(&pIter->aSeg[i]); + } + fts5StructureRelease(pIter->pStruct); + fts5BufferFree(&pIter->poslist); + sqlite3_free(pIter); + } +} + +static void fts5MultiIterAdvanced( + Fts5Index *p, /* FTS5 backend to iterate within */ + Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ + int iChanged, /* Index of sub-iterator just advanced */ + int iMinset /* Minimum entry in aFirst[] to set */ +){ + int i; + for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){ + int iEq; + if( (iEq = fts5MultiIterDoCompare(pIter, i)) ){ + Fts5SegIter *pSeg = &pIter->aSeg[iEq]; + assert( p->rc==SQLITE_OK ); + pSeg->xNext(p, pSeg, 0); + i = pIter->nSeg + iEq; + } + } +} + +/* +** Sub-iterator iChanged of iterator pIter has just been advanced. It still +** points to the same term though - just a different rowid. This function +** attempts to update the contents of the pIter->aFirst[] accordingly. +** If it does so successfully, 0 is returned. Otherwise 1. +** +** If non-zero is returned, the caller should call fts5MultiIterAdvanced() +** on the iterator instead. That function does the same as this one, except +** that it deals with more complicated cases as well. +*/ +static int fts5MultiIterAdvanceRowid( + Fts5Iter *pIter, /* Iterator to update aFirst[] array for */ + int iChanged, /* Index of sub-iterator just advanced */ + Fts5SegIter **ppFirst +){ + Fts5SegIter *pNew = &pIter->aSeg[iChanged]; + + if( pNew->iRowid==pIter->iSwitchRowid + || (pNew->iRowidiSwitchRowid)==pIter->bRev + ){ + int i; + Fts5SegIter *pOther = &pIter->aSeg[iChanged ^ 0x0001]; + pIter->iSwitchRowid = pIter->bRev ? SMALLEST_INT64 : LARGEST_INT64; + for(i=(pIter->nSeg+iChanged)/2; 1; i=i/2){ + Fts5CResult *pRes = &pIter->aFirst[i]; + + assert( pNew->pLeaf ); + assert( pRes->bTermEq==0 || pOther->pLeaf ); + + if( pRes->bTermEq ){ + if( pNew->iRowid==pOther->iRowid ){ + return 1; + }else if( (pOther->iRowid>pNew->iRowid)==pIter->bRev ){ + pIter->iSwitchRowid = pOther->iRowid; + pNew = pOther; + }else if( (pOther->iRowid>pIter->iSwitchRowid)==pIter->bRev ){ + pIter->iSwitchRowid = pOther->iRowid; + } + } + pRes->iFirst = (u16)(pNew - pIter->aSeg); + if( i==1 ) break; + + pOther = &pIter->aSeg[ pIter->aFirst[i ^ 0x0001].iFirst ]; + } + } + + *ppFirst = pNew; + return 0; +} + +/* +** Set the pIter->bEof variable based on the state of the sub-iterators. +*/ +static void fts5MultiIterSetEof(Fts5Iter *pIter){ + Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; + pIter->base.bEof = pSeg->pLeaf==0; + pIter->iSwitchRowid = pSeg->iRowid; +} + +/* +** Move the iterator to the next entry. +** +** If an error occurs, an error code is left in Fts5Index.rc. It is not +** considered an error if the iterator reaches EOF, or if it is already at +** EOF when this function is called. +*/ +static void fts5MultiIterNext( + Fts5Index *p, + Fts5Iter *pIter, + int bFrom, /* True if argument iFrom is valid */ + i64 iFrom /* Advance at least as far as this */ +){ + int bUseFrom = bFrom; + while( p->rc==SQLITE_OK ){ + int iFirst = pIter->aFirst[1].iFirst; + int bNewTerm = 0; + Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; + assert( p->rc==SQLITE_OK ); + if( bUseFrom && pSeg->pDlidx ){ + fts5SegIterNextFrom(p, pSeg, iFrom); + }else{ + pSeg->xNext(p, pSeg, &bNewTerm); + } + + if( pSeg->pLeaf==0 || bNewTerm + || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg) + ){ + fts5MultiIterAdvanced(p, pIter, iFirst, 1); + fts5MultiIterSetEof(pIter); + pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst]; + if( pSeg->pLeaf==0 ) return; + } + + fts5AssertMultiIterSetup(p, pIter); + assert( pSeg==&pIter->aSeg[pIter->aFirst[1].iFirst] && pSeg->pLeaf ); + if( pIter->bSkipEmpty==0 || pSeg->nPos ){ + pIter->xSetOutputs(pIter, pSeg); + return; + } + bUseFrom = 0; + } +} + +static void fts5MultiIterNext2( + Fts5Index *p, + Fts5Iter *pIter, + int *pbNewTerm /* OUT: True if *might* be new term */ +){ + assert( pIter->bSkipEmpty ); + if( p->rc==SQLITE_OK ){ + do { + int iFirst = pIter->aFirst[1].iFirst; + Fts5SegIter *pSeg = &pIter->aSeg[iFirst]; + int bNewTerm = 0; + + assert( p->rc==SQLITE_OK ); + pSeg->xNext(p, pSeg, &bNewTerm); + if( pSeg->pLeaf==0 || bNewTerm + || fts5MultiIterAdvanceRowid(pIter, iFirst, &pSeg) + ){ + fts5MultiIterAdvanced(p, pIter, iFirst, 1); + fts5MultiIterSetEof(pIter); + *pbNewTerm = 1; + }else{ + *pbNewTerm = 0; + } + fts5AssertMultiIterSetup(p, pIter); + + }while( fts5MultiIterIsEmpty(p, pIter) ); + } +} + +static void fts5IterSetOutputs_Noop(Fts5Iter *pUnused1, Fts5SegIter *pUnused2){ + UNUSED_PARAM2(pUnused1, pUnused2); +} + +static Fts5Iter *fts5MultiIterAlloc( + Fts5Index *p, /* FTS5 backend to iterate within */ + int nSeg +){ + Fts5Iter *pNew; + int nSlot; /* Power of two >= nSeg */ + + for(nSlot=2; nSlotaSeg[] */ + sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */ + ); + if( pNew ){ + pNew->nSeg = nSlot; + pNew->aFirst = (Fts5CResult*)&pNew->aSeg[nSlot]; + pNew->pIndex = p; + pNew->xSetOutputs = fts5IterSetOutputs_Noop; + } + return pNew; +} + +static void fts5PoslistCallback( + Fts5Index *pUnused, + void *pContext, + const u8 *pChunk, int nChunk +){ + UNUSED_PARAM(pUnused); + assert_nc( nChunk>=0 ); + if( nChunk>0 ){ + fts5BufferSafeAppendBlob((Fts5Buffer*)pContext, pChunk, nChunk); + } +} + +typedef struct PoslistCallbackCtx PoslistCallbackCtx; +struct PoslistCallbackCtx { + Fts5Buffer *pBuf; /* Append to this buffer */ + Fts5Colset *pColset; /* Restrict matches to this column */ + int eState; /* See above */ +}; + +typedef struct PoslistOffsetsCtx PoslistOffsetsCtx; +struct PoslistOffsetsCtx { + Fts5Buffer *pBuf; /* Append to this buffer */ + Fts5Colset *pColset; /* Restrict matches to this column */ + int iRead; + int iWrite; +}; + +/* +** TODO: Make this more efficient! +*/ +static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){ + int i; + for(i=0; inCol; i++){ + if( pColset->aiCol[i]==iCol ) return 1; + } + return 0; +} + +static void fts5PoslistOffsetsCallback( + Fts5Index *pUnused, + void *pContext, + const u8 *pChunk, int nChunk +){ + PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext; + UNUSED_PARAM(pUnused); + assert_nc( nChunk>=0 ); + if( nChunk>0 ){ + int i = 0; + while( iiRead - 2; + pCtx->iRead = iVal; + if( fts5IndexColsetTest(pCtx->pColset, iVal) ){ + fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite); + pCtx->iWrite = iVal; + } + } + } +} + +static void fts5PoslistFilterCallback( + Fts5Index *pUnused, + void *pContext, + const u8 *pChunk, int nChunk +){ + PoslistCallbackCtx *pCtx = (PoslistCallbackCtx*)pContext; + UNUSED_PARAM(pUnused); + assert_nc( nChunk>=0 ); + if( nChunk>0 ){ + /* Search through to find the first varint with value 1. This is the + ** start of the next columns hits. */ + int i = 0; + int iStart = 0; + + if( pCtx->eState==2 ){ + int iCol; + fts5FastGetVarint32(pChunk, i, iCol); + if( fts5IndexColsetTest(pCtx->pColset, iCol) ){ + pCtx->eState = 1; + fts5BufferSafeAppendVarint(pCtx->pBuf, 1); + }else{ + pCtx->eState = 0; + } + } + + do { + while( ieState ){ + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); + } + if( i=nChunk ){ + pCtx->eState = 2; + }else{ + fts5FastGetVarint32(pChunk, i, iCol); + pCtx->eState = fts5IndexColsetTest(pCtx->pColset, iCol); + if( pCtx->eState ){ + fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); + iStart = i; + } + } + } + }while( inPos; /* Number of bytes still to come */ + Fts5Data *pData = 0; + u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset); + int pgno = pSeg->iLeafPgno; + int pgnoSave = 0; + + /* This function does notmwork with detail=none databases. */ + assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE ); + + if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){ + pgnoSave = pgno+1; + } + + while( 1 ){ + xChunk(p, pCtx, pChunk, nChunk); + nRem -= nChunk; + fts5DataRelease(pData); + if( nRem<=0 ){ + break; + }else{ + pgno++; + pData = fts5DataRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno)); + if( pData==0 ) break; + pChunk = &pData->p[4]; + nChunk = MIN(nRem, pData->szLeaf - 4); + if( pgno==pgnoSave ){ + assert( pSeg->pNextLeaf==0 ); + pSeg->pNextLeaf = pData; + pData = 0; + } + } + } +} + +/* +** Iterator pIter currently points to a valid entry (not EOF). This +** function appends the position list data for the current entry to +** buffer pBuf. It does not make a copy of the position-list size +** field. +*/ +static void fts5SegiterPoslist( + Fts5Index *p, + Fts5SegIter *pSeg, + Fts5Colset *pColset, + Fts5Buffer *pBuf +){ + if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){ + if( pColset==0 ){ + fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback); + }else{ + if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){ + PoslistCallbackCtx sCtx; + sCtx.pBuf = pBuf; + sCtx.pColset = pColset; + sCtx.eState = fts5IndexColsetTest(pColset, 0); + assert( sCtx.eState==0 || sCtx.eState==1 ); + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback); + }else{ + PoslistOffsetsCtx sCtx; + memset(&sCtx, 0, sizeof(sCtx)); + sCtx.pBuf = pBuf; + sCtx.pColset = pColset; + fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback); + } + } + } +} + +/* +** IN/OUT parameter (*pa) points to a position list n bytes in size. If +** the position list contains entries for column iCol, then (*pa) is set +** to point to the sub-position-list for that column and the number of +** bytes in it returned. Or, if the argument position list does not +** contain any entries for column iCol, return 0. +*/ +static int fts5IndexExtractCol( + const u8 **pa, /* IN/OUT: Pointer to poslist */ + int n, /* IN: Size of poslist in bytes */ + int iCol /* Column to extract from poslist */ +){ + int iCurrent = 0; /* Anything before the first 0x01 is col 0 */ + const u8 *p = *pa; + const u8 *pEnd = &p[n]; /* One byte past end of position list */ + + while( iCol>iCurrent ){ + /* Advance pointer p until it points to pEnd or an 0x01 byte that is + ** not part of a varint. Note that it is not possible for a negative + ** or extremely large varint to occur within an uncorrupted position + ** list. So the last byte of each varint may be assumed to have a clear + ** 0x80 bit. */ + while( *p!=0x01 ){ + while( *p++ & 0x80 ); + if( p>=pEnd ) return 0; + } + *pa = p++; + iCurrent = *p++; + if( iCurrent & 0x80 ){ + p--; + p += fts5GetVarint32(p, iCurrent); + } + } + if( iCol!=iCurrent ) return 0; + + /* Advance pointer p until it points to pEnd or an 0x01 byte that is + ** not part of a varint */ + while( pnCol; i++){ + const u8 *pSub = pPos; + int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]); + if( nSub ){ + fts5BufferAppendBlob(&rc, pBuf, nSub, pSub); + } + } + return rc; +} + +/* +** xSetOutputs callback used by detail=none tables. +*/ +static void fts5IterSetOutputs_None(Fts5Iter *pIter, Fts5SegIter *pSeg){ + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_NONE ); + pIter->base.iRowid = pSeg->iRowid; + pIter->base.nData = pSeg->nPos; +} + +/* +** xSetOutputs callback used by detail=full and detail=col tables when no +** column filters are specified. +*/ +static void fts5IterSetOutputs_Nocolset(Fts5Iter *pIter, Fts5SegIter *pSeg){ + pIter->base.iRowid = pSeg->iRowid; + pIter->base.nData = pSeg->nPos; + + assert( pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_NONE ); + assert( pIter->pColset==0 ); + + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ + /* All data is stored on the current page. Populate the output + ** variables to point into the body of the page object. */ + pIter->base.pData = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + }else{ + /* The data is distributed over two or more pages. Copy it into the + ** Fts5Iter.poslist buffer and then set the output pointer to point + ** to this buffer. */ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, 0, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + } +} + +/* +** xSetOutputs callback used by detail=col when there is a column filter +** and there are 100 or more columns. Also called as a fallback from +** fts5IterSetOutputs_Col100 if the column-list spans more than one page. +*/ +static void fts5IterSetOutputs_Col(Fts5Iter *pIter, Fts5SegIter *pSeg){ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, pIter->pColset, &pIter->poslist); + pIter->base.iRowid = pSeg->iRowid; + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; +} + +/* +** xSetOutputs callback used when: +** +** * detail=col, +** * there is a column filter, and +** * the table contains 100 or fewer columns. +** +** The last point is to ensure all column numbers are stored as +** single-byte varints. +*/ +static void fts5IterSetOutputs_Col100(Fts5Iter *pIter, Fts5SegIter *pSeg){ + + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + assert( pIter->pColset ); + + if( pSeg->iLeafOffset+pSeg->nPos>pSeg->pLeaf->szLeaf ){ + fts5IterSetOutputs_Col(pIter, pSeg); + }else{ + u8 *a = (u8*)&pSeg->pLeaf->p[pSeg->iLeafOffset]; + u8 *pEnd = (u8*)&a[pSeg->nPos]; + int iPrev = 0; + int *aiCol = pIter->pColset->aiCol; + int *aiColEnd = &aiCol[pIter->pColset->nCol]; + + u8 *aOut = pIter->poslist.p; + int iPrevOut = 0; + + pIter->base.iRowid = pSeg->iRowid; + + while( abase.pData = pIter->poslist.p; + pIter->base.nData = aOut - pIter->poslist.p; + } +} + +/* +** xSetOutputs callback used by detail=full when there is a column filter. +*/ +static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){ + Fts5Colset *pColset = pIter->pColset; + pIter->base.iRowid = pSeg->iRowid; + + assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_FULL ); + assert( pColset ); + + if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){ + /* All data is stored on the current page. Populate the output + ** variables to point into the body of the page object. */ + const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset]; + if( pColset->nCol==1 ){ + pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]); + pIter->base.pData = a; + }else{ + fts5BufferZero(&pIter->poslist); + fts5IndexExtractColset(pColset, a, pSeg->nPos, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; + } + }else{ + /* The data is distributed over two or more pages. Copy it into the + ** Fts5Iter.poslist buffer and then set the output pointer to point + ** to this buffer. */ + fts5BufferZero(&pIter->poslist); + fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist); + pIter->base.pData = pIter->poslist.p; + pIter->base.nData = pIter->poslist.n; + } +} + +static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){ + if( *pRc==SQLITE_OK ){ + Fts5Config *pConfig = pIter->pIndex->pConfig; + if( pConfig->eDetail==FTS5_DETAIL_NONE ){ + pIter->xSetOutputs = fts5IterSetOutputs_None; + } + + else if( pIter->pColset==0 ){ + pIter->xSetOutputs = fts5IterSetOutputs_Nocolset; + } + + else if( pConfig->eDetail==FTS5_DETAIL_FULL ){ + pIter->xSetOutputs = fts5IterSetOutputs_Full; + } + + else{ + assert( pConfig->eDetail==FTS5_DETAIL_COLUMNS ); + if( pConfig->nCol<=100 ){ + pIter->xSetOutputs = fts5IterSetOutputs_Col100; + sqlite3Fts5BufferSize(pRc, &pIter->poslist, pConfig->nCol); + }else{ + pIter->xSetOutputs = fts5IterSetOutputs_Col; + } + } + } +} + + +/* +** Allocate a new Fts5Iter object. +** +** The new object will be used to iterate through data in structure pStruct. +** If iLevel is -ve, then all data in all segments is merged. Or, if iLevel +** is zero or greater, data from the first nSegment segments on level iLevel +** is merged. +** +** The iterator initially points to the first term/rowid entry in the +** iterated data. +*/ +static void fts5MultiIterNew( + Fts5Index *p, /* FTS5 backend to iterate within */ + Fts5Structure *pStruct, /* Structure of specific index */ + int flags, /* FTS5INDEX_QUERY_XXX flags */ + Fts5Colset *pColset, /* Colset to filter on (or NULL) */ + const u8 *pTerm, int nTerm, /* Term to seek to (or NULL/0) */ + int iLevel, /* Level to iterate (-1 for all) */ + int nSegment, /* Number of segments to merge (iLevel>=0) */ + Fts5Iter **ppOut /* New object */ +){ + int nSeg = 0; /* Number of segment-iters in use */ + int iIter = 0; /* */ + int iSeg; /* Used to iterate through segments */ + Fts5StructureLevel *pLvl; + Fts5Iter *pNew; + + assert( (pTerm==0 && nTerm==0) || iLevel<0 ); + + /* Allocate space for the new multi-seg-iterator. */ + if( p->rc==SQLITE_OK ){ + if( iLevel<0 ){ + assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); + nSeg = pStruct->nSegment; + nSeg += (p->pHash ? 1 : 0); + }else{ + nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); + } + } + *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); + if( pNew==0 ) return; + pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); + pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY)); + pNew->pStruct = pStruct; + pNew->pColset = pColset; + fts5StructureRef(pStruct); + if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){ + fts5IterSetOutputCb(&p->rc, pNew); + } + + /* Initialize each of the component segment iterators. */ + if( p->rc==SQLITE_OK ){ + if( iLevel<0 ){ + Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; + if( p->pHash ){ + /* Add a segment iterator for the current contents of the hash table. */ + Fts5SegIter *pIter = &pNew->aSeg[iIter++]; + fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); + } + for(pLvl=&pStruct->aLevel[0]; pLvlnSeg-1; iSeg>=0; iSeg--){ + Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; + Fts5SegIter *pIter = &pNew->aSeg[iIter++]; + if( pTerm==0 ){ + fts5SegIterInit(p, pSeg, pIter); + }else{ + fts5SegIterSeekInit(p, pTerm, nTerm, flags, pSeg, pIter); + } + } + } + }else{ + pLvl = &pStruct->aLevel[iLevel]; + for(iSeg=nSeg-1; iSeg>=0; iSeg--){ + fts5SegIterInit(p, &pLvl->aSeg[iSeg], &pNew->aSeg[iIter++]); + } + } + assert( iIter==nSeg ); + } + + /* If the above was successful, each component iterators now points + ** to the first entry in its segment. In this case initialize the + ** aFirst[] array. Or, if an error has occurred, free the iterator + ** object and set the output variable to NULL. */ + if( p->rc==SQLITE_OK ){ + for(iIter=pNew->nSeg-1; iIter>0; iIter--){ + int iEq; + if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){ + Fts5SegIter *pSeg = &pNew->aSeg[iEq]; + if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0); + fts5MultiIterAdvanced(p, pNew, iEq, iIter); + } + } + fts5MultiIterSetEof(pNew); + fts5AssertMultiIterSetup(p, pNew); + + if( pNew->bSkipEmpty && fts5MultiIterIsEmpty(p, pNew) ){ + fts5MultiIterNext(p, pNew, 0, 0); + }else if( pNew->base.bEof==0 ){ + Fts5SegIter *pSeg = &pNew->aSeg[pNew->aFirst[1].iFirst]; + pNew->xSetOutputs(pNew, pSeg); + } + + }else{ + fts5MultiIterFree(pNew); + *ppOut = 0; + } +} + +/* +** Create an Fts5Iter that iterates through the doclist provided +** as the second argument. +*/ +static void fts5MultiIterNew2( + Fts5Index *p, /* FTS5 backend to iterate within */ + Fts5Data *pData, /* Doclist to iterate through */ + int bDesc, /* True for descending rowid order */ + Fts5Iter **ppOut /* New object */ +){ + Fts5Iter *pNew; + pNew = fts5MultiIterAlloc(p, 2); + if( pNew ){ + Fts5SegIter *pIter = &pNew->aSeg[1]; + + pIter->flags = FTS5_SEGITER_ONETERM; + if( pData->szLeaf>0 ){ + pIter->pLeaf = pData; + pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid); + pIter->iEndofDoclist = pData->nn; + pNew->aFirst[1].iFirst = 1; + if( bDesc ){ + pNew->bRev = 1; + pIter->flags |= FTS5_SEGITER_REVERSE; + fts5SegIterReverseInitPage(p, pIter); + }else{ + fts5SegIterLoadNPos(p, pIter); + } + pData = 0; + }else{ + pNew->base.bEof = 1; + } + fts5SegIterSetNext(p, pIter); + + *ppOut = pNew; + } + + fts5DataRelease(pData); +} + +/* +** Return true if the iterator is at EOF or if an error has occurred. +** False otherwise. +*/ +static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){ + assert( p->rc + || (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof + ); + return (p->rc || pIter->base.bEof); +} + +/* +** Return the rowid of the entry that the iterator currently points +** to. If the iterator points to EOF when this function is called the +** results are undefined. +*/ +static i64 fts5MultiIterRowid(Fts5Iter *pIter){ + assert( pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf ); + return pIter->aSeg[ pIter->aFirst[1].iFirst ].iRowid; +} + +/* +** Move the iterator to the next entry at or following iMatch. +*/ +static void fts5MultiIterNextFrom( + Fts5Index *p, + Fts5Iter *pIter, + i64 iMatch +){ + while( 1 ){ + i64 iRowid; + fts5MultiIterNext(p, pIter, 1, iMatch); + if( fts5MultiIterEof(p, pIter) ) break; + iRowid = fts5MultiIterRowid(pIter); + if( pIter->bRev==0 && iRowid>=iMatch ) break; + if( pIter->bRev!=0 && iRowid<=iMatch ) break; + } +} + +/* +** Return a pointer to a buffer containing the term associated with the +** entry that the iterator currently points to. +*/ +static const u8 *fts5MultiIterTerm(Fts5Iter *pIter, int *pn){ + Fts5SegIter *p = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; + *pn = p->term.n; + return p->term.p; +} + +/* +** Allocate a new segment-id for the structure pStruct. The new segment +** id must be between 1 and 65335 inclusive, and must not be used by +** any currently existing segment. If a free segment id cannot be found, +** SQLITE_FULL is returned. +** +** If an error has already occurred, this function is a no-op. 0 is +** returned in this case. +*/ +static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){ + int iSegid = 0; + + if( p->rc==SQLITE_OK ){ + if( pStruct->nSegment>=FTS5_MAX_SEGMENT ){ + p->rc = SQLITE_FULL; + }else{ + while( iSegid==0 ){ + int iLvl, iSeg; + sqlite3_randomness(sizeof(u32), (void*)&iSegid); + iSegid = iSegid & ((1 << FTS5_DATA_ID_B)-1); + for(iLvl=0; iLvlnLevel; iLvl++){ + for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ + if( iSegid==pStruct->aLevel[iLvl].aSeg[iSeg].iSegid ){ + iSegid = 0; + } + } + } + } + } + } + + return iSegid; +} + +/* +** Discard all data currently cached in the hash-tables. +*/ +static void fts5IndexDiscardData(Fts5Index *p){ + assert( p->pHash || p->nPendingData==0 ); + if( p->pHash ){ + sqlite3Fts5HashClear(p->pHash); + p->nPendingData = 0; + } +} + +/* +** Return the size of the prefix, in bytes, that buffer +** (pNew/) shares with buffer (pOld/nOld). +** +** Buffer (pNew/) is guaranteed to be greater +** than buffer (pOld/nOld). +*/ +static int fts5PrefixCompress(int nOld, const u8 *pOld, const u8 *pNew){ + int i; + for(i=0; inDlidx>0 && pWriter->aDlidx[0].buf.n>0) ); + for(i=0; inDlidx; i++){ + Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[i]; + if( pDlidx->buf.n==0 ) break; + if( bFlush ){ + assert( pDlidx->pgno!=0 ); + fts5DataWrite(p, + FTS5_DLIDX_ROWID(pWriter->iSegid, i, pDlidx->pgno), + pDlidx->buf.p, pDlidx->buf.n + ); + } + sqlite3Fts5BufferZero(&pDlidx->buf); + pDlidx->bPrevValid = 0; + } +} + +/* +** Grow the pWriter->aDlidx[] array to at least nLvl elements in size. +** Any new array elements are zeroed before returning. +*/ +static int fts5WriteDlidxGrow( + Fts5Index *p, + Fts5SegWriter *pWriter, + int nLvl +){ + if( p->rc==SQLITE_OK && nLvl>=pWriter->nDlidx ){ + Fts5DlidxWriter *aDlidx = (Fts5DlidxWriter*)sqlite3_realloc( + pWriter->aDlidx, sizeof(Fts5DlidxWriter) * nLvl + ); + if( aDlidx==0 ){ + p->rc = SQLITE_NOMEM; + }else{ + int nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx); + memset(&aDlidx[pWriter->nDlidx], 0, nByte); + pWriter->aDlidx = aDlidx; + pWriter->nDlidx = nLvl; + } + } + return p->rc; +} + +/* +** If the current doclist-index accumulating in pWriter->aDlidx[] is large +** enough, flush it to disk and return 1. Otherwise discard it and return +** zero. +*/ +static int fts5WriteFlushDlidx(Fts5Index *p, Fts5SegWriter *pWriter){ + int bFlag = 0; + + /* If there were FTS5_MIN_DLIDX_SIZE or more empty leaf pages written + ** to the database, also write the doclist-index to disk. */ + if( pWriter->aDlidx[0].buf.n>0 && pWriter->nEmpty>=FTS5_MIN_DLIDX_SIZE ){ + bFlag = 1; + } + fts5WriteDlidxClear(p, pWriter, bFlag); + pWriter->nEmpty = 0; + return bFlag; +} + +/* +** This function is called whenever processing of the doclist for the +** last term on leaf page (pWriter->iBtPage) is completed. +** +** The doclist-index for that term is currently stored in-memory within the +** Fts5SegWriter.aDlidx[] array. If it is large enough, this function +** writes it out to disk. Or, if it is too small to bother with, discards +** it. +** +** Fts5SegWriter.btterm currently contains the first term on page iBtPage. +*/ +static void fts5WriteFlushBtree(Fts5Index *p, Fts5SegWriter *pWriter){ + int bFlag; + + assert( pWriter->iBtPage || pWriter->nEmpty==0 ); + if( pWriter->iBtPage==0 ) return; + bFlag = fts5WriteFlushDlidx(p, pWriter); + + if( p->rc==SQLITE_OK ){ + const char *z = (pWriter->btterm.n>0?(const char*)pWriter->btterm.p:""); + /* The following was already done in fts5WriteInit(): */ + /* sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid); */ + sqlite3_bind_blob(p->pIdxWriter, 2, z, pWriter->btterm.n, SQLITE_STATIC); + sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1)); + sqlite3_step(p->pIdxWriter); + p->rc = sqlite3_reset(p->pIdxWriter); + } + pWriter->iBtPage = 0; +} + +/* +** This is called once for each leaf page except the first that contains +** at least one term. Argument (nTerm/pTerm) is the split-key - a term that +** is larger than all terms written to earlier leaves, and equal to or +** smaller than the first term on the new leaf. +** +** If an error occurs, an error code is left in Fts5Index.rc. If an error +** has already occurred when this function is called, it is a no-op. +*/ +static void fts5WriteBtreeTerm( + Fts5Index *p, /* FTS5 backend object */ + Fts5SegWriter *pWriter, /* Writer object */ + int nTerm, const u8 *pTerm /* First term on new page */ +){ + fts5WriteFlushBtree(p, pWriter); + fts5BufferSet(&p->rc, &pWriter->btterm, nTerm, pTerm); + pWriter->iBtPage = pWriter->writer.pgno; +} + +/* +** This function is called when flushing a leaf page that contains no +** terms at all to disk. +*/ +static void fts5WriteBtreeNoTerm( + Fts5Index *p, /* FTS5 backend object */ + Fts5SegWriter *pWriter /* Writer object */ +){ + /* If there were no rowids on the leaf page either and the doclist-index + ** has already been started, append an 0x00 byte to it. */ + if( pWriter->bFirstRowidInPage && pWriter->aDlidx[0].buf.n>0 ){ + Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[0]; + assert( pDlidx->bPrevValid ); + sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, 0); + } + + /* Increment the "number of sequential leaves without a term" counter. */ + pWriter->nEmpty++; +} + +static i64 fts5DlidxExtractFirstRowid(Fts5Buffer *pBuf){ + i64 iRowid; + int iOff; + + iOff = 1 + fts5GetVarint(&pBuf->p[1], (u64*)&iRowid); + fts5GetVarint(&pBuf->p[iOff], (u64*)&iRowid); + return iRowid; +} + +/* +** Rowid iRowid has just been appended to the current leaf page. It is the +** first on the page. This function appends an appropriate entry to the current +** doclist-index. +*/ +static void fts5WriteDlidxAppend( + Fts5Index *p, + Fts5SegWriter *pWriter, + i64 iRowid +){ + int i; + int bDone = 0; + + for(i=0; p->rc==SQLITE_OK && bDone==0; i++){ + i64 iVal; + Fts5DlidxWriter *pDlidx = &pWriter->aDlidx[i]; + + if( pDlidx->buf.n>=p->pConfig->pgsz ){ + /* The current doclist-index page is full. Write it to disk and push + ** a copy of iRowid (which will become the first rowid on the next + ** doclist-index leaf page) up into the next level of the b-tree + ** hierarchy. If the node being flushed is currently the root node, + ** also push its first rowid upwards. */ + pDlidx->buf.p[0] = 0x01; /* Not the root node */ + fts5DataWrite(p, + FTS5_DLIDX_ROWID(pWriter->iSegid, i, pDlidx->pgno), + pDlidx->buf.p, pDlidx->buf.n + ); + fts5WriteDlidxGrow(p, pWriter, i+2); + pDlidx = &pWriter->aDlidx[i]; + if( p->rc==SQLITE_OK && pDlidx[1].buf.n==0 ){ + i64 iFirst = fts5DlidxExtractFirstRowid(&pDlidx->buf); + + /* This was the root node. Push its first rowid up to the new root. */ + pDlidx[1].pgno = pDlidx->pgno; + sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, 0); + sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, pDlidx->pgno); + sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx[1].buf, iFirst); + pDlidx[1].bPrevValid = 1; + pDlidx[1].iPrev = iFirst; + } + + sqlite3Fts5BufferZero(&pDlidx->buf); + pDlidx->bPrevValid = 0; + pDlidx->pgno++; + }else{ + bDone = 1; + } + + if( pDlidx->bPrevValid ){ + iVal = iRowid - pDlidx->iPrev; + }else{ + i64 iPgno = (i==0 ? pWriter->writer.pgno : pDlidx[-1].pgno); + assert( pDlidx->buf.n==0 ); + sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, !bDone); + sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, iPgno); + iVal = iRowid; + } + + sqlite3Fts5BufferAppendVarint(&p->rc, &pDlidx->buf, iVal); + pDlidx->bPrevValid = 1; + pDlidx->iPrev = iRowid; + } +} + +static void fts5WriteFlushLeaf(Fts5Index *p, Fts5SegWriter *pWriter){ + static const u8 zero[] = { 0x00, 0x00, 0x00, 0x00 }; + Fts5PageWriter *pPage = &pWriter->writer; + i64 iRowid; + + assert( (pPage->pgidx.n==0)==(pWriter->bFirstTermInPage) ); + + /* Set the szLeaf header field. */ + assert( 0==fts5GetU16(&pPage->buf.p[2]) ); + fts5PutU16(&pPage->buf.p[2], (u16)pPage->buf.n); + + if( pWriter->bFirstTermInPage ){ + /* No term was written to this page. */ + assert( pPage->pgidx.n==0 ); + fts5WriteBtreeNoTerm(p, pWriter); + }else{ + /* Append the pgidx to the page buffer. Set the szLeaf header field. */ + fts5BufferAppendBlob(&p->rc, &pPage->buf, pPage->pgidx.n, pPage->pgidx.p); + } + + /* Write the page out to disk */ + iRowid = FTS5_SEGMENT_ROWID(pWriter->iSegid, pPage->pgno); + fts5DataWrite(p, iRowid, pPage->buf.p, pPage->buf.n); + + /* Initialize the next page. */ + fts5BufferZero(&pPage->buf); + fts5BufferZero(&pPage->pgidx); + fts5BufferAppendBlob(&p->rc, &pPage->buf, 4, zero); + pPage->iPrevPgidx = 0; + pPage->pgno++; + + /* Increase the leaves written counter */ + pWriter->nLeafWritten++; + + /* The new leaf holds no terms or rowids */ + pWriter->bFirstTermInPage = 1; + pWriter->bFirstRowidInPage = 1; +} + +/* +** Append term pTerm/nTerm to the segment being written by the writer passed +** as the second argument. +** +** If an error occurs, set the Fts5Index.rc error code. If an error has +** already occurred, this function is a no-op. +*/ +static void fts5WriteAppendTerm( + Fts5Index *p, + Fts5SegWriter *pWriter, + int nTerm, const u8 *pTerm +){ + int nPrefix; /* Bytes of prefix compression for term */ + Fts5PageWriter *pPage = &pWriter->writer; + Fts5Buffer *pPgidx = &pWriter->writer.pgidx; + + assert( p->rc==SQLITE_OK ); + assert( pPage->buf.n>=4 ); + assert( pPage->buf.n>4 || pWriter->bFirstTermInPage ); + + /* If the current leaf page is full, flush it to disk. */ + if( (pPage->buf.n + pPgidx->n + nTerm + 2)>=p->pConfig->pgsz ){ + if( pPage->buf.n>4 ){ + fts5WriteFlushLeaf(p, pWriter); + } + fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING); + } + + /* TODO1: Updating pgidx here. */ + pPgidx->n += sqlite3Fts5PutVarint( + &pPgidx->p[pPgidx->n], pPage->buf.n - pPage->iPrevPgidx + ); + pPage->iPrevPgidx = pPage->buf.n; +#if 0 + fts5PutU16(&pPgidx->p[pPgidx->n], pPage->buf.n); + pPgidx->n += 2; +#endif + + if( pWriter->bFirstTermInPage ){ + nPrefix = 0; + if( pPage->pgno!=1 ){ + /* This is the first term on a leaf that is not the leftmost leaf in + ** the segment b-tree. In this case it is necessary to add a term to + ** the b-tree hierarchy that is (a) larger than the largest term + ** already written to the segment and (b) smaller than or equal to + ** this term. In other words, a prefix of (pTerm/nTerm) that is one + ** byte longer than the longest prefix (pTerm/nTerm) shares with the + ** previous term. + ** + ** Usually, the previous term is available in pPage->term. The exception + ** is if this is the first term written in an incremental-merge step. + ** In this case the previous term is not available, so just write a + ** copy of (pTerm/nTerm) into the parent node. This is slightly + ** inefficient, but still correct. */ + int n = nTerm; + if( pPage->term.n ){ + n = 1 + fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm); + } + fts5WriteBtreeTerm(p, pWriter, n, pTerm); + pPage = &pWriter->writer; + } + }else{ + nPrefix = fts5PrefixCompress(pPage->term.n, pPage->term.p, pTerm); + fts5BufferAppendVarint(&p->rc, &pPage->buf, nPrefix); + } + + /* Append the number of bytes of new data, then the term data itself + ** to the page. */ + fts5BufferAppendVarint(&p->rc, &pPage->buf, nTerm - nPrefix); + fts5BufferAppendBlob(&p->rc, &pPage->buf, nTerm - nPrefix, &pTerm[nPrefix]); + + /* Update the Fts5PageWriter.term field. */ + fts5BufferSet(&p->rc, &pPage->term, nTerm, pTerm); + pWriter->bFirstTermInPage = 0; + + pWriter->bFirstRowidInPage = 0; + pWriter->bFirstRowidInDoclist = 1; + + assert( p->rc || (pWriter->nDlidx>0 && pWriter->aDlidx[0].buf.n==0) ); + pWriter->aDlidx[0].pgno = pPage->pgno; +} + +/* +** Append a rowid and position-list size field to the writers output. +*/ +static void fts5WriteAppendRowid( + Fts5Index *p, + Fts5SegWriter *pWriter, + i64 iRowid +){ + if( p->rc==SQLITE_OK ){ + Fts5PageWriter *pPage = &pWriter->writer; + + if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){ + fts5WriteFlushLeaf(p, pWriter); + } + + /* If this is to be the first rowid written to the page, set the + ** rowid-pointer in the page-header. Also append a value to the dlidx + ** buffer, in case a doclist-index is required. */ + if( pWriter->bFirstRowidInPage ){ + fts5PutU16(pPage->buf.p, (u16)pPage->buf.n); + fts5WriteDlidxAppend(p, pWriter, iRowid); + } + + /* Write the rowid. */ + if( pWriter->bFirstRowidInDoclist || pWriter->bFirstRowidInPage ){ + fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid); + }else{ + assert( p->rc || iRowid>pWriter->iPrevRowid ); + fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid); + } + pWriter->iPrevRowid = iRowid; + pWriter->bFirstRowidInDoclist = 0; + pWriter->bFirstRowidInPage = 0; + } +} + +static void fts5WriteAppendPoslistData( + Fts5Index *p, + Fts5SegWriter *pWriter, + const u8 *aData, + int nData +){ + Fts5PageWriter *pPage = &pWriter->writer; + const u8 *a = aData; + int n = nData; + + assert( p->pConfig->pgsz>0 ); + while( p->rc==SQLITE_OK + && (pPage->buf.n + pPage->pgidx.n + n)>=p->pConfig->pgsz + ){ + int nReq = p->pConfig->pgsz - pPage->buf.n - pPage->pgidx.n; + int nCopy = 0; + while( nCopyrc, &pPage->buf, nCopy, a); + a += nCopy; + n -= nCopy; + fts5WriteFlushLeaf(p, pWriter); + } + if( n>0 ){ + fts5BufferAppendBlob(&p->rc, &pPage->buf, n, a); + } +} + +/* +** Flush any data cached by the writer object to the database. Free any +** allocations associated with the writer. +*/ +static void fts5WriteFinish( + Fts5Index *p, + Fts5SegWriter *pWriter, /* Writer object */ + int *pnLeaf /* OUT: Number of leaf pages in b-tree */ +){ + int i; + Fts5PageWriter *pLeaf = &pWriter->writer; + if( p->rc==SQLITE_OK ){ + assert( pLeaf->pgno>=1 ); + if( pLeaf->buf.n>4 ){ + fts5WriteFlushLeaf(p, pWriter); + } + *pnLeaf = pLeaf->pgno-1; + fts5WriteFlushBtree(p, pWriter); + } + fts5BufferFree(&pLeaf->term); + fts5BufferFree(&pLeaf->buf); + fts5BufferFree(&pLeaf->pgidx); + fts5BufferFree(&pWriter->btterm); + + for(i=0; inDlidx; i++){ + sqlite3Fts5BufferFree(&pWriter->aDlidx[i].buf); + } + sqlite3_free(pWriter->aDlidx); +} + +static void fts5WriteInit( + Fts5Index *p, + Fts5SegWriter *pWriter, + int iSegid +){ + const int nBuffer = p->pConfig->pgsz + FTS5_DATA_PADDING; + + memset(pWriter, 0, sizeof(Fts5SegWriter)); + pWriter->iSegid = iSegid; + + fts5WriteDlidxGrow(p, pWriter, 1); + pWriter->writer.pgno = 1; + pWriter->bFirstTermInPage = 1; + pWriter->iBtPage = 1; + + assert( pWriter->writer.buf.n==0 ); + assert( pWriter->writer.pgidx.n==0 ); + + /* Grow the two buffers to pgsz + padding bytes in size. */ + sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.pgidx, nBuffer); + sqlite3Fts5BufferSize(&p->rc, &pWriter->writer.buf, nBuffer); + + if( p->pIdxWriter==0 ){ + Fts5Config *pConfig = p->pConfig; + fts5IndexPrepareStmt(p, &p->pIdxWriter, sqlite3_mprintf( + "INSERT INTO '%q'.'%q_idx'(segid,term,pgno) VALUES(?,?,?)", + pConfig->zDb, pConfig->zName + )); + } + + if( p->rc==SQLITE_OK ){ + /* Initialize the 4-byte leaf-page header to 0x00. */ + memset(pWriter->writer.buf.p, 0, 4); + pWriter->writer.buf.n = 4; + + /* Bind the current output segment id to the index-writer. This is an + ** optimization over binding the same value over and over as rows are + ** inserted into %_idx by the current writer. */ + sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid); + } +} + +/* +** Iterator pIter was used to iterate through the input segments of on an +** incremental merge operation. This function is called if the incremental +** merge step has finished but the input has not been completely exhausted. +*/ +static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ + int i; + Fts5Buffer buf; + memset(&buf, 0, sizeof(Fts5Buffer)); + for(i=0; inSeg; i++){ + Fts5SegIter *pSeg = &pIter->aSeg[i]; + if( pSeg->pSeg==0 ){ + /* no-op */ + }else if( pSeg->pLeaf==0 ){ + /* All keys from this input segment have been transfered to the output. + ** Set both the first and last page-numbers to 0 to indicate that the + ** segment is now empty. */ + pSeg->pSeg->pgnoLast = 0; + pSeg->pSeg->pgnoFirst = 0; + }else{ + int iOff = pSeg->iTermLeafOffset; /* Offset on new first leaf page */ + i64 iLeafRowid; + Fts5Data *pData; + int iId = pSeg->pSeg->iSegid; + u8 aHdr[4] = {0x00, 0x00, 0x00, 0x00}; + + iLeafRowid = FTS5_SEGMENT_ROWID(iId, pSeg->iTermLeafPgno); + pData = fts5DataRead(p, iLeafRowid); + if( pData ){ + fts5BufferZero(&buf); + fts5BufferGrow(&p->rc, &buf, pData->nn); + fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr); + fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n); + fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p); + fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff, &pData->p[iOff]); + if( p->rc==SQLITE_OK ){ + /* Set the szLeaf field */ + fts5PutU16(&buf.p[2], (u16)buf.n); + } + + /* Set up the new page-index array */ + fts5BufferAppendVarint(&p->rc, &buf, 4); + if( pSeg->iLeafPgno==pSeg->iTermLeafPgno + && pSeg->iEndofDoclistszLeaf + ){ + int nDiff = pData->szLeaf - pSeg->iEndofDoclist; + fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4); + fts5BufferAppendBlob(&p->rc, &buf, + pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff] + ); + } + + fts5DataRelease(pData); + pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno; + fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid); + fts5DataWrite(p, iLeafRowid, buf.p, buf.n); + } + } + } + fts5BufferFree(&buf); +} + +static void fts5MergeChunkCallback( + Fts5Index *p, + void *pCtx, + const u8 *pChunk, int nChunk +){ + Fts5SegWriter *pWriter = (Fts5SegWriter*)pCtx; + fts5WriteAppendPoslistData(p, pWriter, pChunk, nChunk); +} + +/* +** +*/ +static void fts5IndexMergeLevel( + Fts5Index *p, /* FTS5 backend object */ + Fts5Structure **ppStruct, /* IN/OUT: Stucture of index */ + int iLvl, /* Level to read input from */ + int *pnRem /* Write up to this many output leaves */ +){ + Fts5Structure *pStruct = *ppStruct; + Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; + Fts5StructureLevel *pLvlOut; + Fts5Iter *pIter = 0; /* Iterator to read input data */ + int nRem = pnRem ? *pnRem : 0; /* Output leaf pages left to write */ + int nInput; /* Number of input segments */ + Fts5SegWriter writer; /* Writer object */ + Fts5StructureSegment *pSeg; /* Output segment */ + Fts5Buffer term; + int bOldest; /* True if the output segment is the oldest */ + int eDetail = p->pConfig->eDetail; + const int flags = FTS5INDEX_QUERY_NOOUTPUT; + + assert( iLvlnLevel ); + assert( pLvl->nMerge<=pLvl->nSeg ); + + memset(&writer, 0, sizeof(Fts5SegWriter)); + memset(&term, 0, sizeof(Fts5Buffer)); + if( pLvl->nMerge ){ + pLvlOut = &pStruct->aLevel[iLvl+1]; + assert( pLvlOut->nSeg>0 ); + nInput = pLvl->nMerge; + pSeg = &pLvlOut->aSeg[pLvlOut->nSeg-1]; + + fts5WriteInit(p, &writer, pSeg->iSegid); + writer.writer.pgno = pSeg->pgnoLast+1; + writer.iBtPage = 0; + }else{ + int iSegid = fts5AllocateSegid(p, pStruct); + + /* Extend the Fts5Structure object as required to ensure the output + ** segment exists. */ + if( iLvl==pStruct->nLevel-1 ){ + fts5StructureAddLevel(&p->rc, ppStruct); + pStruct = *ppStruct; + } + fts5StructureExtendLevel(&p->rc, pStruct, iLvl+1, 1, 0); + if( p->rc ) return; + pLvl = &pStruct->aLevel[iLvl]; + pLvlOut = &pStruct->aLevel[iLvl+1]; + + fts5WriteInit(p, &writer, iSegid); + + /* Add the new segment to the output level */ + pSeg = &pLvlOut->aSeg[pLvlOut->nSeg]; + pLvlOut->nSeg++; + pSeg->pgnoFirst = 1; + pSeg->iSegid = iSegid; + pStruct->nSegment++; + + /* Read input from all segments in the input level */ + nInput = pLvl->nSeg; + } + bOldest = (pLvlOut->nSeg==1 && pStruct->nLevel==iLvl+2); + + assert( iLvl>=0 ); + for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, iLvl, nInput, &pIter); + fts5MultiIterEof(p, pIter)==0; + fts5MultiIterNext(p, pIter, 0, 0) + ){ + Fts5SegIter *pSegIter = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; + int nPos; /* position-list size field value */ + int nTerm; + const u8 *pTerm; + + /* Check for key annihilation. */ + if( pSegIter->nPos==0 && (bOldest || pSegIter->bDel==0) ) continue; + + pTerm = fts5MultiIterTerm(pIter, &nTerm); + if( nTerm!=term.n || memcmp(pTerm, term.p, nTerm) ){ + if( pnRem && writer.nLeafWritten>nRem ){ + break; + } + + /* This is a new term. Append a term to the output segment. */ + fts5WriteAppendTerm(p, &writer, nTerm, pTerm); + fts5BufferSet(&p->rc, &term, nTerm, pTerm); + } + + /* Append the rowid to the output */ + /* WRITEPOSLISTSIZE */ + fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter)); + + if( eDetail==FTS5_DETAIL_NONE ){ + if( pSegIter->bDel ){ + fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0); + if( pSegIter->nPos>0 ){ + fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0); + } + } + }else{ + /* Append the position-list data to the output */ + nPos = pSegIter->nPos*2 + pSegIter->bDel; + fts5BufferAppendVarint(&p->rc, &writer.writer.buf, nPos); + fts5ChunkIterate(p, pSegIter, (void*)&writer, fts5MergeChunkCallback); + } + } + + /* Flush the last leaf page to disk. Set the output segment b-tree height + ** and last leaf page number at the same time. */ + fts5WriteFinish(p, &writer, &pSeg->pgnoLast); + + if( fts5MultiIterEof(p, pIter) ){ + int i; + + /* Remove the redundant segments from the %_data table */ + for(i=0; iaSeg[i].iSegid); + } + + /* Remove the redundant segments from the input level */ + if( pLvl->nSeg!=nInput ){ + int nMove = (pLvl->nSeg - nInput) * sizeof(Fts5StructureSegment); + memmove(pLvl->aSeg, &pLvl->aSeg[nInput], nMove); + } + pStruct->nSegment -= nInput; + pLvl->nSeg -= nInput; + pLvl->nMerge = 0; + if( pSeg->pgnoLast==0 ){ + pLvlOut->nSeg--; + pStruct->nSegment--; + } + }else{ + assert( pSeg->pgnoLast>0 ); + fts5TrimSegments(p, pIter); + pLvl->nMerge = nInput; + } + + fts5MultiIterFree(pIter); + fts5BufferFree(&term); + if( pnRem ) *pnRem -= writer.nLeafWritten; +} + +/* +** Do up to nPg pages of automerge work on the index. +*/ +static void fts5IndexMerge( + Fts5Index *p, /* FTS5 backend object */ + Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */ + int nPg /* Pages of work to do */ +){ + int nRem = nPg; + Fts5Structure *pStruct = *ppStruct; + while( nRem>0 && p->rc==SQLITE_OK ){ + int iLvl; /* To iterate through levels */ + int iBestLvl = 0; /* Level offering the most input segments */ + int nBest = 0; /* Number of input segments on best level */ + + /* Set iBestLvl to the level to read input segments from. */ + assert( pStruct->nLevel>0 ); + for(iLvl=0; iLvlnLevel; iLvl++){ + Fts5StructureLevel *pLvl = &pStruct->aLevel[iLvl]; + if( pLvl->nMerge ){ + if( pLvl->nMerge>nBest ){ + iBestLvl = iLvl; + nBest = pLvl->nMerge; + } + break; + } + if( pLvl->nSeg>nBest ){ + nBest = pLvl->nSeg; + iBestLvl = iLvl; + } + } + + /* If nBest is still 0, then the index must be empty. */ +#ifdef SQLITE_DEBUG + for(iLvl=0; nBest==0 && iLvlnLevel; iLvl++){ + assert( pStruct->aLevel[iLvl].nSeg==0 ); + } +#endif + + if( nBestpConfig->nAutomerge + && pStruct->aLevel[iBestLvl].nMerge==0 + ){ + break; + } + fts5IndexMergeLevel(p, &pStruct, iBestLvl, &nRem); + if( p->rc==SQLITE_OK && pStruct->aLevel[iBestLvl].nMerge==0 ){ + fts5StructurePromote(p, iBestLvl+1, pStruct); + } + } + *ppStruct = pStruct; +} + +/* +** A total of nLeaf leaf pages of data has just been flushed to a level-0 +** segment. This function updates the write-counter accordingly and, if +** necessary, performs incremental merge work. +** +** If an error occurs, set the Fts5Index.rc error code. If an error has +** already occurred, this function is a no-op. +*/ +static void fts5IndexAutomerge( + Fts5Index *p, /* FTS5 backend object */ + Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */ + int nLeaf /* Number of output leaves just written */ +){ + if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 ){ + Fts5Structure *pStruct = *ppStruct; + u64 nWrite; /* Initial value of write-counter */ + int nWork; /* Number of work-quanta to perform */ + int nRem; /* Number of leaf pages left to write */ + + /* Update the write-counter. While doing so, set nWork. */ + nWrite = pStruct->nWriteCounter; + nWork = (int)(((nWrite + nLeaf) / p->nWorkUnit) - (nWrite / p->nWorkUnit)); + pStruct->nWriteCounter += nLeaf; + nRem = (int)(p->nWorkUnit * nWork * pStruct->nLevel); + + fts5IndexMerge(p, ppStruct, nRem); + } +} + +static void fts5IndexCrisismerge( + Fts5Index *p, /* FTS5 backend object */ + Fts5Structure **ppStruct /* IN/OUT: Current structure of index */ +){ + const int nCrisis = p->pConfig->nCrisisMerge; + Fts5Structure *pStruct = *ppStruct; + int iLvl = 0; + + assert( p->rc!=SQLITE_OK || pStruct->nLevel>0 ); + while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){ + fts5IndexMergeLevel(p, &pStruct, iLvl, 0); + assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) ); + fts5StructurePromote(p, iLvl+1, pStruct); + iLvl++; + } + *ppStruct = pStruct; +} + +static int fts5IndexReturn(Fts5Index *p){ + int rc = p->rc; + p->rc = SQLITE_OK; + return rc; +} + +typedef struct Fts5FlushCtx Fts5FlushCtx; +struct Fts5FlushCtx { + Fts5Index *pIdx; + Fts5SegWriter writer; +}; + +/* +** Buffer aBuf[] contains a list of varints, all small enough to fit +** in a 32-bit integer. Return the size of the largest prefix of this +** list nMax bytes or less in size. +*/ +static int fts5PoslistPrefix(const u8 *aBuf, int nMax){ + int ret; + u32 dummy; + ret = fts5GetVarint32(aBuf, dummy); + if( ret nMax ) break; + ret += i; + } + } + return ret; +} + +/* +** Flush the contents of in-memory hash table iHash to a new level-0 +** segment on disk. Also update the corresponding structure record. +** +** If an error occurs, set the Fts5Index.rc error code. If an error has +** already occurred, this function is a no-op. +*/ +static void fts5FlushOneHash(Fts5Index *p){ + Fts5Hash *pHash = p->pHash; + Fts5Structure *pStruct; + int iSegid; + int pgnoLast = 0; /* Last leaf page number in segment */ + + /* Obtain a reference to the index structure and allocate a new segment-id + ** for the new level-0 segment. */ + pStruct = fts5StructureRead(p); + iSegid = fts5AllocateSegid(p, pStruct); + + if( iSegid ){ + const int pgsz = p->pConfig->pgsz; + int eDetail = p->pConfig->eDetail; + Fts5StructureSegment *pSeg; /* New segment within pStruct */ + Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */ + Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */ + + Fts5SegWriter writer; + fts5WriteInit(p, &writer, iSegid); + + pBuf = &writer.writer.buf; + pPgidx = &writer.writer.pgidx; + + /* fts5WriteInit() should have initialized the buffers to (most likely) + ** the maximum space required. */ + assert( p->rc || pBuf->nSpace>=(pgsz + FTS5_DATA_PADDING) ); + assert( p->rc || pPgidx->nSpace>=(pgsz + FTS5_DATA_PADDING) ); + + /* Begin scanning through hash table entries. This loop runs once for each + ** term/doclist currently stored within the hash table. */ + if( p->rc==SQLITE_OK ){ + p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0); + } + while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){ + const char *zTerm; /* Buffer containing term */ + const u8 *pDoclist; /* Pointer to doclist for this term */ + int nDoclist; /* Size of doclist in bytes */ + + /* Write the term for this entry to disk. */ + sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist); + fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm); + + assert( writer.bFirstRowidInPage==0 ); + if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){ + /* The entire doclist will fit on the current leaf. */ + fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist); + }else{ + i64 iRowid = 0; + i64 iDelta = 0; + int iOff = 0; + + /* The entire doclist will not fit on this leaf. The following + ** loop iterates through the poslists that make up the current + ** doclist. */ + while( p->rc==SQLITE_OK && iOffp[0], (u16)pBuf->n); /* first rowid on page */ + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid); + writer.bFirstRowidInPage = 0; + fts5WriteDlidxAppend(p, &writer, iRowid); + }else{ + pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta); + } + assert( pBuf->n<=pBuf->nSpace ); + + if( eDetail==FTS5_DETAIL_NONE ){ + if( iOffp[pBuf->n++] = 0; + iOff++; + if( iOffp[pBuf->n++] = 0; + iOff++; + } + } + if( (pBuf->n + pPgidx->n)>=pgsz ){ + fts5WriteFlushLeaf(p, &writer); + } + }else{ + int bDummy; + int nPos; + int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy); + nCopy += nPos; + if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){ + /* The entire poslist will fit on the current leaf. So copy + ** it in one go. */ + fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy); + }else{ + /* The entire poslist will not fit on this leaf. So it needs + ** to be broken into sections. The only qualification being + ** that each varint must be stored contiguously. */ + const u8 *pPoslist = &pDoclist[iOff]; + int iPos = 0; + while( p->rc==SQLITE_OK ){ + int nSpace = pgsz - pBuf->n - pPgidx->n; + int n = 0; + if( (nCopy - iPos)<=nSpace ){ + n = nCopy - iPos; + }else{ + n = fts5PoslistPrefix(&pPoslist[iPos], nSpace); + } + assert( n>0 ); + fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n); + iPos += n; + if( (pBuf->n + pPgidx->n)>=pgsz ){ + fts5WriteFlushLeaf(p, &writer); + } + if( iPos>=nCopy ) break; + } + } + iOff += nCopy; + } + } + } + + /* TODO2: Doclist terminator written here. */ + /* pBuf->p[pBuf->n++] = '\0'; */ + assert( pBuf->n<=pBuf->nSpace ); + sqlite3Fts5HashScanNext(pHash); + } + sqlite3Fts5HashClear(pHash); + fts5WriteFinish(p, &writer, &pgnoLast); + + /* Update the Fts5Structure. It is written back to the database by the + ** fts5StructureRelease() call below. */ + if( pStruct->nLevel==0 ){ + fts5StructureAddLevel(&p->rc, &pStruct); + } + fts5StructureExtendLevel(&p->rc, pStruct, 0, 1, 0); + if( p->rc==SQLITE_OK ){ + pSeg = &pStruct->aLevel[0].aSeg[ pStruct->aLevel[0].nSeg++ ]; + pSeg->iSegid = iSegid; + pSeg->pgnoFirst = 1; + pSeg->pgnoLast = pgnoLast; + pStruct->nSegment++; + } + fts5StructurePromote(p, 0, pStruct); + } + + fts5IndexAutomerge(p, &pStruct, pgnoLast); + fts5IndexCrisismerge(p, &pStruct); + fts5StructureWrite(p, pStruct); + fts5StructureRelease(pStruct); +} + +/* +** Flush any data stored in the in-memory hash tables to the database. +*/ +static void fts5IndexFlush(Fts5Index *p){ + /* Unless it is empty, flush the hash table to disk */ + if( p->nPendingData ){ + assert( p->pHash ); + p->nPendingData = 0; + fts5FlushOneHash(p); + } +} + + +int sqlite3Fts5IndexOptimize(Fts5Index *p){ + Fts5Structure *pStruct; + Fts5Structure *pNew = 0; + int nSeg = 0; + + assert( p->rc==SQLITE_OK ); + fts5IndexFlush(p); + pStruct = fts5StructureRead(p); + + if( pStruct ){ + assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); + nSeg = pStruct->nSegment; + if( nSeg>1 ){ + int nByte = sizeof(Fts5Structure); + nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel); + pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); + } + } + if( pNew ){ + Fts5StructureLevel *pLvl; + int nByte = nSeg * sizeof(Fts5StructureSegment); + pNew->nLevel = pStruct->nLevel+1; + pNew->nRef = 1; + pNew->nWriteCounter = pStruct->nWriteCounter; + pLvl = &pNew->aLevel[pStruct->nLevel]; + pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte); + if( pLvl->aSeg ){ + int iLvl, iSeg; + int iSegOut = 0; + for(iLvl=0; iLvlnLevel; iLvl++){ + for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ + pLvl->aSeg[iSegOut] = pStruct->aLevel[iLvl].aSeg[iSeg]; + iSegOut++; + } + } + pNew->nSegment = pLvl->nSeg = nSeg; + }else{ + sqlite3_free(pNew); + pNew = 0; + } + } + + if( pNew ){ + int iLvl = pNew->nLevel-1; + while( p->rc==SQLITE_OK && pNew->aLevel[iLvl].nSeg>0 ){ + int nRem = FTS5_OPT_WORK_UNIT; + fts5IndexMergeLevel(p, &pNew, iLvl, &nRem); + } + + fts5StructureWrite(p, pNew); + fts5StructureRelease(pNew); + } + + fts5StructureRelease(pStruct); + return fts5IndexReturn(p); +} + +int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){ + Fts5Structure *pStruct; + + pStruct = fts5StructureRead(p); + if( pStruct && pStruct->nLevel ){ + fts5IndexMerge(p, &pStruct, nMerge); + fts5StructureWrite(p, pStruct); + } + fts5StructureRelease(pStruct); + + return fts5IndexReturn(p); +} + +static void fts5AppendRowid( + Fts5Index *p, + i64 iDelta, + Fts5Iter *pUnused, + Fts5Buffer *pBuf +){ + UNUSED_PARAM(pUnused); + fts5BufferAppendVarint(&p->rc, pBuf, iDelta); +} + +static void fts5AppendPoslist( + Fts5Index *p, + i64 iDelta, + Fts5Iter *pMulti, + Fts5Buffer *pBuf +){ + int nData = pMulti->base.nData; + assert( nData>0 ); + if( p->rc==SQLITE_OK && 0==fts5BufferGrow(&p->rc, pBuf, nData+9+9) ){ + fts5BufferSafeAppendVarint(pBuf, iDelta); + fts5BufferSafeAppendVarint(pBuf, nData*2); + fts5BufferSafeAppendBlob(pBuf, pMulti->base.pData, nData); + } +} + + +static void fts5DoclistIterNext(Fts5DoclistIter *pIter){ + u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist; + + assert( pIter->aPoslist ); + if( p>=pIter->aEof ){ + pIter->aPoslist = 0; + }else{ + i64 iDelta; + + p += fts5GetVarint(p, (u64*)&iDelta); + pIter->iRowid += iDelta; + + /* Read position list size */ + if( p[0] & 0x80 ){ + int nPos; + pIter->nSize = fts5GetVarint32(p, nPos); + pIter->nPoslist = (nPos>>1); + }else{ + pIter->nPoslist = ((int)(p[0])) >> 1; + pIter->nSize = 1; + } + + pIter->aPoslist = p; + } +} + +static void fts5DoclistIterInit( + Fts5Buffer *pBuf, + Fts5DoclistIter *pIter +){ + memset(pIter, 0, sizeof(*pIter)); + pIter->aPoslist = pBuf->p; + pIter->aEof = &pBuf->p[pBuf->n]; + fts5DoclistIterNext(pIter); +} + +#if 0 +/* +** Append a doclist to buffer pBuf. +** +** This function assumes that space within the buffer has already been +** allocated. +*/ +static void fts5MergeAppendDocid( + Fts5Buffer *pBuf, /* Buffer to write to */ + i64 *piLastRowid, /* IN/OUT: Previous rowid written (if any) */ + i64 iRowid /* Rowid to append */ +){ + assert( pBuf->n!=0 || (*piLastRowid)==0 ); + fts5BufferSafeAppendVarint(pBuf, iRowid - *piLastRowid); + *piLastRowid = iRowid; +} +#endif + +#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \ + assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \ + fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \ + (iLastRowid) = (iRowid); \ +} + +/* +** Swap the contents of buffer *p1 with that of *p2. +*/ +static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){ + Fts5Buffer tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} + +static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){ + int i = *piOff; + if( i>=pBuf->n ){ + *piOff = -1; + }else{ + u64 iVal; + *piOff = i + sqlite3Fts5GetVarint(&pBuf->p[i], &iVal); + *piRowid += iVal; + } +} + +/* +** This is the equivalent of fts5MergePrefixLists() for detail=none mode. +** In this case the buffers consist of a delta-encoded list of rowids only. +*/ +static void fts5MergeRowidLists( + Fts5Index *p, /* FTS5 backend object */ + Fts5Buffer *p1, /* First list to merge */ + Fts5Buffer *p2 /* Second list to merge */ +){ + int i1 = 0; + int i2 = 0; + i64 iRowid1 = 0; + i64 iRowid2 = 0; + i64 iOut = 0; + + Fts5Buffer out; + memset(&out, 0, sizeof(out)); + sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n); + if( p->rc ) return; + + fts5NextRowid(p1, &i1, &iRowid1); + fts5NextRowid(p2, &i2, &iRowid2); + while( i1>=0 || i2>=0 ){ + if( i1>=0 && (i2<0 || iRowid1iOut ); + fts5BufferSafeAppendVarint(&out, iRowid1 - iOut); + iOut = iRowid1; + fts5NextRowid(p1, &i1, &iRowid1); + }else{ + assert( iOut==0 || iRowid2>iOut ); + fts5BufferSafeAppendVarint(&out, iRowid2 - iOut); + iOut = iRowid2; + if( i1>=0 && iRowid1==iRowid2 ){ + fts5NextRowid(p1, &i1, &iRowid1); + } + fts5NextRowid(p2, &i2, &iRowid2); + } + } + + fts5BufferSwap(&out, p1); + fts5BufferFree(&out); +} + +/* +** Buffers p1 and p2 contain doclists. This function merges the content +** of the two doclists together and sets buffer p1 to the result before +** returning. +** +** If an error occurs, an error code is left in p->rc. If an error has +** already occurred, this function is a no-op. +*/ +static void fts5MergePrefixLists( + Fts5Index *p, /* FTS5 backend object */ + Fts5Buffer *p1, /* First list to merge */ + Fts5Buffer *p2 /* Second list to merge */ +){ + if( p2->n ){ + i64 iLastRowid = 0; + Fts5DoclistIter i1; + Fts5DoclistIter i2; + Fts5Buffer out = {0, 0, 0}; + Fts5Buffer tmp = {0, 0, 0}; + + if( sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n) ) return; + fts5DoclistIterInit(p1, &i1); + fts5DoclistIterInit(p2, &i2); + + while( 1 ){ + if( i1.iRowidrc, &tmp, i1.nPoslist + i2.nPoslist); + if( p->rc ) break; + + sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); + sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2); + assert( iPos1>=0 && iPos2>=0 ); + + if( iPos1=0 && iPos2>=0 ){ + while( 1 ){ + if( iPos1=0 ){ + if( iPos1!=iPrev ){ + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1); + } + fts5BufferSafeAppendBlob(&tmp, &a1[iOff1], i1.nPoslist-iOff1); + }else{ + assert( iPos2>=0 && iPos2!=iPrev ); + sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2); + fts5BufferSafeAppendBlob(&tmp, &a2[iOff2], i2.nPoslist-iOff2); + } + + /* WRITEPOSLISTSIZE */ + fts5BufferSafeAppendVarint(&out, tmp.n * 2); + fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); + fts5DoclistIterNext(&i1); + fts5DoclistIterNext(&i2); + if( i1.aPoslist==0 || i2.aPoslist==0 ) break; + } + } + + if( i1.aPoslist ){ + fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid); + fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist); + } + else if( i2.aPoslist ){ + fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); + fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist); + } + + fts5BufferSet(&p->rc, p1, out.n, out.p); + fts5BufferFree(&tmp); + fts5BufferFree(&out); + } +} + +static void fts5SetupPrefixIter( + Fts5Index *p, /* Index to read from */ + int bDesc, /* True for "ORDER BY rowid DESC" */ + const u8 *pToken, /* Buffer containing prefix to match */ + int nToken, /* Size of buffer pToken in bytes */ + Fts5Colset *pColset, /* Restrict matches to these columns */ + Fts5Iter **ppIter /* OUT: New iterator */ +){ + Fts5Structure *pStruct; + Fts5Buffer *aBuf; + const int nBuf = 32; + + void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*); + void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*); + if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){ + xMerge = fts5MergeRowidLists; + xAppend = fts5AppendRowid; + }else{ + xMerge = fts5MergePrefixLists; + xAppend = fts5AppendPoslist; + } + + aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf); + pStruct = fts5StructureRead(p); + + if( aBuf && pStruct ){ + const int flags = FTS5INDEX_QUERY_SCAN + | FTS5INDEX_QUERY_SKIPEMPTY + | FTS5INDEX_QUERY_NOOUTPUT; + int i; + i64 iLastRowid = 0; + Fts5Iter *p1 = 0; /* Iterator used to gather data from index */ + Fts5Data *pData; + Fts5Buffer doclist; + int bNewTerm = 1; + + memset(&doclist, 0, sizeof(doclist)); + fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1); + fts5IterSetOutputCb(&p->rc, p1); + for( /* no-op */ ; + fts5MultiIterEof(p, p1)==0; + fts5MultiIterNext2(p, p1, &bNewTerm) + ){ + Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ]; + int nTerm = pSeg->term.n; + const u8 *pTerm = pSeg->term.p; + p1->xSetOutputs(p1, pSeg); + + assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 ); + if( bNewTerm ){ + if( nTermbase.nData==0 ) continue; + + if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){ + for(i=0; p->rc==SQLITE_OK && doclist.n; i++){ + assert( ibase.iRowid-iLastRowid, p1, &doclist); + iLastRowid = p1->base.iRowid; + } + + for(i=0; irc==SQLITE_OK ){ + xMerge(p, &doclist, &aBuf[i]); + } + fts5BufferFree(&aBuf[i]); + } + fts5MultiIterFree(p1); + + pData = fts5IdxMalloc(p, sizeof(Fts5Data) + doclist.n); + if( pData ){ + pData->p = (u8*)&pData[1]; + pData->nn = pData->szLeaf = doclist.n; + memcpy(pData->p, doclist.p, doclist.n); + fts5MultiIterNew2(p, pData, bDesc, ppIter); + } + fts5BufferFree(&doclist); + } + + fts5StructureRelease(pStruct); + sqlite3_free(aBuf); +} + + +/* +** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain +** to the document with rowid iRowid. +*/ +int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){ + assert( p->rc==SQLITE_OK ); + + /* Allocate the hash table if it has not already been allocated */ + if( p->pHash==0 ){ + p->rc = sqlite3Fts5HashNew(p->pConfig, &p->pHash, &p->nPendingData); + } + + /* Flush the hash table to disk if required */ + if( iRowidiWriteRowid + || (iRowid==p->iWriteRowid && p->bDelete==0) + || (p->nPendingData > p->pConfig->nHashSize) + ){ + fts5IndexFlush(p); + } + + p->iWriteRowid = iRowid; + p->bDelete = bDelete; + return fts5IndexReturn(p); +} + +/* +** Commit data to disk. +*/ +int sqlite3Fts5IndexSync(Fts5Index *p, int bCommit){ + assert( p->rc==SQLITE_OK ); + fts5IndexFlush(p); + if( bCommit ) fts5CloseReader(p); + return fts5IndexReturn(p); +} + +/* +** Discard any data stored in the in-memory hash tables. Do not write it +** to the database. Additionally, assume that the contents of the %_data +** table may have changed on disk. So any in-memory caches of %_data +** records must be invalidated. +*/ +int sqlite3Fts5IndexRollback(Fts5Index *p){ + fts5CloseReader(p); + fts5IndexDiscardData(p); + /* assert( p->rc==SQLITE_OK ); */ + return SQLITE_OK; +} + +/* +** The %_data table is completely empty when this function is called. This +** function populates it with the initial structure objects for each index, +** and the initial version of the "averages" record (a zero-byte blob). +*/ +int sqlite3Fts5IndexReinit(Fts5Index *p){ + Fts5Structure s; + memset(&s, 0, sizeof(Fts5Structure)); + fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0); + fts5StructureWrite(p, &s); + return fts5IndexReturn(p); +} + +/* +** Open a new Fts5Index handle. If the bCreate argument is true, create +** and initialize the underlying %_data table. +** +** If successful, set *pp to point to the new object and return SQLITE_OK. +** Otherwise, set *pp to NULL and return an SQLite error code. +*/ +int sqlite3Fts5IndexOpen( + Fts5Config *pConfig, + int bCreate, + Fts5Index **pp, + char **pzErr +){ + int rc = SQLITE_OK; + Fts5Index *p; /* New object */ + + *pp = p = (Fts5Index*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Index)); + if( rc==SQLITE_OK ){ + p->pConfig = pConfig; + p->nWorkUnit = FTS5_WORK_UNIT; + p->zDataTbl = sqlite3Fts5Mprintf(&rc, "%s_data", pConfig->zName); + if( p->zDataTbl && bCreate ){ + rc = sqlite3Fts5CreateTable( + pConfig, "data", "id INTEGER PRIMARY KEY, block BLOB", 0, pzErr + ); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5CreateTable(pConfig, "idx", + "segid, term, pgno, PRIMARY KEY(segid, term)", + 1, pzErr + ); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexReinit(p); + } + } + } + + assert( rc!=SQLITE_OK || p->rc==SQLITE_OK ); + if( rc ){ + sqlite3Fts5IndexClose(p); + *pp = 0; + } + return rc; +} + +/* +** Close a handle opened by an earlier call to sqlite3Fts5IndexOpen(). +*/ +int sqlite3Fts5IndexClose(Fts5Index *p){ + int rc = SQLITE_OK; + if( p ){ + assert( p->pReader==0 ); + sqlite3_finalize(p->pWriter); + sqlite3_finalize(p->pDeleter); + sqlite3_finalize(p->pIdxWriter); + sqlite3_finalize(p->pIdxDeleter); + sqlite3_finalize(p->pIdxSelect); + sqlite3Fts5HashFree(p->pHash); + sqlite3_free(p->zDataTbl); + sqlite3_free(p); + } + return rc; +} + +/* +** Argument p points to a buffer containing utf-8 text that is n bytes in +** size. Return the number of bytes in the nChar character prefix of the +** buffer, or 0 if there are less than nChar characters in total. +*/ +int sqlite3Fts5IndexCharlenToBytelen( + const char *p, + int nByte, + int nChar +){ + int n = 0; + int i; + for(i=0; i=nByte ) return 0; /* Input contains fewer than nChar chars */ + if( (unsigned char)p[n++]>=0xc0 ){ + while( (p[n] & 0xc0)==0x80 ) n++; + } + } + return n; +} + +/* +** pIn is a UTF-8 encoded string, nIn bytes in size. Return the number of +** unicode characters in the string. +*/ +static int fts5IndexCharlen(const char *pIn, int nIn){ + int nChar = 0; + int i = 0; + while( i=0xc0 ){ + while( i delete) */ + int iPos, /* Position of token within column */ + const char *pToken, int nToken /* Token to add or remove to or from index */ +){ + int i; /* Used to iterate through indexes */ + int rc = SQLITE_OK; /* Return code */ + Fts5Config *pConfig = p->pConfig; + + assert( p->rc==SQLITE_OK ); + assert( (iCol<0)==p->bDelete ); + + /* Add the entry to the main terms index. */ + rc = sqlite3Fts5HashWrite( + p->pHash, p->iWriteRowid, iCol, iPos, FTS5_MAIN_PREFIX, pToken, nToken + ); + + for(i=0; inPrefix && rc==SQLITE_OK; i++){ + const int nChar = pConfig->aPrefix[i]; + int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar); + if( nByte ){ + rc = sqlite3Fts5HashWrite(p->pHash, + p->iWriteRowid, iCol, iPos, (char)(FTS5_MAIN_PREFIX+i+1), pToken, + nByte + ); + } + } + + return rc; +} + +/* +** Open a new iterator to iterate though all rowid that match the +** specified token or token prefix. +*/ +int sqlite3Fts5IndexQuery( + Fts5Index *p, /* FTS index to query */ + const char *pToken, int nToken, /* Token (or prefix) to query for */ + int flags, /* Mask of FTS5INDEX_QUERY_X flags */ + Fts5Colset *pColset, /* Match these columns only */ + Fts5IndexIter **ppIter /* OUT: New iterator object */ +){ + Fts5Config *pConfig = p->pConfig; + Fts5Iter *pRet = 0; + Fts5Buffer buf = {0, 0, 0}; + + /* If the QUERY_SCAN flag is set, all other flags must be clear. */ + assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN ); + + if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ + int iIdx = 0; /* Index to search */ + memcpy(&buf.p[1], pToken, nToken); + + /* Figure out which index to search and set iIdx accordingly. If this + ** is a prefix query for which there is no prefix index, set iIdx to + ** greater than pConfig->nPrefix to indicate that the query will be + ** satisfied by scanning multiple terms in the main index. + ** + ** If the QUERY_TEST_NOIDX flag was specified, then this must be a + ** prefix-query. Instead of using a prefix-index (if one exists), + ** evaluate the prefix query using the main FTS index. This is used + ** for internal sanity checking by the integrity-check in debug + ** mode only. */ +#ifdef SQLITE_DEBUG + if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){ + assert( flags & FTS5INDEX_QUERY_PREFIX ); + iIdx = 1+pConfig->nPrefix; + }else +#endif + if( flags & FTS5INDEX_QUERY_PREFIX ){ + int nChar = fts5IndexCharlen(pToken, nToken); + for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){ + if( pConfig->aPrefix[iIdx-1]==nChar ) break; + } + } + + if( iIdx<=pConfig->nPrefix ){ + /* Straight index lookup */ + Fts5Structure *pStruct = fts5StructureRead(p); + buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx); + if( pStruct ){ + fts5MultiIterNew(p, pStruct, flags | FTS5INDEX_QUERY_SKIPEMPTY, + pColset, buf.p, nToken+1, -1, 0, &pRet + ); + fts5StructureRelease(pStruct); + } + }else{ + /* Scan multiple terms in the main index */ + int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0; + buf.p[0] = FTS5_MAIN_PREFIX; + fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet); + assert( p->rc!=SQLITE_OK || pRet->pColset==0 ); + fts5IterSetOutputCb(&p->rc, pRet); + if( p->rc==SQLITE_OK ){ + Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst]; + if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg); + } + } + + if( p->rc ){ + sqlite3Fts5IterClose(&pRet->base); + pRet = 0; + fts5CloseReader(p); + } + + *ppIter = &pRet->base; + sqlite3Fts5BufferFree(&buf); + } + return fts5IndexReturn(p); +} + +/* +** Return true if the iterator passed as the only argument is at EOF. +*/ +/* +** Move to the next matching rowid. +*/ +int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; + assert( pIter->pIndex->rc==SQLITE_OK ); + fts5MultiIterNext(pIter->pIndex, pIter, 0, 0); + return fts5IndexReturn(pIter->pIndex); +} + +/* +** Move to the next matching term/rowid. Used by the fts5vocab module. +*/ +int sqlite3Fts5IterNextScan(Fts5IndexIter *pIndexIter){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; + Fts5Index *p = pIter->pIndex; + + assert( pIter->pIndex->rc==SQLITE_OK ); + + fts5MultiIterNext(p, pIter, 0, 0); + if( p->rc==SQLITE_OK ){ + Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ]; + if( pSeg->pLeaf && pSeg->term.p[0]!=FTS5_MAIN_PREFIX ){ + fts5DataRelease(pSeg->pLeaf); + pSeg->pLeaf = 0; + pIter->base.bEof = 1; + } + } + + return fts5IndexReturn(pIter->pIndex); +} + +/* +** Move to the next matching rowid that occurs at or after iMatch. The +** definition of "at or after" depends on whether this iterator iterates +** in ascending or descending rowid order. +*/ +int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; + fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch); + return fts5IndexReturn(pIter->pIndex); +} + +/* +** Return the current term. +*/ +const char *sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){ + int n; + const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n); + *pn = n-1; + return &z[1]; +} + +/* +** Close an iterator opened by an earlier call to sqlite3Fts5IndexQuery(). +*/ +void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){ + if( pIndexIter ){ + Fts5Iter *pIter = (Fts5Iter*)pIndexIter; + Fts5Index *pIndex = pIter->pIndex; + fts5MultiIterFree(pIter); + fts5CloseReader(pIndex); + } +} + +/* +** Read and decode the "averages" record from the database. +** +** Parameter anSize must point to an array of size nCol, where nCol is +** the number of user defined columns in the FTS table. +*/ +int sqlite3Fts5IndexGetAverages(Fts5Index *p, i64 *pnRow, i64 *anSize){ + int nCol = p->pConfig->nCol; + Fts5Data *pData; + + *pnRow = 0; + memset(anSize, 0, sizeof(i64) * nCol); + pData = fts5DataRead(p, FTS5_AVERAGES_ROWID); + if( p->rc==SQLITE_OK && pData->nn ){ + int i = 0; + int iCol; + i += fts5GetVarint(&pData->p[i], (u64*)pnRow); + for(iCol=0; inn && iColp[i], (u64*)&anSize[iCol]); + } + } + + fts5DataRelease(pData); + return fts5IndexReturn(p); +} + +/* +** Replace the current "averages" record with the contents of the buffer +** supplied as the second argument. +*/ +int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8 *pData, int nData){ + assert( p->rc==SQLITE_OK ); + fts5DataWrite(p, FTS5_AVERAGES_ROWID, pData, nData); + return fts5IndexReturn(p); +} + +/* +** Return the total number of blocks this module has read from the %_data +** table since it was created. +*/ +int sqlite3Fts5IndexReads(Fts5Index *p){ + return p->nRead; +} + +/* +** Set the 32-bit cookie value stored at the start of all structure +** records to the value passed as the second argument. +** +** Return SQLITE_OK if successful, or an SQLite error code if an error +** occurs. +*/ +int sqlite3Fts5IndexSetCookie(Fts5Index *p, int iNew){ + int rc; /* Return code */ + Fts5Config *pConfig = p->pConfig; /* Configuration object */ + u8 aCookie[4]; /* Binary representation of iNew */ + sqlite3_blob *pBlob = 0; + + assert( p->rc==SQLITE_OK ); + sqlite3Fts5Put32(aCookie, iNew); + + rc = sqlite3_blob_open(pConfig->db, pConfig->zDb, p->zDataTbl, + "block", FTS5_STRUCTURE_ROWID, 1, &pBlob + ); + if( rc==SQLITE_OK ){ + sqlite3_blob_write(pBlob, aCookie, 4, 0); + rc = sqlite3_blob_close(pBlob); + } + + return rc; +} + +int sqlite3Fts5IndexLoadConfig(Fts5Index *p){ + Fts5Structure *pStruct; + pStruct = fts5StructureRead(p); + fts5StructureRelease(pStruct); + return fts5IndexReturn(p); +} + + +/************************************************************************* +************************************************************************** +** Below this point is the implementation of the integrity-check +** functionality. +*/ + +/* +** Return a simple checksum value based on the arguments. +*/ +u64 sqlite3Fts5IndexEntryCksum( + i64 iRowid, + int iCol, + int iPos, + int iIdx, + const char *pTerm, + int nTerm +){ + int i; + u64 ret = iRowid; + ret += (ret<<3) + iCol; + ret += (ret<<3) + iPos; + if( iIdx>=0 ) ret += (ret<<3) + (FTS5_MAIN_PREFIX + iIdx); + for(i=0; iiLeaf ); + cksum1 += iRowid + ((i64)pgno<<32); + } + fts5DlidxIterFree(pDlidx); + pDlidx = 0; + + for(pDlidx=fts5DlidxIterInit(p, 1, iSegid, iLeaf); + fts5DlidxIterEof(p, pDlidx)==0; + fts5DlidxIterPrev(p, pDlidx) + ){ + i64 iRowid = fts5DlidxIterRowid(pDlidx); + int pgno = fts5DlidxIterPgno(pDlidx); + assert( fts5DlidxIterPgno(pDlidx)>iLeaf ); + cksum2 += iRowid + ((i64)pgno<<32); + } + fts5DlidxIterFree(pDlidx); + pDlidx = 0; + + if( p->rc==SQLITE_OK && cksum1!=cksum2 ) p->rc = FTS5_CORRUPT; +} + +static int fts5QueryCksum( + Fts5Index *p, /* Fts5 index object */ + int iIdx, + const char *z, /* Index key to query for */ + int n, /* Size of index key in bytes */ + int flags, /* Flags for Fts5IndexQuery */ + u64 *pCksum /* IN/OUT: Checksum value */ +){ + int eDetail = p->pConfig->eDetail; + u64 cksum = *pCksum; + Fts5IndexIter *pIter = 0; + int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter); + + while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIter) ){ + i64 rowid = pIter->iRowid; + + if( eDetail==FTS5_DETAIL_NONE ){ + cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n); + }else{ + Fts5PoslistReader sReader; + for(sqlite3Fts5PoslistReaderInit(pIter->pData, pIter->nData, &sReader); + sReader.bEof==0; + sqlite3Fts5PoslistReaderNext(&sReader) + ){ + int iCol = FTS5_POS2COLUMN(sReader.iPos); + int iOff = FTS5_POS2OFFSET(sReader.iPos); + cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n); + } + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IterNext(pIter); + } + } + sqlite3Fts5IterClose(pIter); + + *pCksum = cksum; + return rc; +} + + +/* +** This function is also purely an internal test. It does not contribute to +** FTS functionality, or even the integrity-check, in any way. +*/ +static void fts5TestTerm( + Fts5Index *p, + Fts5Buffer *pPrev, /* Previous term */ + const char *z, int n, /* Possibly new term to test */ + u64 expected, + u64 *pCksum +){ + int rc = p->rc; + if( pPrev->n==0 ){ + fts5BufferSet(&rc, pPrev, n, (const u8*)z); + }else + 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 */ + int iIdx = (pPrev->p[0] - FTS5_MAIN_PREFIX); + int flags = (iIdx==0 ? 0 : FTS5INDEX_QUERY_PREFIX); + u64 ck1 = 0; + u64 ck2 = 0; + + /* Check that the results returned for ASC and DESC queries are + ** the same. If not, call this corruption. */ + rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, flags, &ck1); + if( rc==SQLITE_OK ){ + int f = flags|FTS5INDEX_QUERY_DESC; + rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2); + } + if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT; + + /* If this is a prefix query, check that the results returned if the + ** the index is disabled are the same. In both ASC and DESC order. + ** + ** This check may only be performed if the hash table is empty. This + ** is because the hash table only supports a single scan query at + ** a time, and the multi-iter loop from which this function is called + ** is already performing such a scan. */ + if( p->nPendingData==0 ){ + if( iIdx>0 && rc==SQLITE_OK ){ + int f = flags|FTS5INDEX_QUERY_TEST_NOIDX; + ck2 = 0; + rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2); + if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT; + } + if( iIdx>0 && rc==SQLITE_OK ){ + int f = flags|FTS5INDEX_QUERY_TEST_NOIDX|FTS5INDEX_QUERY_DESC; + ck2 = 0; + rc = fts5QueryCksum(p, iIdx, zTerm, nTerm, f, &ck2); + if( rc==SQLITE_OK && ck1!=ck2 ) rc = FTS5_CORRUPT; + } + } + + cksum3 ^= ck1; + fts5BufferSet(&rc, pPrev, n, (const u8*)z); + + if( rc==SQLITE_OK && cksum3!=expected ){ + rc = FTS5_CORRUPT; + } + *pCksum = cksum3; + } + p->rc = rc; +} + +#else +# define fts5TestDlidxReverse(x,y,z) +# define fts5TestTerm(u,v,w,x,y,z) +#endif + +/* +** Check that: +** +** 1) All leaves of pSeg between iFirst and iLast (inclusive) exist and +** contain zero terms. +** 2) All leaves of pSeg between iNoRowid and iLast (inclusive) exist and +** contain zero rowids. +*/ +static void fts5IndexIntegrityCheckEmpty( + Fts5Index *p, + Fts5StructureSegment *pSeg, /* Segment to check internal consistency */ + int iFirst, + int iNoRowid, + int iLast +){ + int i; + + /* Now check that the iter.nEmpty leaves following the current leaf + ** (a) exist and (b) contain no terms. */ + 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) ) p->rc = FTS5_CORRUPT; + if( i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf) ) p->rc = FTS5_CORRUPT; + } + fts5DataRelease(pLeaf); + } +} + +static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){ + int iTermOff = 0; + int ii; + + Fts5Buffer buf1 = {0,0,0}; + Fts5Buffer buf2 = {0,0,0}; + + ii = pLeaf->szLeaf; + while( iinn && p->rc==SQLITE_OK ){ + int res; + int iOff; + int nIncr; + + ii += fts5GetVarint32(&pLeaf->p[ii], nIncr); + iTermOff += nIncr; + iOff = iTermOff; + + if( iOff>=pLeaf->szLeaf ){ + p->rc = FTS5_CORRUPT; + }else if( iTermOff==nIncr ){ + int nByte; + iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte); + if( (iOff+nByte)>pLeaf->szLeaf ){ + p->rc = FTS5_CORRUPT; + }else{ + fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]); + } + }else{ + int nKeep, nByte; + iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep); + iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte); + if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){ + p->rc = FTS5_CORRUPT; + }else{ + buf1.n = nKeep; + fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]); + } + + if( p->rc==SQLITE_OK ){ + res = fts5BufferCompare(&buf1, &buf2); + if( res<=0 ) p->rc = FTS5_CORRUPT; + } + } + fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p); + } + + fts5BufferFree(&buf1); + fts5BufferFree(&buf2); +} + +static void fts5IndexIntegrityCheckSegment( + Fts5Index *p, /* FTS5 backend object */ + Fts5StructureSegment *pSeg /* Segment to check internal consistency */ +){ + Fts5Config *pConfig = p->pConfig; + sqlite3_stmt *pStmt = 0; + int rc2; + int iIdxPrevLeaf = pSeg->pgnoFirst-1; + int iDlidxPrevLeaf = pSeg->pgnoLast; + + if( pSeg->pgnoFirst==0 ) return; + + fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf( + "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d", + pConfig->zDb, pConfig->zName, pSeg->iSegid + )); + + /* Iterate through the b-tree hierarchy. */ + while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + i64 iRow; /* Rowid for this leaf */ + Fts5Data *pLeaf; /* Data for this leaf */ + + int nIdxTerm = sqlite3_column_bytes(pStmt, 1); + const char *zIdxTerm = (const char*)sqlite3_column_text(pStmt, 1); + int iIdxLeaf = sqlite3_column_int(pStmt, 2); + int bIdxDlidx = sqlite3_column_int(pStmt, 3); + + /* If the leaf in question has already been trimmed from the segment, + ** ignore this b-tree entry. Otherwise, load it into memory. */ + if( iIdxLeafpgnoFirst ) continue; + iRow = FTS5_SEGMENT_ROWID(pSeg->iSegid, iIdxLeaf); + pLeaf = fts5DataRead(p, iRow); + if( pLeaf==0 ) break; + + /* Check that the leaf contains at least one term, and that it is equal + ** to or larger than the split-key in zIdxTerm. Also check that if there + ** is also a rowid pointer within the leaf page header, it points to a + ** location before the term. */ + if( pLeaf->nn<=pLeaf->szLeaf ){ + p->rc = FTS5_CORRUPT; + }else{ + int iOff; /* Offset of first term on leaf */ + int iRowidOff; /* Offset of first rowid on leaf */ + int nTerm; /* Size of term on leaf in bytes */ + int res; /* Comparison of term and split-key */ + + iOff = fts5LeafFirstTermOff(pLeaf); + iRowidOff = fts5LeafFirstRowidOff(pLeaf); + if( iRowidOff>=iOff ){ + p->rc = FTS5_CORRUPT; + }else{ + iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm); + res = memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm)); + if( res==0 ) res = nTerm - nIdxTerm; + if( res<0 ) p->rc = FTS5_CORRUPT; + } + + fts5IntegrityCheckPgidx(p, pLeaf); + } + fts5DataRelease(pLeaf); + if( p->rc ) break; + + /* Now check that the iter.nEmpty leaves following the current leaf + ** (a) exist and (b) contain no terms. */ + fts5IndexIntegrityCheckEmpty( + p, pSeg, iIdxPrevLeaf+1, iDlidxPrevLeaf+1, iIdxLeaf-1 + ); + if( p->rc ) break; + + /* If there is a doclist-index, check that it looks right. */ + if( bIdxDlidx ){ + Fts5DlidxIter *pDlidx = 0; /* For iterating through doclist index */ + int iPrevLeaf = iIdxLeaf; + int iSegid = pSeg->iSegid; + int iPg = 0; + i64 iKey; + + for(pDlidx=fts5DlidxIterInit(p, 0, iSegid, iIdxLeaf); + fts5DlidxIterEof(p, pDlidx)==0; + fts5DlidxIterNext(p, pDlidx) + ){ + + /* Check any rowid-less pages that occur before the current leaf. */ + for(iPg=iPrevLeaf+1; iPgrc = FTS5_CORRUPT; + fts5DataRelease(pLeaf); + } + } + iPrevLeaf = fts5DlidxIterPgno(pDlidx); + + /* Check that the leaf page indicated by the iterator really does + ** contain the rowid suggested by the same. */ + iKey = FTS5_SEGMENT_ROWID(iSegid, iPrevLeaf); + pLeaf = fts5DataRead(p, iKey); + if( pLeaf ){ + i64 iRowid; + int iRowidOff = fts5LeafFirstRowidOff(pLeaf); + ASSERT_SZLEAF_OK(pLeaf); + if( iRowidOff>=pLeaf->szLeaf ){ + p->rc = FTS5_CORRUPT; + }else{ + fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); + if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT; + } + fts5DataRelease(pLeaf); + } + } + + iDlidxPrevLeaf = iPg; + fts5DlidxIterFree(pDlidx); + fts5TestDlidxReverse(p, iSegid, iIdxLeaf); + }else{ + iDlidxPrevLeaf = pSeg->pgnoLast; + /* TODO: Check there is no doclist index */ + } + + iIdxPrevLeaf = iIdxLeaf; + } + + rc2 = sqlite3_finalize(pStmt); + if( p->rc==SQLITE_OK ) p->rc = rc2; + + /* Page iter.iLeaf must now be the rightmost leaf-page in the segment */ +#if 0 + if( p->rc==SQLITE_OK && iter.iLeaf!=pSeg->pgnoLast ){ + p->rc = FTS5_CORRUPT; + } +#endif +} + + +/* +** Run internal checks to ensure that the FTS index (a) is internally +** consistent and (b) contains entries for which the XOR of the checksums +** as calculated by sqlite3Fts5IndexEntryCksum() is cksum. +** +** Return SQLITE_CORRUPT if any of the internal checks fail, or if the +** checksum does not match. Return SQLITE_OK if all checks pass without +** error, or some other SQLite error code if another error (e.g. OOM) +** occurs. +*/ +int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){ + int eDetail = p->pConfig->eDetail; + u64 cksum2 = 0; /* Checksum based on contents of indexes */ + Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */ + Fts5Iter *pIter; /* Used to iterate through entire index */ + Fts5Structure *pStruct; /* Index structure */ + +#ifdef SQLITE_DEBUG + /* 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 */ +#endif + const int flags = FTS5INDEX_QUERY_NOOUTPUT; + + /* Load the FTS index structure */ + pStruct = fts5StructureRead(p); + + /* Check that the internal nodes of each segment match the leaves */ + if( pStruct ){ + int iLvl, iSeg; + for(iLvl=0; iLvlnLevel; iLvl++){ + for(iSeg=0; iSegaLevel[iLvl].nSeg; iSeg++){ + Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg]; + fts5IndexIntegrityCheckSegment(p, pSeg); + } + } + } + + /* The cksum argument passed to this function is a checksum calculated + ** based on all expected entries in the FTS index (including prefix index + ** entries). This block checks that a checksum calculated based on the + ** actual contents of FTS index is identical. + ** + ** Two versions of the same checksum are calculated. The first (stack + ** variable cksum2) based on entries extracted from the full-text index + ** while doing a linear scan of each individual index in turn. + ** + ** As each term visited by the linear scans, a separate query for the + ** same term is performed. cksum3 is calculated based on the entries + ** extracted by these queries. + */ + for(fts5MultiIterNew(p, pStruct, flags, 0, 0, 0, -1, 0, &pIter); + fts5MultiIterEof(p, pIter)==0; + fts5MultiIterNext(p, pIter, 0, 0) + ){ + int n; /* Size of term in bytes */ + i64 iPos = 0; /* Position read from poslist */ + int iOff = 0; /* Offset within poslist */ + i64 iRowid = fts5MultiIterRowid(pIter); + 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); + + if( eDetail==FTS5_DETAIL_NONE ){ + if( 0==fts5MultiIterIsEmpty(p, pIter) ){ + cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, 0, 0, -1, z, n); + } + }else{ + poslist.n = 0; + fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist); + while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){ + int iCol = FTS5_POS2COLUMN(iPos); + int iTokOff = FTS5_POS2OFFSET(iPos); + cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n); + } + } + } + fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3); + + fts5MultiIterFree(pIter); + if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT; + + fts5StructureRelease(pStruct); +#ifdef SQLITE_DEBUG + fts5BufferFree(&term); +#endif + fts5BufferFree(&poslist); + return fts5IndexReturn(p); +} + +/************************************************************************* +************************************************************************** +** Below this point is the implementation of the fts5_decode() scalar +** function only. +*/ + +/* +** Decode a segment-data rowid from the %_data table. This function is +** the opposite of macro FTS5_SEGMENT_ROWID(). +*/ +static void fts5DecodeRowid( + i64 iRowid, /* Rowid from %_data table */ + int *piSegid, /* OUT: Segment id */ + int *pbDlidx, /* OUT: Dlidx flag */ + int *piHeight, /* OUT: Height */ + int *piPgno /* OUT: Page number */ +){ + *piPgno = (int)(iRowid & (((i64)1 << FTS5_DATA_PAGE_B) - 1)); + iRowid >>= FTS5_DATA_PAGE_B; + + *piHeight = (int)(iRowid & (((i64)1 << FTS5_DATA_HEIGHT_B) - 1)); + iRowid >>= FTS5_DATA_HEIGHT_B; + + *pbDlidx = (int)(iRowid & 0x0001); + iRowid >>= FTS5_DATA_DLI_B; + + *piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1)); +} + +static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){ + int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */ + fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno); + + if( iSegid==0 ){ + if( iKey==FTS5_AVERAGES_ROWID ){ + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{averages} "); + }else{ + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{structure}"); + } + } + else{ + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "{%ssegid=%d h=%d pgno=%d}", + bDlidx ? "dlidx " : "", iSegid, iHeight, iPgno + ); + } +} + +static void fts5DebugStructure( + int *pRc, /* IN/OUT: error code */ + Fts5Buffer *pBuf, + Fts5Structure *p +){ + int iLvl, iSeg; /* Iterate through levels, segments */ + + for(iLvl=0; iLvlnLevel; iLvl++){ + Fts5StructureLevel *pLvl = &p->aLevel[iLvl]; + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, + " {lvl=%d nMerge=%d nSeg=%d", iLvl, pLvl->nMerge, pLvl->nSeg + ); + for(iSeg=0; iSegnSeg; iSeg++){ + Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}", + pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast + ); + } + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}"); + } +} + +/* +** This is part of the fts5_decode() debugging aid. +** +** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This +** function appends a human-readable representation of the same object +** to the buffer passed as the second argument. +*/ +static void fts5DecodeStructure( + int *pRc, /* IN/OUT: error code */ + Fts5Buffer *pBuf, + const u8 *pBlob, int nBlob +){ + int rc; /* Return code */ + Fts5Structure *p = 0; /* Decoded structure object */ + + rc = fts5StructureDecode(pBlob, nBlob, 0, &p); + if( rc!=SQLITE_OK ){ + *pRc = rc; + return; + } + + fts5DebugStructure(pRc, pBuf, p); + fts5StructureRelease(p); +} + +/* +** This is part of the fts5_decode() debugging aid. +** +** Arguments pBlob/nBlob contain an "averages" record. This function +** appends a human-readable representation of record to the buffer passed +** as the second argument. +*/ +static void fts5DecodeAverages( + int *pRc, /* IN/OUT: error code */ + Fts5Buffer *pBuf, + const u8 *pBlob, int nBlob +){ + int i = 0; + const char *zSpace = ""; + + while( i0 ){ + iOff = sqlite3Fts5GetVarint(a, (u64*)&iDocid); + sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid); + } + while( iOff none) */ +}; + +/* +** A single object of this type is allocated when the FTS5 module is +** registered with a database handle. It is used to store pointers to +** all registered FTS5 extensions - tokenizers and auxiliary functions. +*/ +struct Fts5Global { + fts5_api api; /* User visible part of object (see fts5.h) */ + sqlite3 *db; /* Associated database connection */ + i64 iNextId; /* Used to allocate unique cursor ids */ + Fts5Auxiliary *pAux; /* First in list of all aux. functions */ + Fts5TokenizerModule *pTok; /* First in list of all tokenizer modules */ + Fts5TokenizerModule *pDfltTok; /* Default tokenizer module */ + Fts5Cursor *pCsr; /* First in list of all open cursors */ +}; + +/* +** Each auxiliary function registered with the FTS5 module is represented +** by an object of the following type. All such objects are stored as part +** of the Fts5Global.pAux list. +*/ +struct Fts5Auxiliary { + Fts5Global *pGlobal; /* Global context for this function */ + char *zFunc; /* Function name (nul-terminated) */ + void *pUserData; /* User-data pointer */ + fts5_extension_function xFunc; /* Callback function */ + void (*xDestroy)(void*); /* Destructor function */ + Fts5Auxiliary *pNext; /* Next registered auxiliary function */ +}; + +/* +** Each tokenizer module registered with the FTS5 module is represented +** by an object of the following type. All such objects are stored as part +** of the Fts5Global.pTok list. +*/ +struct Fts5TokenizerModule { + char *zName; /* Name of tokenizer */ + void *pUserData; /* User pointer passed to xCreate() */ + fts5_tokenizer x; /* Tokenizer functions */ + void (*xDestroy)(void*); /* Destructor function */ + Fts5TokenizerModule *pNext; /* Next registered tokenizer module */ +}; + +/* +** Virtual-table object. +*/ +struct Fts5Table { + sqlite3_vtab base; /* Base class used by SQLite core */ + Fts5Config *pConfig; /* Virtual table configuration */ + Fts5Index *pIndex; /* Full-text index */ + Fts5Storage *pStorage; /* Document store */ + Fts5Global *pGlobal; /* Global (connection wide) data */ + Fts5Cursor *pSortCsr; /* Sort data from this cursor */ +#ifdef SQLITE_DEBUG + struct Fts5TransactionState ts; +#endif +}; + +struct Fts5MatchPhrase { + Fts5Buffer *pPoslist; /* Pointer to current poslist */ + int nTerm; /* Size of phrase in terms */ +}; + +/* +** pStmt: +** SELECT rowid, FROM ORDER BY +rank; +** +** aIdx[]: +** There is one entry in the aIdx[] array for each phrase in the query, +** the value of which is the offset within aPoslist[] following the last +** byte of the position list for the corresponding phrase. +*/ +struct Fts5Sorter { + sqlite3_stmt *pStmt; + i64 iRowid; /* Current rowid */ + const u8 *aPoslist; /* Position lists for current row */ + int nIdx; /* Number of entries in aIdx[] */ + int aIdx[1]; /* Offsets into aPoslist for current row */ +}; + + +/* +** Virtual-table cursor object. +** +** iSpecial: +** If this is a 'special' query (refer to function fts5SpecialMatch()), +** then this variable contains the result of the query. +** +** iFirstRowid, iLastRowid: +** These variables are only used for FTS5_PLAN_MATCH cursors. Assuming the +** cursor iterates in ascending order of rowids, iFirstRowid is the lower +** limit of rowids to return, and iLastRowid the upper. In other words, the +** WHERE clause in the user's query might have been: +** +** MATCH AND rowid BETWEEN $iFirstRowid AND $iLastRowid +** +** If the cursor iterates in descending order of rowid, iFirstRowid +** is the upper limit (i.e. the "first" rowid visited) and iLastRowid +** the lower. +*/ +struct Fts5Cursor { + sqlite3_vtab_cursor base; /* Base class used by SQLite core */ + Fts5Cursor *pNext; /* Next cursor in Fts5Cursor.pCsr list */ + int *aColumnSize; /* Values for xColumnSize() */ + i64 iCsrId; /* Cursor id */ + + /* Zero from this point onwards on cursor reset */ + int ePlan; /* FTS5_PLAN_XXX value */ + int bDesc; /* True for "ORDER BY rowid DESC" queries */ + i64 iFirstRowid; /* Return no rowids earlier than this */ + i64 iLastRowid; /* Return no rowids later than this */ + sqlite3_stmt *pStmt; /* Statement used to read %_content */ + Fts5Expr *pExpr; /* Expression for MATCH queries */ + Fts5Sorter *pSorter; /* Sorter for "ORDER BY rank" queries */ + int csrflags; /* Mask of cursor flags (see below) */ + i64 iSpecial; /* Result of special query */ + + /* "rank" function. Populated on demand from vtab.xColumn(). */ + char *zRank; /* Custom rank function */ + char *zRankArgs; /* Custom rank function args */ + Fts5Auxiliary *pRank; /* Rank callback (or NULL) */ + int nRankArg; /* Number of trailing arguments for rank() */ + sqlite3_value **apRankArg; /* Array of trailing arguments */ + sqlite3_stmt *pRankArgStmt; /* Origin of objects in apRankArg[] */ + + /* Auxiliary data storage */ + Fts5Auxiliary *pAux; /* Currently executing extension function */ + Fts5Auxdata *pAuxdata; /* First in linked list of saved aux-data */ + + /* Cache used by auxiliary functions xInst() and xInstCount() */ + Fts5PoslistReader *aInstIter; /* One for each phrase */ + int nInstAlloc; /* Size of aInst[] array (entries / 3) */ + int nInstCount; /* Number of phrase instances */ + int *aInst; /* 3 integers per phrase instance */ +}; + +/* +** Bits that make up the "idxNum" parameter passed indirectly by +** xBestIndex() to xFilter(). +*/ +#define FTS5_BI_MATCH 0x0001 /* MATCH ? */ +#define FTS5_BI_RANK 0x0002 /* rank MATCH ? */ +#define FTS5_BI_ROWID_EQ 0x0004 /* rowid == ? */ +#define FTS5_BI_ROWID_LE 0x0008 /* rowid <= ? */ +#define FTS5_BI_ROWID_GE 0x0010 /* rowid >= ? */ + +#define FTS5_BI_ORDER_RANK 0x0020 +#define FTS5_BI_ORDER_ROWID 0x0040 +#define FTS5_BI_ORDER_DESC 0x0080 + +/* +** Values for Fts5Cursor.csrflags +*/ +#define FTS5CSR_EOF 0x01 +#define FTS5CSR_REQUIRE_CONTENT 0x02 +#define FTS5CSR_REQUIRE_DOCSIZE 0x04 +#define FTS5CSR_REQUIRE_INST 0x08 +#define FTS5CSR_FREE_ZRANK 0x10 +#define FTS5CSR_REQUIRE_RESEEK 0x20 +#define FTS5CSR_REQUIRE_POSLIST 0x40 + +#define BitFlagAllTest(x,y) (((x) & (y))==(y)) +#define BitFlagTest(x,y) (((x) & (y))!=0) + + +/* +** Macros to Set(), Clear() and Test() cursor flags. +*/ +#define CsrFlagSet(pCsr, flag) ((pCsr)->csrflags |= (flag)) +#define CsrFlagClear(pCsr, flag) ((pCsr)->csrflags &= ~(flag)) +#define CsrFlagTest(pCsr, flag) ((pCsr)->csrflags & (flag)) + +struct Fts5Auxdata { + Fts5Auxiliary *pAux; /* Extension to which this belongs */ + void *pPtr; /* Pointer value */ + void(*xDelete)(void*); /* Destructor */ + Fts5Auxdata *pNext; /* Next object in linked list */ +}; + +#ifdef SQLITE_DEBUG +#define FTS5_BEGIN 1 +#define FTS5_SYNC 2 +#define FTS5_COMMIT 3 +#define FTS5_ROLLBACK 4 +#define FTS5_SAVEPOINT 5 +#define FTS5_RELEASE 6 +#define FTS5_ROLLBACKTO 7 +static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){ + switch( op ){ + case FTS5_BEGIN: + assert( p->ts.eState==0 ); + p->ts.eState = 1; + p->ts.iSavepoint = -1; + break; + + case FTS5_SYNC: + assert( p->ts.eState==1 ); + p->ts.eState = 2; + break; + + case FTS5_COMMIT: + assert( p->ts.eState==2 ); + p->ts.eState = 0; + break; + + case FTS5_ROLLBACK: + assert( p->ts.eState==1 || p->ts.eState==2 || p->ts.eState==0 ); + p->ts.eState = 0; + break; + + case FTS5_SAVEPOINT: + assert( p->ts.eState==1 ); + assert( iSavepoint>=0 ); + assert( iSavepoint>p->ts.iSavepoint ); + p->ts.iSavepoint = iSavepoint; + break; + + case FTS5_RELEASE: + assert( p->ts.eState==1 ); + assert( iSavepoint>=0 ); + assert( iSavepoint<=p->ts.iSavepoint ); + p->ts.iSavepoint = iSavepoint-1; + break; + + case FTS5_ROLLBACKTO: + assert( p->ts.eState==1 ); + assert( iSavepoint>=0 ); + assert( iSavepoint<=p->ts.iSavepoint ); + p->ts.iSavepoint = iSavepoint; + break; + } +} +#else +# define fts5CheckTransactionState(x,y,z) +#endif + +/* +** Return true if pTab is a contentless table. +*/ +static int fts5IsContentless(Fts5Table *pTab){ + return pTab->pConfig->eContent==FTS5_CONTENT_NONE; +} + +/* +** Delete a virtual table handle allocated by fts5InitVtab(). +*/ +static void fts5FreeVtab(Fts5Table *pTab){ + if( pTab ){ + sqlite3Fts5IndexClose(pTab->pIndex); + sqlite3Fts5StorageClose(pTab->pStorage); + sqlite3Fts5ConfigFree(pTab->pConfig); + sqlite3_free(pTab); + } +} + +/* +** The xDisconnect() virtual table method. +*/ +static int fts5DisconnectMethod(sqlite3_vtab *pVtab){ + fts5FreeVtab((Fts5Table*)pVtab); + return SQLITE_OK; +} + +/* +** The xDestroy() virtual table method. +*/ +static int fts5DestroyMethod(sqlite3_vtab *pVtab){ + Fts5Table *pTab = (Fts5Table*)pVtab; + int rc = sqlite3Fts5DropAll(pTab->pConfig); + if( rc==SQLITE_OK ){ + fts5FreeVtab((Fts5Table*)pVtab); + } + return rc; +} + +/* +** This function is the implementation of both the xConnect and xCreate +** methods of the FTS3 virtual table. +** +** The argv[] array contains the following: +** +** argv[0] -> module name ("fts5") +** argv[1] -> database name +** argv[2] -> table name +** argv[...] -> "column name" and other module argument fields. +*/ +static int fts5InitVtab( + int bCreate, /* True for xCreate, false for xConnect */ + sqlite3 *db, /* The SQLite database connection */ + void *pAux, /* Hash table containing tokenizers */ + int argc, /* Number of elements in argv array */ + const char * const *argv, /* xCreate/xConnect argument array */ + sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ + char **pzErr /* Write any error message here */ +){ + Fts5Global *pGlobal = (Fts5Global*)pAux; + const char **azConfig = (const char**)argv; + int rc = SQLITE_OK; /* Return code */ + Fts5Config *pConfig = 0; /* Results of parsing argc/argv */ + Fts5Table *pTab = 0; /* New virtual table object */ + + /* Allocate the new vtab object and parse the configuration */ + pTab = (Fts5Table*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Table)); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5ConfigParse(pGlobal, db, argc, azConfig, &pConfig, pzErr); + assert( (rc==SQLITE_OK && *pzErr==0) || pConfig==0 ); + } + if( rc==SQLITE_OK ){ + pTab->pConfig = pConfig; + pTab->pGlobal = pGlobal; + } + + /* Open the index sub-system */ + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexOpen(pConfig, bCreate, &pTab->pIndex, pzErr); + } + + /* Open the storage sub-system */ + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageOpen( + pConfig, pTab->pIndex, bCreate, &pTab->pStorage, pzErr + ); + } + + /* Call sqlite3_declare_vtab() */ + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5ConfigDeclareVtab(pConfig); + } + + /* Load the initial configuration */ + if( rc==SQLITE_OK ){ + assert( pConfig->pzErrmsg==0 ); + pConfig->pzErrmsg = pzErr; + rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex); + sqlite3Fts5IndexRollback(pTab->pIndex); + pConfig->pzErrmsg = 0; + } + + if( rc!=SQLITE_OK ){ + fts5FreeVtab(pTab); + pTab = 0; + }else if( bCreate ){ + fts5CheckTransactionState(pTab, FTS5_BEGIN, 0); + } + *ppVTab = (sqlite3_vtab*)pTab; + return rc; +} + +/* +** The xConnect() and xCreate() methods for the virtual table. All the +** work is done in function fts5InitVtab(). +*/ +static int fts5ConnectMethod( + sqlite3 *db, /* Database connection */ + void *pAux, /* Pointer to tokenizer hash table */ + int argc, /* Number of elements in argv array */ + const char * const *argv, /* xCreate/xConnect argument array */ + sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ + char **pzErr /* OUT: sqlite3_malloc'd error message */ +){ + return fts5InitVtab(0, db, pAux, argc, argv, ppVtab, pzErr); +} +static int fts5CreateMethod( + sqlite3 *db, /* Database connection */ + void *pAux, /* Pointer to tokenizer hash table */ + int argc, /* Number of elements in argv array */ + const char * const *argv, /* xCreate/xConnect argument array */ + sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ + char **pzErr /* OUT: sqlite3_malloc'd error message */ +){ + return fts5InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr); +} + +/* +** The different query plans. +*/ +#define FTS5_PLAN_MATCH 1 /* ( MATCH ?) */ +#define FTS5_PLAN_SOURCE 2 /* A source cursor for SORTED_MATCH */ +#define FTS5_PLAN_SPECIAL 3 /* An internal query */ +#define FTS5_PLAN_SORTED_MATCH 4 /* ( MATCH ? ORDER BY rank) */ +#define FTS5_PLAN_SCAN 5 /* No usable constraint */ +#define FTS5_PLAN_ROWID 6 /* (rowid = ?) */ + +/* +** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this +** extension is currently being used by a version of SQLite too old to +** support index-info flags. In that case this function is a no-op. +*/ +static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){ +#if SQLITE_VERSION_NUMBER>=3008012 +#ifndef SQLITE_CORE + if( sqlite3_libversion_number()>=3008012 ) +#endif + { + pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE; + } +#endif +} + +/* +** Implementation of the xBestIndex method for FTS5 tables. Within the +** WHERE constraint, it searches for the following: +** +** 1. A MATCH constraint against the special column. +** 2. A MATCH constraint against the "rank" column. +** 3. An == constraint against the rowid column. +** 4. A < or <= constraint against the rowid column. +** 5. A > or >= constraint against the rowid column. +** +** Within the ORDER BY, either: +** +** 5. ORDER BY rank [ASC|DESC] +** 6. ORDER BY rowid [ASC|DESC] +** +** Costs are assigned as follows: +** +** a) If an unusable MATCH operator is present in the WHERE clause, the +** cost is unconditionally set to 1e50 (a really big number). +** +** a) If a MATCH operator is present, the cost depends on the other +** constraints also present. As follows: +** +** * No other constraints: cost=1000.0 +** * One rowid range constraint: cost=750.0 +** * Both rowid range constraints: cost=500.0 +** * An == rowid constraint: cost=100.0 +** +** b) Otherwise, if there is no MATCH: +** +** * No other constraints: cost=1000000.0 +** * One rowid range constraint: cost=750000.0 +** * Both rowid range constraints: cost=250000.0 +** * An == rowid constraint: cost=10.0 +** +** Costs are not modified by the ORDER BY clause. +*/ +static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ + Fts5Table *pTab = (Fts5Table*)pVTab; + Fts5Config *pConfig = pTab->pConfig; + int idxFlags = 0; /* Parameter passed through to xFilter() */ + int bHasMatch; + int iNext; + int i; + + struct Constraint { + int op; /* Mask against sqlite3_index_constraint.op */ + int fts5op; /* FTS5 mask for idxFlags */ + int iCol; /* 0==rowid, 1==tbl, 2==rank */ + int omit; /* True to omit this if found */ + int iConsIndex; /* Index in pInfo->aConstraint[] */ + } aConstraint[] = { + {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, + FTS5_BI_MATCH, 1, 1, -1}, + {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, + FTS5_BI_RANK, 2, 1, -1}, + {SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1}, + {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE, + FTS5_BI_ROWID_LE, 0, 0, -1}, + {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE, + FTS5_BI_ROWID_GE, 0, 0, -1}, + }; + + int aColMap[3]; + aColMap[0] = -1; + aColMap[1] = pConfig->nCol; + aColMap[2] = pConfig->nCol+1; + + /* Set idxFlags flags for all WHERE clause terms that will be used. */ + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; + int j; + for(j=0; jiColumn==aColMap[pC->iCol] && p->op & pC->op ){ + if( p->usable ){ + pC->iConsIndex = i; + idxFlags |= pC->fts5op; + }else if( j==0 ){ + /* As there exists an unusable MATCH constraint this is an + ** unusable plan. Set a prohibitively high cost. */ + pInfo->estimatedCost = 1e50; + return SQLITE_OK; + } + } + } + } + + /* Set idxFlags flags for the ORDER BY clause */ + if( pInfo->nOrderBy==1 ){ + int iSort = pInfo->aOrderBy[0].iColumn; + if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){ + idxFlags |= FTS5_BI_ORDER_RANK; + }else if( iSort==-1 ){ + idxFlags |= FTS5_BI_ORDER_ROWID; + } + if( BitFlagTest(idxFlags, FTS5_BI_ORDER_RANK|FTS5_BI_ORDER_ROWID) ){ + pInfo->orderByConsumed = 1; + if( pInfo->aOrderBy[0].desc ){ + idxFlags |= FTS5_BI_ORDER_DESC; + } + } + } + + /* Calculate the estimated cost based on the flags set in idxFlags. */ + bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH); + if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){ + pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0; + if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo); + }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ + pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0; + }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ + pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0; + }else{ + pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; + } + + /* Assign argvIndex values to each constraint in use. */ + iNext = 1; + for(i=0; iiConsIndex>=0 ){ + pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; + pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; + } + } + + pInfo->idxNum = idxFlags; + return SQLITE_OK; +} + +/* +** Implementation of xOpen method. +*/ +static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ + Fts5Table *pTab = (Fts5Table*)pVTab; + Fts5Config *pConfig = pTab->pConfig; + Fts5Cursor *pCsr; /* New cursor object */ + int nByte; /* Bytes of space to allocate */ + int rc = SQLITE_OK; /* Return code */ + + nByte = sizeof(Fts5Cursor) + pConfig->nCol * sizeof(int); + pCsr = (Fts5Cursor*)sqlite3_malloc(nByte); + if( pCsr ){ + Fts5Global *pGlobal = pTab->pGlobal; + memset(pCsr, 0, nByte); + pCsr->aColumnSize = (int*)&pCsr[1]; + pCsr->pNext = pGlobal->pCsr; + pGlobal->pCsr = pCsr; + pCsr->iCsrId = ++pGlobal->iNextId; + }else{ + rc = SQLITE_NOMEM; + } + *ppCsr = (sqlite3_vtab_cursor*)pCsr; + return rc; +} + +static int fts5StmtType(Fts5Cursor *pCsr){ + if( pCsr->ePlan==FTS5_PLAN_SCAN ){ + return (pCsr->bDesc) ? FTS5_STMT_SCAN_DESC : FTS5_STMT_SCAN_ASC; + } + return FTS5_STMT_LOOKUP; +} + +/* +** This function is called after the cursor passed as the only argument +** is moved to point at a different row. It clears all cached data +** specific to the previous row stored by the cursor object. +*/ +static void fts5CsrNewrow(Fts5Cursor *pCsr){ + CsrFlagSet(pCsr, + FTS5CSR_REQUIRE_CONTENT + | FTS5CSR_REQUIRE_DOCSIZE + | FTS5CSR_REQUIRE_INST + | FTS5CSR_REQUIRE_POSLIST + ); +} + +static void fts5FreeCursorComponents(Fts5Cursor *pCsr){ + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + Fts5Auxdata *pData; + Fts5Auxdata *pNext; + + sqlite3_free(pCsr->aInstIter); + sqlite3_free(pCsr->aInst); + if( pCsr->pStmt ){ + int eStmt = fts5StmtType(pCsr); + sqlite3Fts5StorageStmtRelease(pTab->pStorage, eStmt, pCsr->pStmt); + } + if( pCsr->pSorter ){ + Fts5Sorter *pSorter = pCsr->pSorter; + sqlite3_finalize(pSorter->pStmt); + sqlite3_free(pSorter); + } + + if( pCsr->ePlan!=FTS5_PLAN_SOURCE ){ + sqlite3Fts5ExprFree(pCsr->pExpr); + } + + for(pData=pCsr->pAuxdata; pData; pData=pNext){ + pNext = pData->pNext; + if( pData->xDelete ) pData->xDelete(pData->pPtr); + sqlite3_free(pData); + } + + sqlite3_finalize(pCsr->pRankArgStmt); + sqlite3_free(pCsr->apRankArg); + + if( CsrFlagTest(pCsr, FTS5CSR_FREE_ZRANK) ){ + sqlite3_free(pCsr->zRank); + sqlite3_free(pCsr->zRankArgs); + } + + memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr)); +} + + +/* +** Close the cursor. For additional information see the documentation +** on the xClose method of the virtual table interface. +*/ +static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){ + if( pCursor ){ + Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); + Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; + Fts5Cursor **pp; + + fts5FreeCursorComponents(pCsr); + /* Remove the cursor from the Fts5Global.pCsr list */ + for(pp=&pTab->pGlobal->pCsr; (*pp)!=pCsr; pp=&(*pp)->pNext); + *pp = pCsr->pNext; + + sqlite3_free(pCsr); + } + return SQLITE_OK; +} + +static int fts5SorterNext(Fts5Cursor *pCsr){ + Fts5Sorter *pSorter = pCsr->pSorter; + int rc; + + rc = sqlite3_step(pSorter->pStmt); + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + CsrFlagSet(pCsr, FTS5CSR_EOF); + }else if( rc==SQLITE_ROW ){ + const u8 *a; + const u8 *aBlob; + int nBlob; + int i; + int iOff = 0; + rc = SQLITE_OK; + + pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0); + nBlob = sqlite3_column_bytes(pSorter->pStmt, 1); + aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1); + + /* nBlob==0 in detail=none mode. */ + if( nBlob>0 ){ + for(i=0; i<(pSorter->nIdx-1); i++){ + int iVal; + a += fts5GetVarint32(a, iVal); + iOff += iVal; + pSorter->aIdx[i] = iOff; + } + pSorter->aIdx[i] = &aBlob[nBlob] - a; + pSorter->aPoslist = a; + } + + fts5CsrNewrow(pCsr); + } + + return rc; +} + + +/* +** Set the FTS5CSR_REQUIRE_RESEEK flag on all FTS5_PLAN_MATCH cursors +** open on table pTab. +*/ +static void fts5TripCursors(Fts5Table *pTab){ + Fts5Cursor *pCsr; + for(pCsr=pTab->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){ + if( pCsr->ePlan==FTS5_PLAN_MATCH + && pCsr->base.pVtab==(sqlite3_vtab*)pTab + ){ + CsrFlagSet(pCsr, FTS5CSR_REQUIRE_RESEEK); + } + } +} + +/* +** If the REQUIRE_RESEEK flag is set on the cursor passed as the first +** argument, close and reopen all Fts5IndexIter iterators that the cursor +** is using. Then attempt to move the cursor to a rowid equal to or laster +** (in the cursors sort order - ASC or DESC) than the current rowid. +** +** If the new rowid is not equal to the old, set output parameter *pbSkip +** to 1 before returning. Otherwise, leave it unchanged. +** +** Return SQLITE_OK if successful or if no reseek was required, or an +** error code if an error occurred. +*/ +static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){ + int rc = SQLITE_OK; + assert( *pbSkip==0 ); + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_RESEEK) ){ + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + int bDesc = pCsr->bDesc; + i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); + + rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, iRowid, bDesc); + if( rc==SQLITE_OK && iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){ + *pbSkip = 1; + } + + CsrFlagClear(pCsr, FTS5CSR_REQUIRE_RESEEK); + fts5CsrNewrow(pCsr); + if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ + CsrFlagSet(pCsr, FTS5CSR_EOF); + *pbSkip = 1; + } + } + return rc; +} + + +/* +** Advance the cursor to the next row in the table that matches the +** search criteria. +** +** Return SQLITE_OK if nothing goes wrong. SQLITE_OK is returned +** even if we reach end-of-file. The fts5EofMethod() will be called +** subsequently to determine whether or not an EOF was hit. +*/ +static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; + int rc; + + assert( (pCsr->ePlan<3)== + (pCsr->ePlan==FTS5_PLAN_MATCH || pCsr->ePlan==FTS5_PLAN_SOURCE) + ); + assert( !CsrFlagTest(pCsr, FTS5CSR_EOF) ); + + if( pCsr->ePlan<3 ){ + int bSkip = 0; + if( (rc = fts5CursorReseek(pCsr, &bSkip)) || bSkip ) return rc; + rc = sqlite3Fts5ExprNext(pCsr->pExpr, pCsr->iLastRowid); + CsrFlagSet(pCsr, sqlite3Fts5ExprEof(pCsr->pExpr)); + fts5CsrNewrow(pCsr); + }else{ + switch( pCsr->ePlan ){ + case FTS5_PLAN_SPECIAL: { + CsrFlagSet(pCsr, FTS5CSR_EOF); + rc = SQLITE_OK; + break; + } + + case FTS5_PLAN_SORTED_MATCH: { + rc = fts5SorterNext(pCsr); + break; + } + + default: + rc = sqlite3_step(pCsr->pStmt); + if( rc!=SQLITE_ROW ){ + CsrFlagSet(pCsr, FTS5CSR_EOF); + rc = sqlite3_reset(pCsr->pStmt); + }else{ + rc = SQLITE_OK; + } + break; + } + } + + return rc; +} + + +static int fts5PrepareStatement( + sqlite3_stmt **ppStmt, + Fts5Config *pConfig, + const char *zFmt, + ... +){ + sqlite3_stmt *pRet = 0; + int rc; + char *zSql; + va_list ap; + + va_start(ap, zFmt); + zSql = sqlite3_vmprintf(zFmt, ap); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0); + if( rc!=SQLITE_OK ){ + *pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db)); + } + sqlite3_free(zSql); + } + + va_end(ap); + *ppStmt = pRet; + return rc; +} + +static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ + Fts5Config *pConfig = pTab->pConfig; + Fts5Sorter *pSorter; + int nPhrase; + int nByte; + int rc; + const char *zRank = pCsr->zRank; + const char *zRankArgs = pCsr->zRankArgs; + + nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); + nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1); + pSorter = (Fts5Sorter*)sqlite3_malloc(nByte); + if( pSorter==0 ) return SQLITE_NOMEM; + memset(pSorter, 0, nByte); + pSorter->nIdx = nPhrase; + + /* TODO: It would be better to have some system for reusing statement + ** handles here, rather than preparing a new one for each query. But that + ** is not possible as SQLite reference counts the virtual table objects. + ** And since the statement required here reads from this very virtual + ** table, saving it creates a circular reference. + ** + ** If SQLite a built-in statement cache, this wouldn't be a problem. */ + rc = fts5PrepareStatement(&pSorter->pStmt, pConfig, + "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s", + pConfig->zDb, pConfig->zName, zRank, pConfig->zName, + (zRankArgs ? ", " : ""), + (zRankArgs ? zRankArgs : ""), + bDesc ? "DESC" : "ASC" + ); + + pCsr->pSorter = pSorter; + if( rc==SQLITE_OK ){ + assert( pTab->pSortCsr==0 ); + pTab->pSortCsr = pCsr; + rc = fts5SorterNext(pCsr); + pTab->pSortCsr = 0; + } + + if( rc!=SQLITE_OK ){ + sqlite3_finalize(pSorter->pStmt); + sqlite3_free(pSorter); + pCsr->pSorter = 0; + } + + return rc; +} + +static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ + int rc; + Fts5Expr *pExpr = pCsr->pExpr; + rc = sqlite3Fts5ExprFirst(pExpr, pTab->pIndex, pCsr->iFirstRowid, bDesc); + if( sqlite3Fts5ExprEof(pExpr) ){ + CsrFlagSet(pCsr, FTS5CSR_EOF); + } + fts5CsrNewrow(pCsr); + return rc; +} + +/* +** Process a "special" query. A special query is identified as one with a +** MATCH expression that begins with a '*' character. The remainder of +** the text passed to the MATCH operator are used as the special query +** parameters. +*/ +static int fts5SpecialMatch( + Fts5Table *pTab, + Fts5Cursor *pCsr, + const char *zQuery +){ + int rc = SQLITE_OK; /* Return code */ + const char *z = zQuery; /* Special query text */ + int n; /* Number of bytes in text at z */ + + while( z[0]==' ' ) z++; + for(n=0; z[n] && z[n]!=' '; n++); + + assert( pTab->base.zErrMsg==0 ); + pCsr->ePlan = FTS5_PLAN_SPECIAL; + + if( 0==sqlite3_strnicmp("reads", z, n) ){ + pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->pIndex); + } + else if( 0==sqlite3_strnicmp("id", z, n) ){ + pCsr->iSpecial = pCsr->iCsrId; + } + else{ + /* An unrecognized directive. Return an error message. */ + pTab->base.zErrMsg = sqlite3_mprintf("unknown special query: %.*s", n, z); + rc = SQLITE_ERROR; + } + + return rc; +} + +/* +** Search for an auxiliary function named zName that can be used with table +** pTab. If one is found, return a pointer to the corresponding Fts5Auxiliary +** structure. Otherwise, if no such function exists, return NULL. +*/ +static Fts5Auxiliary *fts5FindAuxiliary(Fts5Table *pTab, const char *zName){ + Fts5Auxiliary *pAux; + + for(pAux=pTab->pGlobal->pAux; pAux; pAux=pAux->pNext){ + if( sqlite3_stricmp(zName, pAux->zFunc)==0 ) return pAux; + } + + /* No function of the specified name was found. Return 0. */ + return 0; +} + + +static int fts5FindRankFunction(Fts5Cursor *pCsr){ + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + Fts5Config *pConfig = pTab->pConfig; + int rc = SQLITE_OK; + Fts5Auxiliary *pAux = 0; + const char *zRank = pCsr->zRank; + const char *zRankArgs = pCsr->zRankArgs; + + if( zRankArgs ){ + char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs); + if( zSql ){ + sqlite3_stmt *pStmt = 0; + rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 ); + if( rc==SQLITE_OK ){ + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + int nByte; + pCsr->nRankArg = sqlite3_column_count(pStmt); + nByte = sizeof(sqlite3_value*)*pCsr->nRankArg; + pCsr->apRankArg = (sqlite3_value**)sqlite3Fts5MallocZero(&rc, nByte); + if( rc==SQLITE_OK ){ + int i; + for(i=0; inRankArg; i++){ + pCsr->apRankArg[i] = sqlite3_column_value(pStmt, i); + } + } + pCsr->pRankArgStmt = pStmt; + }else{ + rc = sqlite3_finalize(pStmt); + assert( rc!=SQLITE_OK ); + } + } + } + } + + if( rc==SQLITE_OK ){ + pAux = fts5FindAuxiliary(pTab, zRank); + if( pAux==0 ){ + assert( pTab->base.zErrMsg==0 ); + pTab->base.zErrMsg = sqlite3_mprintf("no such function: %s", zRank); + rc = SQLITE_ERROR; + } + } + + pCsr->pRank = pAux; + return rc; +} + + +static int fts5CursorParseRank( + Fts5Config *pConfig, + Fts5Cursor *pCsr, + sqlite3_value *pRank +){ + int rc = SQLITE_OK; + if( pRank ){ + const char *z = (const char*)sqlite3_value_text(pRank); + char *zRank = 0; + char *zRankArgs = 0; + + if( z==0 ){ + if( sqlite3_value_type(pRank)==SQLITE_NULL ) rc = SQLITE_ERROR; + }else{ + rc = sqlite3Fts5ConfigParseRank(z, &zRank, &zRankArgs); + } + if( rc==SQLITE_OK ){ + pCsr->zRank = zRank; + pCsr->zRankArgs = zRankArgs; + CsrFlagSet(pCsr, FTS5CSR_FREE_ZRANK); + }else if( rc==SQLITE_ERROR ){ + pCsr->base.pVtab->zErrMsg = sqlite3_mprintf( + "parse error in rank function: %s", z + ); + } + }else{ + if( pConfig->zRank ){ + pCsr->zRank = (char*)pConfig->zRank; + pCsr->zRankArgs = (char*)pConfig->zRankArgs; + }else{ + pCsr->zRank = (char*)FTS5_DEFAULT_RANK; + pCsr->zRankArgs = 0; + } + } + return rc; +} + +static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){ + if( pVal ){ + int eType = sqlite3_value_numeric_type(pVal); + if( eType==SQLITE_INTEGER ){ + return sqlite3_value_int64(pVal); + } + } + return iDefault; +} + +/* +** This is the xFilter interface for the virtual table. See +** the virtual table xFilter method documentation for additional +** information. +** +** There are three possible query strategies: +** +** 1. Full-text search using a MATCH operator. +** 2. A by-rowid lookup. +** 3. A full-table scan. +*/ +static int fts5FilterMethod( + sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ + int idxNum, /* Strategy index */ + const char *zUnused, /* Unused */ + int nVal, /* Number of elements in apVal */ + sqlite3_value **apVal /* Arguments for the indexing scheme */ +){ + Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); + Fts5Config *pConfig = pTab->pConfig; + Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; + int rc = SQLITE_OK; /* Error code */ + int iVal = 0; /* Counter for apVal[] */ + int bDesc; /* True if ORDER BY [rank|rowid] DESC */ + int bOrderByRank; /* True if ORDER BY rank */ + sqlite3_value *pMatch = 0; /* MATCH ? expression (or NULL) */ + sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */ + sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */ + sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */ + sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */ + char **pzErrmsg = pConfig->pzErrmsg; + + UNUSED_PARAM(zUnused); + UNUSED_PARAM(nVal); + + if( pCsr->ePlan ){ + fts5FreeCursorComponents(pCsr); + memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr)); + } + + assert( pCsr->pStmt==0 ); + assert( pCsr->pExpr==0 ); + assert( pCsr->csrflags==0 ); + assert( pCsr->pRank==0 ); + assert( pCsr->zRank==0 ); + assert( pCsr->zRankArgs==0 ); + + assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg ); + pConfig->pzErrmsg = &pTab->base.zErrMsg; + + /* Decode the arguments passed through to this function. + ** + ** Note: The following set of if(...) statements must be in the same + ** order as the corresponding entries in the struct at the top of + ** fts5BestIndexMethod(). */ + if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++]; + if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++]; + if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++]; + if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++]; + if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++]; + assert( iVal==nVal ); + bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0); + pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0); + + /* Set the cursor upper and lower rowid limits. Only some strategies + ** actually use them. This is ok, as the xBestIndex() method leaves the + ** sqlite3_index_constraint.omit flag clear for range constraints + ** on the rowid field. */ + if( pRowidEq ){ + pRowidLe = pRowidGe = pRowidEq; + } + if( bDesc ){ + pCsr->iFirstRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64); + pCsr->iLastRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64); + }else{ + pCsr->iLastRowid = fts5GetRowidLimit(pRowidLe, LARGEST_INT64); + pCsr->iFirstRowid = fts5GetRowidLimit(pRowidGe, SMALLEST_INT64); + } + + if( pTab->pSortCsr ){ + /* If pSortCsr is non-NULL, then this call is being made as part of + ** processing for a "... MATCH ORDER BY rank" query (ePlan is + ** set to FTS5_PLAN_SORTED_MATCH). pSortCsr is the cursor that will + ** return results to the user for this query. The current cursor + ** (pCursor) is used to execute the query issued by function + ** fts5CursorFirstSorted() above. */ + assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 ); + assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 ); + assert( pCsr->iLastRowid==LARGEST_INT64 ); + assert( pCsr->iFirstRowid==SMALLEST_INT64 ); + pCsr->ePlan = FTS5_PLAN_SOURCE; + pCsr->pExpr = pTab->pSortCsr->pExpr; + rc = fts5CursorFirst(pTab, pCsr, bDesc); + sqlite3Fts5ExprClearEof(pCsr->pExpr); + }else if( pMatch ){ + const char *zExpr = (const char*)sqlite3_value_text(apVal[0]); + if( zExpr==0 ) zExpr = ""; + + rc = fts5CursorParseRank(pConfig, pCsr, pRank); + if( rc==SQLITE_OK ){ + if( zExpr[0]=='*' ){ + /* The user has issued a query of the form "MATCH '*...'". This + ** indicates that the MATCH expression is not a full text query, + ** but a request for an internal parameter. */ + rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]); + }else{ + char **pzErr = &pTab->base.zErrMsg; + rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pCsr->pExpr, pzErr); + if( rc==SQLITE_OK ){ + if( bOrderByRank ){ + pCsr->ePlan = FTS5_PLAN_SORTED_MATCH; + rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); + }else{ + pCsr->ePlan = FTS5_PLAN_MATCH; + rc = fts5CursorFirst(pTab, pCsr, bDesc); + } + } + } + } + }else if( pConfig->zContent==0 ){ + *pConfig->pzErrmsg = sqlite3_mprintf( + "%s: table does not support scanning", pConfig->zName + ); + rc = SQLITE_ERROR; + }else{ + /* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup + ** by rowid (ePlan==FTS5_PLAN_ROWID). */ + pCsr->ePlan = (pRowidEq ? FTS5_PLAN_ROWID : FTS5_PLAN_SCAN); + rc = sqlite3Fts5StorageStmt( + pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->base.zErrMsg + ); + if( rc==SQLITE_OK ){ + if( pCsr->ePlan==FTS5_PLAN_ROWID ){ + sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); + }else{ + sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid); + sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid); + } + rc = fts5NextMethod(pCursor); + } + } + + pConfig->pzErrmsg = pzErrmsg; + return rc; +} + +/* +** This is the xEof method of the virtual table. SQLite calls this +** routine to find out if it has reached the end of a result set. +*/ +static int fts5EofMethod(sqlite3_vtab_cursor *pCursor){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; + return (CsrFlagTest(pCsr, FTS5CSR_EOF) ? 1 : 0); +} + +/* +** Return the rowid that the cursor currently points to. +*/ +static i64 fts5CursorRowid(Fts5Cursor *pCsr){ + assert( pCsr->ePlan==FTS5_PLAN_MATCH + || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH + || pCsr->ePlan==FTS5_PLAN_SOURCE + ); + if( pCsr->pSorter ){ + return pCsr->pSorter->iRowid; + }else{ + return sqlite3Fts5ExprRowid(pCsr->pExpr); + } +} + +/* +** This is the xRowid method. The SQLite core calls this routine to +** retrieve the rowid for the current row of the result set. fts5 +** exposes %_content.rowid as the rowid for the virtual table. The +** rowid should be written to *pRowid. +*/ +static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; + int ePlan = pCsr->ePlan; + + assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 ); + switch( ePlan ){ + case FTS5_PLAN_SPECIAL: + *pRowid = 0; + break; + + case FTS5_PLAN_SOURCE: + case FTS5_PLAN_MATCH: + case FTS5_PLAN_SORTED_MATCH: + *pRowid = fts5CursorRowid(pCsr); + break; + + default: + *pRowid = sqlite3_column_int64(pCsr->pStmt, 0); + break; + } + + return SQLITE_OK; +} + +/* +** If the cursor requires seeking (bSeekRequired flag is set), seek it. +** Return SQLITE_OK if no error occurs, or an SQLite error code otherwise. +** +** If argument bErrormsg is true and an error occurs, an error message may +** be left in sqlite3_vtab.zErrMsg. +*/ +static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){ + int rc = SQLITE_OK; + + /* If the cursor does not yet have a statement handle, obtain one now. */ + if( pCsr->pStmt==0 ){ + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + int eStmt = fts5StmtType(pCsr); + rc = sqlite3Fts5StorageStmt( + pTab->pStorage, eStmt, &pCsr->pStmt, (bErrormsg?&pTab->base.zErrMsg:0) + ); + assert( rc!=SQLITE_OK || pTab->base.zErrMsg==0 ); + assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ); + } + + if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){ + assert( pCsr->pExpr ); + sqlite3_reset(pCsr->pStmt); + sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr)); + rc = sqlite3_step(pCsr->pStmt); + if( rc==SQLITE_ROW ){ + rc = SQLITE_OK; + CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT); + }else{ + rc = sqlite3_reset(pCsr->pStmt); + if( rc==SQLITE_OK ){ + rc = FTS5_CORRUPT; + } + } + } + return rc; +} + +static void fts5SetVtabError(Fts5Table *p, const char *zFormat, ...){ + va_list ap; /* ... printf arguments */ + va_start(ap, zFormat); + assert( p->base.zErrMsg==0 ); + p->base.zErrMsg = sqlite3_vmprintf(zFormat, ap); + va_end(ap); +} + +/* +** This function is called to handle an FTS INSERT command. In other words, +** an INSERT statement of the form: +** +** INSERT INTO fts(fts) VALUES($pCmd) +** INSERT INTO fts(fts, rank) VALUES($pCmd, $pVal) +** +** Argument pVal is the value assigned to column "fts" by the INSERT +** statement. This function returns SQLITE_OK if successful, or an SQLite +** error code if an error occurs. +** +** The commands implemented by this function are documented in the "Special +** INSERT Directives" section of the documentation. It should be updated if +** more commands are added to this function. +*/ +static int fts5SpecialInsert( + Fts5Table *pTab, /* Fts5 table object */ + const char *zCmd, /* Text inserted into table-name column */ + sqlite3_value *pVal /* Value inserted into rank column */ +){ + Fts5Config *pConfig = pTab->pConfig; + int rc = SQLITE_OK; + int bError = 0; + + if( 0==sqlite3_stricmp("delete-all", zCmd) ){ + if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ + fts5SetVtabError(pTab, + "'delete-all' may only be used with a " + "contentless or external content fts5 table" + ); + rc = SQLITE_ERROR; + }else{ + rc = sqlite3Fts5StorageDeleteAll(pTab->pStorage); + } + }else if( 0==sqlite3_stricmp("rebuild", zCmd) ){ + if( pConfig->eContent==FTS5_CONTENT_NONE ){ + fts5SetVtabError(pTab, + "'rebuild' may not be used with a contentless fts5 table" + ); + rc = SQLITE_ERROR; + }else{ + rc = sqlite3Fts5StorageRebuild(pTab->pStorage); + } + }else if( 0==sqlite3_stricmp("optimize", zCmd) ){ + rc = sqlite3Fts5StorageOptimize(pTab->pStorage); + }else if( 0==sqlite3_stricmp("merge", zCmd) ){ + int nMerge = sqlite3_value_int(pVal); + rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge); + }else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){ + rc = sqlite3Fts5StorageIntegrity(pTab->pStorage); +#ifdef SQLITE_DEBUG + }else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){ + pConfig->bPrefixIndex = sqlite3_value_int(pVal); +#endif + }else{ + rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5ConfigSetValue(pTab->pConfig, zCmd, pVal, &bError); + } + if( rc==SQLITE_OK ){ + if( bError ){ + rc = SQLITE_ERROR; + }else{ + rc = sqlite3Fts5StorageConfigValue(pTab->pStorage, zCmd, pVal, 0); + } + } + } + return rc; +} + +static int fts5SpecialDelete( + Fts5Table *pTab, + sqlite3_value **apVal +){ + int rc = SQLITE_OK; + int eType1 = sqlite3_value_type(apVal[1]); + if( eType1==SQLITE_INTEGER ){ + sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]); + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, &apVal[2]); + } + return rc; +} + +static void fts5StorageInsert( + int *pRc, + Fts5Table *pTab, + sqlite3_value **apVal, + i64 *piRowid +){ + int rc = *pRc; + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, piRowid); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *piRowid); + } + *pRc = rc; +} + +/* +** This function is the implementation of the xUpdate callback used by +** FTS3 virtual tables. It is invoked by SQLite each time a row is to be +** inserted, updated or deleted. +** +** A delete specifies a single argument - the rowid of the row to remove. +** +** Update and insert operations pass: +** +** 1. The "old" rowid, or NULL. +** 2. The "new" rowid. +** 3. Values for each of the nCol matchable columns. +** 4. Values for the two hidden columns ( and "rank"). +*/ +static int fts5UpdateMethod( + sqlite3_vtab *pVtab, /* Virtual table handle */ + int nArg, /* Size of argument array */ + sqlite3_value **apVal, /* Array of arguments */ + sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ +){ + Fts5Table *pTab = (Fts5Table*)pVtab; + Fts5Config *pConfig = pTab->pConfig; + int eType0; /* value_type() of apVal[0] */ + int rc = SQLITE_OK; /* Return code */ + + /* A transaction must be open when this is called. */ + assert( pTab->ts.eState==1 ); + + assert( pVtab->zErrMsg==0 ); + assert( nArg==1 || nArg==(2+pConfig->nCol+2) ); + assert( nArg==1 + || sqlite3_value_type(apVal[1])==SQLITE_INTEGER + || sqlite3_value_type(apVal[1])==SQLITE_NULL + ); + assert( pTab->pConfig->pzErrmsg==0 ); + pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg; + + /* Put any active cursors into REQUIRE_SEEK state. */ + fts5TripCursors(pTab); + + eType0 = sqlite3_value_type(apVal[0]); + if( eType0==SQLITE_NULL + && sqlite3_value_type(apVal[2+pConfig->nCol])!=SQLITE_NULL + ){ + /* A "special" INSERT op. These are handled separately. */ + const char *z = (const char*)sqlite3_value_text(apVal[2+pConfig->nCol]); + if( pConfig->eContent!=FTS5_CONTENT_NORMAL + && 0==sqlite3_stricmp("delete", z) + ){ + rc = fts5SpecialDelete(pTab, apVal); + }else{ + rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]); + } + }else{ + /* A regular INSERT, UPDATE or DELETE statement. The trick here is that + ** any conflict on the rowid value must be detected before any + ** modifications are made to the database file. There are 4 cases: + ** + ** 1) DELETE + ** 2) UPDATE (rowid not modified) + ** 3) UPDATE (rowid modified) + ** 4) INSERT + ** + ** Cases 3 and 4 may violate the rowid constraint. + */ + int eConflict = SQLITE_ABORT; + if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ + eConflict = sqlite3_vtab_on_conflict(pConfig->db); + } + + assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL ); + assert( nArg!=1 || eType0==SQLITE_INTEGER ); + + /* Filter out attempts to run UPDATE or DELETE on contentless tables. + ** This is not suported. */ + if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){ + pTab->base.zErrMsg = sqlite3_mprintf( + "cannot %s contentless fts5 table: %s", + (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName + ); + rc = SQLITE_ERROR; + } + + /* Case 1: DELETE */ + else if( nArg==1 ){ + i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0); + } + + /* Case 2: INSERT */ + else if( eType0!=SQLITE_INTEGER ){ + /* If this is a REPLACE, first remove the current entry (if any) */ + if( eConflict==SQLITE_REPLACE + && sqlite3_value_type(apVal[1])==SQLITE_INTEGER + ){ + i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0); + } + fts5StorageInsert(&rc, pTab, apVal, pRowid); + } + + /* Case 2: UPDATE */ + else{ + i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */ + i64 iNew = sqlite3_value_int64(apVal[1]); /* New rowid */ + if( iOld!=iNew ){ + if( eConflict==SQLITE_REPLACE ){ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0); + } + fts5StorageInsert(&rc, pTab, apVal, pRowid); + }else{ + rc = sqlite3Fts5StorageContentInsert(pTab->pStorage, apVal, pRowid); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal, *pRowid); + } + } + }else{ + rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); + fts5StorageInsert(&rc, pTab, apVal, pRowid); + } + } + } + + pTab->pConfig->pzErrmsg = 0; + return rc; +} + +/* +** Implementation of xSync() method. +*/ +static int fts5SyncMethod(sqlite3_vtab *pVtab){ + int rc; + Fts5Table *pTab = (Fts5Table*)pVtab; + fts5CheckTransactionState(pTab, FTS5_SYNC, 0); + pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg; + fts5TripCursors(pTab); + rc = sqlite3Fts5StorageSync(pTab->pStorage, 1); + pTab->pConfig->pzErrmsg = 0; + return rc; +} + +/* +** Implementation of xBegin() method. +*/ +static int fts5BeginMethod(sqlite3_vtab *pVtab){ + UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */ + fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_BEGIN, 0); + return SQLITE_OK; +} + +/* +** Implementation of xCommit() method. This is a no-op. The contents of +** the pending-terms hash-table have already been flushed into the database +** by fts5SyncMethod(). +*/ +static int fts5CommitMethod(sqlite3_vtab *pVtab){ + UNUSED_PARAM(pVtab); /* Call below is a no-op for NDEBUG builds */ + fts5CheckTransactionState((Fts5Table*)pVtab, FTS5_COMMIT, 0); + return SQLITE_OK; +} + +/* +** Implementation of xRollback(). Discard the contents of the pending-terms +** hash-table. Any changes made to the database are reverted by SQLite. +*/ +static int fts5RollbackMethod(sqlite3_vtab *pVtab){ + int rc; + Fts5Table *pTab = (Fts5Table*)pVtab; + fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0); + rc = sqlite3Fts5StorageRollback(pTab->pStorage); + return rc; +} + +static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*); + +static void *fts5ApiUserData(Fts5Context *pCtx){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + return pCsr->pAux->pUserData; +} + +static int fts5ApiColumnCount(Fts5Context *pCtx){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + return ((Fts5Table*)(pCsr->base.pVtab))->pConfig->nCol; +} + +static int fts5ApiColumnTotalSize( + Fts5Context *pCtx, + int iCol, + sqlite3_int64 *pnToken +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + return sqlite3Fts5StorageSize(pTab->pStorage, iCol, pnToken); +} + +static int fts5ApiRowCount(Fts5Context *pCtx, i64 *pnRow){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + return sqlite3Fts5StorageRowCount(pTab->pStorage, pnRow); +} + +static int fts5ApiTokenize( + Fts5Context *pCtx, + const char *pText, int nText, + void *pUserData, + int (*xToken)(void*, int, const char*, int, int, int) +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + return sqlite3Fts5Tokenize( + pTab->pConfig, FTS5_TOKENIZE_AUX, pText, nText, pUserData, xToken + ); +} + +static int fts5ApiPhraseCount(Fts5Context *pCtx){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + return sqlite3Fts5ExprPhraseCount(pCsr->pExpr); +} + +static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase); +} + +static int fts5ApiColumnText( + Fts5Context *pCtx, + int iCol, + const char **pz, + int *pn +){ + int rc = SQLITE_OK; + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){ + *pz = 0; + *pn = 0; + }else{ + rc = fts5SeekCursor(pCsr, 0); + if( rc==SQLITE_OK ){ + *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1); + *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1); + } + } + return rc; +} + +static int fts5CsrPoslist( + Fts5Cursor *pCsr, + int iPhrase, + const u8 **pa, + int *pn +){ + Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig; + int rc = SQLITE_OK; + int bLive = (pCsr->pSorter==0); + + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){ + + if( pConfig->eDetail!=FTS5_DETAIL_FULL ){ + Fts5PoslistPopulator *aPopulator; + int i; + aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive); + if( aPopulator==0 ) rc = SQLITE_NOMEM; + for(i=0; inCol && rc==SQLITE_OK; i++){ + int n; const char *z; + rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5ExprPopulatePoslists( + pConfig, pCsr->pExpr, aPopulator, i, z, n + ); + } + } + sqlite3_free(aPopulator); + + if( pCsr->pSorter ){ + sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid); + } + } + CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST); + } + + if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){ + Fts5Sorter *pSorter = pCsr->pSorter; + int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); + *pn = pSorter->aIdx[iPhrase] - i1; + *pa = &pSorter->aPoslist[i1]; + }else{ + *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa); + } + + return rc; +} + +/* +** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated +** correctly for the current view. Return SQLITE_OK if successful, or an +** SQLite error code otherwise. +*/ +static int fts5CacheInstArray(Fts5Cursor *pCsr){ + int rc = SQLITE_OK; + Fts5PoslistReader *aIter; /* One iterator for each phrase */ + int nIter; /* Number of iterators/phrases */ + + nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); + if( pCsr->aInstIter==0 ){ + int nByte = sizeof(Fts5PoslistReader) * nIter; + pCsr->aInstIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte); + } + aIter = pCsr->aInstIter; + + if( aIter ){ + int nInst = 0; /* Number instances seen so far */ + int i; + + /* Initialize all iterators */ + for(i=0; i=pCsr->nInstAlloc ){ + pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32; + aInst = (int*)sqlite3_realloc( + pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3 + ); + if( aInst ){ + pCsr->aInst = aInst; + }else{ + rc = SQLITE_NOMEM; + break; + } + } + + aInst = &pCsr->aInst[3 * (nInst-1)]; + aInst[0] = iBest; + aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos); + aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos); + sqlite3Fts5PoslistReaderNext(&aIter[iBest]); + } + } + + pCsr->nInstCount = nInst; + CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST); + } + return rc; +} + +static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + int rc = SQLITE_OK; + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 + || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) ){ + *pnInst = pCsr->nInstCount; + } + return rc; +} + +static int fts5ApiInst( + Fts5Context *pCtx, + int iIdx, + int *piPhrase, + int *piCol, + int *piOff +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + int rc = SQLITE_OK; + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0 + || SQLITE_OK==(rc = fts5CacheInstArray(pCsr)) + ){ + if( iIdx<0 || iIdx>=pCsr->nInstCount ){ + rc = SQLITE_RANGE; +#if 0 + }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){ + *piPhrase = pCsr->aInst[iIdx*3]; + *piCol = pCsr->aInst[iIdx*3 + 2]; + *piOff = -1; +#endif + }else{ + *piPhrase = pCsr->aInst[iIdx*3]; + *piCol = pCsr->aInst[iIdx*3 + 1]; + *piOff = pCsr->aInst[iIdx*3 + 2]; + } + } + return rc; +} + +static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){ + return fts5CursorRowid((Fts5Cursor*)pCtx); +} + +static int fts5ColumnSizeCb( + void *pContext, /* Pointer to int */ + int tflags, + const char *pUnused, /* Buffer containing token */ + int nUnused, /* Size of token in bytes */ + int iUnused1, /* Start offset of token */ + int iUnused2 /* End offset of token */ +){ + int *pCnt = (int*)pContext; + UNUSED_PARAM2(pUnused, nUnused); + UNUSED_PARAM2(iUnused1, iUnused2); + if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){ + (*pCnt)++; + } + return SQLITE_OK; +} + +static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + Fts5Config *pConfig = pTab->pConfig; + int rc = SQLITE_OK; + + if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){ + if( pConfig->bColumnsize ){ + i64 iRowid = fts5CursorRowid(pCsr); + rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize); + }else if( pConfig->zContent==0 ){ + int i; + for(i=0; inCol; i++){ + if( pConfig->abUnindexed[i]==0 ){ + pCsr->aColumnSize[i] = -1; + } + } + }else{ + int i; + for(i=0; rc==SQLITE_OK && inCol; i++){ + if( pConfig->abUnindexed[i]==0 ){ + const char *z; int n; + void *p = (void*)(&pCsr->aColumnSize[i]); + pCsr->aColumnSize[i] = 0; + rc = fts5ApiColumnText(pCtx, i, &z, &n); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5Tokenize( + pConfig, FTS5_TOKENIZE_AUX, z, n, p, fts5ColumnSizeCb + ); + } + } + } + } + CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE); + } + if( iCol<0 ){ + int i; + *pnToken = 0; + for(i=0; inCol; i++){ + *pnToken += pCsr->aColumnSize[i]; + } + }else if( iColnCol ){ + *pnToken = pCsr->aColumnSize[iCol]; + }else{ + *pnToken = 0; + rc = SQLITE_RANGE; + } + return rc; +} + +/* +** Implementation of the xSetAuxdata() method. +*/ +static int fts5ApiSetAuxdata( + Fts5Context *pCtx, /* Fts5 context */ + void *pPtr, /* Pointer to save as auxdata */ + void(*xDelete)(void*) /* Destructor for pPtr (or NULL) */ +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Auxdata *pData; + + /* Search through the cursors list of Fts5Auxdata objects for one that + ** corresponds to the currently executing auxiliary function. */ + for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){ + if( pData->pAux==pCsr->pAux ) break; + } + + if( pData ){ + if( pData->xDelete ){ + pData->xDelete(pData->pPtr); + } + }else{ + int rc = SQLITE_OK; + pData = (Fts5Auxdata*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Auxdata)); + if( pData==0 ){ + if( xDelete ) xDelete(pPtr); + return rc; + } + pData->pAux = pCsr->pAux; + pData->pNext = pCsr->pAuxdata; + pCsr->pAuxdata = pData; + } + + pData->xDelete = xDelete; + pData->pPtr = pPtr; + return SQLITE_OK; +} + +static void *fts5ApiGetAuxdata(Fts5Context *pCtx, int bClear){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Auxdata *pData; + void *pRet = 0; + + for(pData=pCsr->pAuxdata; pData; pData=pData->pNext){ + if( pData->pAux==pCsr->pAux ) break; + } + + if( pData ){ + pRet = pData->pPtr; + if( bClear ){ + pData->pPtr = 0; + pData->xDelete = 0; + } + } + + return pRet; +} + +static void fts5ApiPhraseNext( + Fts5Context *pUnused, + Fts5PhraseIter *pIter, + int *piCol, int *piOff +){ + UNUSED_PARAM(pUnused); + if( pIter->a>=pIter->b ){ + *piCol = -1; + *piOff = -1; + }else{ + int iVal; + pIter->a += fts5GetVarint32(pIter->a, iVal); + if( iVal==1 ){ + pIter->a += fts5GetVarint32(pIter->a, iVal); + *piCol = iVal; + *piOff = 0; + pIter->a += fts5GetVarint32(pIter->a, iVal); + } + *piOff += (iVal-2); + } +} + +static int fts5ApiPhraseFirst( + Fts5Context *pCtx, + int iPhrase, + Fts5PhraseIter *pIter, + int *piCol, int *piOff +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + int n; + int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n); + if( rc==SQLITE_OK ){ + pIter->b = &pIter->a[n]; + *piCol = 0; + *piOff = 0; + fts5ApiPhraseNext(pCtx, pIter, piCol, piOff); + } + return rc; +} + +static void fts5ApiPhraseNextColumn( + Fts5Context *pCtx, + Fts5PhraseIter *pIter, + int *piCol +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig; + + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ + if( pIter->a>=pIter->b ){ + *piCol = -1; + }else{ + int iIncr; + pIter->a += fts5GetVarint32(&pIter->a[0], iIncr); + *piCol += (iIncr-2); + } + }else{ + while( 1 ){ + int dummy; + if( pIter->a>=pIter->b ){ + *piCol = -1; + return; + } + if( pIter->a[0]==0x01 ) break; + pIter->a += fts5GetVarint32(pIter->a, dummy); + } + pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol); + } +} + +static int fts5ApiPhraseFirstColumn( + Fts5Context *pCtx, + int iPhrase, + Fts5PhraseIter *pIter, + int *piCol +){ + int rc = SQLITE_OK; + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig; + + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ + Fts5Sorter *pSorter = pCsr->pSorter; + int n; + if( pSorter ){ + int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]); + n = pSorter->aIdx[iPhrase] - i1; + pIter->a = &pSorter->aPoslist[i1]; + }else{ + rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n); + } + if( rc==SQLITE_OK ){ + pIter->b = &pIter->a[n]; + *piCol = 0; + fts5ApiPhraseNextColumn(pCtx, pIter, piCol); + } + }else{ + int n; + rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n); + if( rc==SQLITE_OK ){ + pIter->b = &pIter->a[n]; + if( n<=0 ){ + *piCol = -1; + }else if( pIter->a[0]==0x01 ){ + pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol); + }else{ + *piCol = 0; + } + } + } + + return rc; +} + + +static int fts5ApiQueryPhrase(Fts5Context*, int, void*, + int(*)(const Fts5ExtensionApi*, Fts5Context*, void*) +); + +static const Fts5ExtensionApi sFts5Api = { + 2, /* iVersion */ + fts5ApiUserData, + fts5ApiColumnCount, + fts5ApiRowCount, + fts5ApiColumnTotalSize, + fts5ApiTokenize, + fts5ApiPhraseCount, + fts5ApiPhraseSize, + fts5ApiInstCount, + fts5ApiInst, + fts5ApiRowid, + fts5ApiColumnText, + fts5ApiColumnSize, + fts5ApiQueryPhrase, + fts5ApiSetAuxdata, + fts5ApiGetAuxdata, + fts5ApiPhraseFirst, + fts5ApiPhraseNext, + fts5ApiPhraseFirstColumn, + fts5ApiPhraseNextColumn, +}; + +/* +** Implementation of API function xQueryPhrase(). +*/ +static int fts5ApiQueryPhrase( + Fts5Context *pCtx, + int iPhrase, + void *pUserData, + int(*xCallback)(const Fts5ExtensionApi*, Fts5Context*, void*) +){ + Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; + Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab); + int rc; + Fts5Cursor *pNew = 0; + + rc = fts5OpenMethod(pCsr->base.pVtab, (sqlite3_vtab_cursor**)&pNew); + if( rc==SQLITE_OK ){ + pNew->ePlan = FTS5_PLAN_MATCH; + pNew->iFirstRowid = SMALLEST_INT64; + pNew->iLastRowid = LARGEST_INT64; + pNew->base.pVtab = (sqlite3_vtab*)pTab; + rc = sqlite3Fts5ExprClonePhrase(pCsr->pExpr, iPhrase, &pNew->pExpr); + } + + if( rc==SQLITE_OK ){ + for(rc = fts5CursorFirst(pTab, pNew, 0); + rc==SQLITE_OK && CsrFlagTest(pNew, FTS5CSR_EOF)==0; + rc = fts5NextMethod((sqlite3_vtab_cursor*)pNew) + ){ + rc = xCallback(&sFts5Api, (Fts5Context*)pNew, pUserData); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + break; + } + } + } + + fts5CloseMethod((sqlite3_vtab_cursor*)pNew); + return rc; +} + +static void fts5ApiInvoke( + Fts5Auxiliary *pAux, + Fts5Cursor *pCsr, + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + assert( pCsr->pAux==0 ); + pCsr->pAux = pAux; + pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv); + pCsr->pAux = 0; +} + +static Fts5Cursor *fts5CursorFromCsrid(Fts5Global *pGlobal, i64 iCsrId){ + Fts5Cursor *pCsr; + for(pCsr=pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){ + if( pCsr->iCsrId==iCsrId ) break; + } + return pCsr; +} + +static void fts5ApiCallback( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + + Fts5Auxiliary *pAux; + Fts5Cursor *pCsr; + i64 iCsrId; + + assert( argc>=1 ); + pAux = (Fts5Auxiliary*)sqlite3_user_data(context); + iCsrId = sqlite3_value_int64(argv[0]); + + pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId); + if( pCsr==0 ){ + char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + }else{ + fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]); + } +} + + +/* +** Given cursor id iId, return a pointer to the corresponding Fts5Index +** object. Or NULL If the cursor id does not exist. +** +** If successful, set *ppConfig to point to the associated config object +** before returning. +*/ +Fts5Index *sqlite3Fts5IndexFromCsrid( + Fts5Global *pGlobal, /* FTS5 global context for db handle */ + i64 iCsrId, /* Id of cursor to find */ + Fts5Config **ppConfig /* OUT: Configuration object */ +){ + Fts5Cursor *pCsr; + Fts5Table *pTab; + + pCsr = fts5CursorFromCsrid(pGlobal, iCsrId); + pTab = (Fts5Table*)pCsr->base.pVtab; + *ppConfig = pTab->pConfig; + + return pTab->pIndex; +} + +/* +** Return a "position-list blob" corresponding to the current position of +** cursor pCsr via sqlite3_result_blob(). A position-list blob contains +** the current position-list for each phrase in the query associated with +** cursor pCsr. +** +** A position-list blob begins with (nPhrase-1) varints, where nPhrase is +** the number of phrases in the query. Following the varints are the +** concatenated position lists for each phrase, in order. +** +** The first varint (if it exists) contains the size of the position list +** for phrase 0. The second (same disclaimer) contains the size of position +** list 1. And so on. There is no size field for the final position list, +** as it can be derived from the total size of the blob. +*/ +static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){ + int i; + int rc = SQLITE_OK; + int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); + Fts5Buffer val; + + memset(&val, 0, sizeof(Fts5Buffer)); + switch( ((Fts5Table*)(pCsr->base.pVtab))->pConfig->eDetail ){ + case FTS5_DETAIL_FULL: + + /* Append the varints */ + for(i=0; i<(nPhrase-1); i++){ + const u8 *dummy; + int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy); + sqlite3Fts5BufferAppendVarint(&rc, &val, nByte); + } + + /* Append the position lists */ + for(i=0; ipExpr, i, &pPoslist); + sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist); + } + break; + + case FTS5_DETAIL_COLUMNS: + + /* Append the varints */ + for(i=0; rc==SQLITE_OK && i<(nPhrase-1); i++){ + const u8 *dummy; + int nByte; + rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &dummy, &nByte); + sqlite3Fts5BufferAppendVarint(&rc, &val, nByte); + } + + /* Append the position lists */ + for(i=0; rc==SQLITE_OK && ipExpr, i, &pPoslist, &nPoslist); + sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist); + } + break; + + default: + break; + } + + sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free); + return rc; +} + +/* +** This is the xColumn method, called by SQLite to request a value from +** the row that the supplied cursor currently points to. +*/ +static int fts5ColumnMethod( + sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ + sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ + int iCol /* Index of column to read value from */ +){ + Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab); + Fts5Config *pConfig = pTab->pConfig; + Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; + int rc = SQLITE_OK; + + assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 ); + + if( pCsr->ePlan==FTS5_PLAN_SPECIAL ){ + if( iCol==pConfig->nCol ){ + sqlite3_result_int64(pCtx, pCsr->iSpecial); + } + }else + + if( iCol==pConfig->nCol ){ + /* User is requesting the value of the special column with the same name + ** as the table. Return the cursor integer id number. This value is only + ** useful in that it may be passed as the first argument to an FTS5 + ** auxiliary function. */ + sqlite3_result_int64(pCtx, pCsr->iCsrId); + }else if( iCol==pConfig->nCol+1 ){ + + /* The value of the "rank" column. */ + if( pCsr->ePlan==FTS5_PLAN_SOURCE ){ + fts5PoslistBlob(pCtx, pCsr); + }else if( + pCsr->ePlan==FTS5_PLAN_MATCH + || pCsr->ePlan==FTS5_PLAN_SORTED_MATCH + ){ + if( pCsr->pRank || SQLITE_OK==(rc = fts5FindRankFunction(pCsr)) ){ + fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg); + } + } + }else if( !fts5IsContentless(pTab) ){ + rc = fts5SeekCursor(pCsr, 1); + if( rc==SQLITE_OK ){ + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); + } + } + return rc; +} + + +/* +** This routine implements the xFindFunction method for the FTS3 +** virtual table. +*/ +static int fts5FindFunctionMethod( + sqlite3_vtab *pVtab, /* Virtual table handle */ + int nUnused, /* Number of SQL function arguments */ + const char *zName, /* Name of SQL function */ + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */ + void **ppArg /* OUT: User data for *pxFunc */ +){ + Fts5Table *pTab = (Fts5Table*)pVtab; + Fts5Auxiliary *pAux; + + UNUSED_PARAM(nUnused); + pAux = fts5FindAuxiliary(pTab, zName); + if( pAux ){ + *pxFunc = fts5ApiCallback; + *ppArg = (void*)pAux; + return 1; + } + + /* No function of the specified name was found. Return 0. */ + return 0; +} + +/* +** Implementation of FTS5 xRename method. Rename an fts5 table. +*/ +static int fts5RenameMethod( + sqlite3_vtab *pVtab, /* Virtual table handle */ + const char *zName /* New name of table */ +){ + Fts5Table *pTab = (Fts5Table*)pVtab; + return sqlite3Fts5StorageRename(pTab->pStorage, zName); +} + +/* +** The xSavepoint() method. +** +** Flush the contents of the pending-terms table to disk. +*/ +static int fts5SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ + Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ + fts5CheckTransactionState(pTab, FTS5_SAVEPOINT, iSavepoint); + fts5TripCursors(pTab); + return sqlite3Fts5StorageSync(pTab->pStorage, 0); +} + +/* +** The xRelease() method. +** +** This is a no-op. +*/ +static int fts5ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){ + Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ + fts5CheckTransactionState(pTab, FTS5_RELEASE, iSavepoint); + fts5TripCursors(pTab); + return sqlite3Fts5StorageSync(pTab->pStorage, 0); +} + +/* +** The xRollbackTo() method. +** +** Discard the contents of the pending terms table. +*/ +static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ + Fts5Table *pTab = (Fts5Table*)pVtab; + UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ + fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); + fts5TripCursors(pTab); + return sqlite3Fts5StorageRollback(pTab->pStorage); +} + +/* +** Register a new auxiliary function with global context pGlobal. +*/ +static int fts5CreateAux( + fts5_api *pApi, /* Global context (one per db handle) */ + const char *zName, /* Name of new function */ + void *pUserData, /* User data for aux. function */ + fts5_extension_function xFunc, /* Aux. function implementation */ + void(*xDestroy)(void*) /* Destructor for pUserData */ +){ + Fts5Global *pGlobal = (Fts5Global*)pApi; + int rc = sqlite3_overload_function(pGlobal->db, zName, -1); + if( rc==SQLITE_OK ){ + Fts5Auxiliary *pAux; + int nName; /* Size of zName in bytes, including \0 */ + int nByte; /* Bytes of space to allocate */ + + nName = (int)strlen(zName) + 1; + nByte = sizeof(Fts5Auxiliary) + nName; + pAux = (Fts5Auxiliary*)sqlite3_malloc(nByte); + if( pAux ){ + memset(pAux, 0, nByte); + pAux->zFunc = (char*)&pAux[1]; + memcpy(pAux->zFunc, zName, nName); + pAux->pGlobal = pGlobal; + pAux->pUserData = pUserData; + pAux->xFunc = xFunc; + pAux->xDestroy = xDestroy; + pAux->pNext = pGlobal->pAux; + pGlobal->pAux = pAux; + }else{ + rc = SQLITE_NOMEM; + } + } + + return rc; +} + +/* +** Register a new tokenizer. This is the implementation of the +** fts5_api.xCreateTokenizer() method. +*/ +static int fts5CreateTokenizer( + fts5_api *pApi, /* Global context (one per db handle) */ + const char *zName, /* Name of new function */ + void *pUserData, /* User data for aux. function */ + fts5_tokenizer *pTokenizer, /* Tokenizer implementation */ + void(*xDestroy)(void*) /* Destructor for pUserData */ +){ + Fts5Global *pGlobal = (Fts5Global*)pApi; + Fts5TokenizerModule *pNew; + int nName; /* Size of zName and its \0 terminator */ + int nByte; /* Bytes of space to allocate */ + int rc = SQLITE_OK; + + nName = (int)strlen(zName) + 1; + nByte = sizeof(Fts5TokenizerModule) + nName; + pNew = (Fts5TokenizerModule*)sqlite3_malloc(nByte); + if( pNew ){ + memset(pNew, 0, nByte); + pNew->zName = (char*)&pNew[1]; + memcpy(pNew->zName, zName, nName); + pNew->pUserData = pUserData; + pNew->x = *pTokenizer; + pNew->xDestroy = xDestroy; + pNew->pNext = pGlobal->pTok; + pGlobal->pTok = pNew; + if( pNew->pNext==0 ){ + pGlobal->pDfltTok = pNew; + } + }else{ + rc = SQLITE_NOMEM; + } + + return rc; +} + +static Fts5TokenizerModule *fts5LocateTokenizer( + Fts5Global *pGlobal, + const char *zName +){ + Fts5TokenizerModule *pMod = 0; + + if( zName==0 ){ + pMod = pGlobal->pDfltTok; + }else{ + for(pMod=pGlobal->pTok; pMod; pMod=pMod->pNext){ + if( sqlite3_stricmp(zName, pMod->zName)==0 ) break; + } + } + + return pMod; +} + +/* +** Find a tokenizer. This is the implementation of the +** fts5_api.xFindTokenizer() method. +*/ +static int fts5FindTokenizer( + fts5_api *pApi, /* Global context (one per db handle) */ + const char *zName, /* Name of new function */ + void **ppUserData, + fts5_tokenizer *pTokenizer /* Populate this object */ +){ + int rc = SQLITE_OK; + Fts5TokenizerModule *pMod; + + pMod = fts5LocateTokenizer((Fts5Global*)pApi, zName); + if( pMod ){ + *pTokenizer = pMod->x; + *ppUserData = pMod->pUserData; + }else{ + memset(pTokenizer, 0, sizeof(fts5_tokenizer)); + rc = SQLITE_ERROR; + } + + return rc; +} + +int sqlite3Fts5GetTokenizer( + Fts5Global *pGlobal, + const char **azArg, + int nArg, + Fts5Tokenizer **ppTok, + fts5_tokenizer **ppTokApi, + char **pzErr +){ + Fts5TokenizerModule *pMod; + int rc = SQLITE_OK; + + pMod = fts5LocateTokenizer(pGlobal, nArg==0 ? 0 : azArg[0]); + if( pMod==0 ){ + assert( nArg>0 ); + rc = SQLITE_ERROR; + *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]); + }else{ + rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok); + *ppTokApi = &pMod->x; + if( rc!=SQLITE_OK && pzErr ){ + *pzErr = sqlite3_mprintf("error in tokenizer constructor"); + } + } + + if( rc!=SQLITE_OK ){ + *ppTokApi = 0; + *ppTok = 0; + } + + return rc; +} + +static void fts5ModuleDestroy(void *pCtx){ + Fts5TokenizerModule *pTok, *pNextTok; + Fts5Auxiliary *pAux, *pNextAux; + Fts5Global *pGlobal = (Fts5Global*)pCtx; + + for(pAux=pGlobal->pAux; pAux; pAux=pNextAux){ + pNextAux = pAux->pNext; + if( pAux->xDestroy ) pAux->xDestroy(pAux->pUserData); + sqlite3_free(pAux); + } + + for(pTok=pGlobal->pTok; pTok; pTok=pNextTok){ + pNextTok = pTok->pNext; + if( pTok->xDestroy ) pTok->xDestroy(pTok->pUserData); + sqlite3_free(pTok); + } + + sqlite3_free(pGlobal); +} + +static void fts5Fts5Func( + sqlite3_context *pCtx, /* Function call context */ + int nArg, /* Number of args */ + sqlite3_value **apUnused /* Function arguments */ +){ + Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx); + char buf[8]; + UNUSED_PARAM2(nArg, apUnused); + assert( nArg==0 ); + assert( sizeof(buf)>=sizeof(pGlobal) ); + memcpy(buf, (void*)&pGlobal, sizeof(pGlobal)); + sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT); +} + +/* +** Implementation of fts5_source_id() function. +*/ +static void fts5SourceIdFunc( + sqlite3_context *pCtx, /* Function call context */ + int nArg, /* Number of args */ + sqlite3_value **apUnused /* Function arguments */ +){ + assert( nArg==0 ); + UNUSED_PARAM2(nArg, apUnused); + sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT); +} + +static int fts5Init(sqlite3 *db){ + static const sqlite3_module fts5Mod = { + /* iVersion */ 2, + /* xCreate */ fts5CreateMethod, + /* xConnect */ fts5ConnectMethod, + /* xBestIndex */ fts5BestIndexMethod, + /* xDisconnect */ fts5DisconnectMethod, + /* xDestroy */ fts5DestroyMethod, + /* xOpen */ fts5OpenMethod, + /* xClose */ fts5CloseMethod, + /* xFilter */ fts5FilterMethod, + /* xNext */ fts5NextMethod, + /* xEof */ fts5EofMethod, + /* xColumn */ fts5ColumnMethod, + /* xRowid */ fts5RowidMethod, + /* xUpdate */ fts5UpdateMethod, + /* xBegin */ fts5BeginMethod, + /* xSync */ fts5SyncMethod, + /* xCommit */ fts5CommitMethod, + /* xRollback */ fts5RollbackMethod, + /* xFindFunction */ fts5FindFunctionMethod, + /* xRename */ fts5RenameMethod, + /* xSavepoint */ fts5SavepointMethod, + /* xRelease */ fts5ReleaseMethod, + /* xRollbackTo */ fts5RollbackToMethod, + }; + + int rc; + Fts5Global *pGlobal = 0; + + pGlobal = (Fts5Global*)sqlite3_malloc(sizeof(Fts5Global)); + if( pGlobal==0 ){ + rc = SQLITE_NOMEM; + }else{ + void *p = (void*)pGlobal; + memset(pGlobal, 0, sizeof(Fts5Global)); + pGlobal->db = db; + pGlobal->api.iVersion = 2; + pGlobal->api.xCreateFunction = fts5CreateAux; + pGlobal->api.xCreateTokenizer = fts5CreateTokenizer; + pGlobal->api.xFindTokenizer = fts5FindTokenizer; + rc = sqlite3_create_module_v2(db, "fts5", &fts5Mod, p, fts5ModuleDestroy); + if( rc==SQLITE_OK ) rc = sqlite3Fts5IndexInit(db); + if( rc==SQLITE_OK ) rc = sqlite3Fts5ExprInit(pGlobal, db); + if( rc==SQLITE_OK ) rc = sqlite3Fts5AuxInit(&pGlobal->api); + if( rc==SQLITE_OK ) rc = sqlite3Fts5TokenizerInit(&pGlobal->api); + if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function( + db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0 + ); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function( + db, "fts5_source_id", 0, SQLITE_UTF8, p, fts5SourceIdFunc, 0, 0 + ); + } + } + return rc; +} + +/* +** The following functions are used to register the module with SQLite. If +** this module is being built as part of the SQLite core (SQLITE_CORE is +** defined), then sqlite3_open() will call sqlite3Fts5Init() directly. +** +** Or, if this module is being built as a loadable extension, +** sqlite3Fts5Init() is omitted and the two standard entry points +** sqlite3_fts_init() and sqlite3_fts5_init() defined instead. +*/ +#ifndef SQLITE_CORE +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_fts_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + return fts5Init(db); +} + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_fts5_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + return fts5Init(db); +} +#else +int sqlite3Fts5Init(sqlite3 *db){ + return fts5Init(db); +} +#endif diff --git a/ext/fts5/fts5_storage.c b/ext/fts5/fts5_storage.c new file mode 100644 index 0000000..e4f5dd8 --- /dev/null +++ b/ext/fts5/fts5_storage.c @@ -0,0 +1,1125 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +** +*/ + + + +#include "fts5Int.h" + +struct Fts5Storage { + Fts5Config *pConfig; + Fts5Index *pIndex; + int bTotalsValid; /* True if nTotalRow/aTotalSize[] are valid */ + i64 nTotalRow; /* Total number of rows in FTS table */ + i64 *aTotalSize; /* Total sizes of each column */ + sqlite3_stmt *aStmt[11]; +}; + + +#if FTS5_STMT_SCAN_ASC!=0 +# error "FTS5_STMT_SCAN_ASC mismatch" +#endif +#if FTS5_STMT_SCAN_DESC!=1 +# error "FTS5_STMT_SCAN_DESC mismatch" +#endif +#if FTS5_STMT_LOOKUP!=2 +# error "FTS5_STMT_LOOKUP mismatch" +#endif + +#define FTS5_STMT_INSERT_CONTENT 3 +#define FTS5_STMT_REPLACE_CONTENT 4 +#define FTS5_STMT_DELETE_CONTENT 5 +#define FTS5_STMT_REPLACE_DOCSIZE 6 +#define FTS5_STMT_DELETE_DOCSIZE 7 +#define FTS5_STMT_LOOKUP_DOCSIZE 8 +#define FTS5_STMT_REPLACE_CONFIG 9 +#define FTS5_STMT_SCAN 10 + +/* +** Prepare the two insert statements - Fts5Storage.pInsertContent and +** Fts5Storage.pInsertDocsize - if they have not already been prepared. +** Return SQLITE_OK if successful, or an SQLite error code if an error +** occurs. +*/ +static int fts5StorageGetStmt( + Fts5Storage *p, /* Storage handle */ + int eStmt, /* FTS5_STMT_XXX constant */ + sqlite3_stmt **ppStmt, /* OUT: Prepared statement handle */ + char **pzErrMsg /* OUT: Error message (if any) */ +){ + int rc = SQLITE_OK; + + /* If there is no %_docsize table, there should be no requests for + ** statements to operate on it. */ + assert( p->pConfig->bColumnsize || ( + eStmt!=FTS5_STMT_REPLACE_DOCSIZE + && eStmt!=FTS5_STMT_DELETE_DOCSIZE + && eStmt!=FTS5_STMT_LOOKUP_DOCSIZE + )); + + assert( eStmt>=0 && eStmtaStmt) ); + if( p->aStmt[eStmt]==0 ){ + const char *azStmt[] = { + "SELECT %s FROM %s T WHERE T.%Q >= ? AND T.%Q <= ? ORDER BY T.%Q ASC", + "SELECT %s FROM %s T WHERE T.%Q <= ? AND T.%Q >= ? ORDER BY T.%Q DESC", + "SELECT %s FROM %s T WHERE T.%Q=?", /* LOOKUP */ + + "INSERT INTO %Q.'%q_content' VALUES(%s)", /* INSERT_CONTENT */ + "REPLACE INTO %Q.'%q_content' VALUES(%s)", /* REPLACE_CONTENT */ + "DELETE FROM %Q.'%q_content' WHERE id=?", /* DELETE_CONTENT */ + "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", /* REPLACE_DOCSIZE */ + "DELETE FROM %Q.'%q_docsize' WHERE id=?", /* DELETE_DOCSIZE */ + + "SELECT sz FROM %Q.'%q_docsize' WHERE id=?", /* LOOKUP_DOCSIZE */ + + "REPLACE INTO %Q.'%q_config' VALUES(?,?)", /* REPLACE_CONFIG */ + "SELECT %s FROM %s AS T", /* SCAN */ + }; + Fts5Config *pC = p->pConfig; + char *zSql = 0; + + switch( eStmt ){ + case FTS5_STMT_SCAN: + zSql = sqlite3_mprintf(azStmt[eStmt], + pC->zContentExprlist, pC->zContent + ); + break; + + case FTS5_STMT_SCAN_ASC: + case FTS5_STMT_SCAN_DESC: + zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContentExprlist, + pC->zContent, pC->zContentRowid, pC->zContentRowid, + pC->zContentRowid + ); + break; + + case FTS5_STMT_LOOKUP: + zSql = sqlite3_mprintf(azStmt[eStmt], + pC->zContentExprlist, pC->zContent, pC->zContentRowid + ); + break; + + case FTS5_STMT_INSERT_CONTENT: + case FTS5_STMT_REPLACE_CONTENT: { + int nCol = pC->nCol + 1; + char *zBind; + int i; + + zBind = sqlite3_malloc(1 + nCol*2); + if( zBind ){ + for(i=0; izDb, pC->zName, zBind); + sqlite3_free(zBind); + } + break; + } + + default: + zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName); + break; + } + + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0); + sqlite3_free(zSql); + if( rc!=SQLITE_OK && pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db)); + } + } + } + + *ppStmt = p->aStmt[eStmt]; + return rc; +} + + +static int fts5ExecPrintf( + sqlite3 *db, + char **pzErr, + const char *zFormat, + ... +){ + int rc; + va_list ap; /* ... printf arguments */ + char *zSql; + + va_start(ap, zFormat); + zSql = sqlite3_vmprintf(zFormat, ap); + + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_exec(db, zSql, 0, 0, pzErr); + sqlite3_free(zSql); + } + + va_end(ap); + return rc; +} + +/* +** Drop all shadow tables. Return SQLITE_OK if successful or an SQLite error +** code otherwise. +*/ +int sqlite3Fts5DropAll(Fts5Config *pConfig){ + int rc = fts5ExecPrintf(pConfig->db, 0, + "DROP TABLE IF EXISTS %Q.'%q_data';" + "DROP TABLE IF EXISTS %Q.'%q_idx';" + "DROP TABLE IF EXISTS %Q.'%q_config';", + pConfig->zDb, pConfig->zName, + pConfig->zDb, pConfig->zName, + pConfig->zDb, pConfig->zName + ); + if( rc==SQLITE_OK && pConfig->bColumnsize ){ + rc = fts5ExecPrintf(pConfig->db, 0, + "DROP TABLE IF EXISTS %Q.'%q_docsize';", + pConfig->zDb, pConfig->zName + ); + } + if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ + rc = fts5ExecPrintf(pConfig->db, 0, + "DROP TABLE IF EXISTS %Q.'%q_content';", + pConfig->zDb, pConfig->zName + ); + } + return rc; +} + +static void fts5StorageRenameOne( + Fts5Config *pConfig, /* Current FTS5 configuration */ + int *pRc, /* IN/OUT: Error code */ + const char *zTail, /* Tail of table name e.g. "data", "config" */ + const char *zName /* New name of FTS5 table */ +){ + if( *pRc==SQLITE_OK ){ + *pRc = fts5ExecPrintf(pConfig->db, 0, + "ALTER TABLE %Q.'%q_%s' RENAME TO '%q_%s';", + pConfig->zDb, pConfig->zName, zTail, zName, zTail + ); + } +} + +int sqlite3Fts5StorageRename(Fts5Storage *pStorage, const char *zName){ + Fts5Config *pConfig = pStorage->pConfig; + int rc = sqlite3Fts5StorageSync(pStorage, 1); + + fts5StorageRenameOne(pConfig, &rc, "data", zName); + fts5StorageRenameOne(pConfig, &rc, "idx", zName); + fts5StorageRenameOne(pConfig, &rc, "config", zName); + if( pConfig->bColumnsize ){ + fts5StorageRenameOne(pConfig, &rc, "docsize", zName); + } + if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ + fts5StorageRenameOne(pConfig, &rc, "content", zName); + } + return rc; +} + +/* +** Create the shadow table named zPost, with definition zDefn. Return +** SQLITE_OK if successful, or an SQLite error code otherwise. +*/ +int sqlite3Fts5CreateTable( + Fts5Config *pConfig, /* FTS5 configuration */ + const char *zPost, /* Shadow table to create (e.g. "content") */ + const char *zDefn, /* Columns etc. for shadow table */ + int bWithout, /* True for without rowid */ + char **pzErr /* OUT: Error message */ +){ + int rc; + char *zErr = 0; + + rc = fts5ExecPrintf(pConfig->db, &zErr, "CREATE TABLE %Q.'%q_%q'(%s)%s", + pConfig->zDb, pConfig->zName, zPost, zDefn, bWithout?" WITHOUT ROWID":"" + ); + if( zErr ){ + *pzErr = sqlite3_mprintf( + "fts5: error creating shadow table %q_%s: %s", + pConfig->zName, zPost, zErr + ); + sqlite3_free(zErr); + } + + return rc; +} + +/* +** Open a new Fts5Index handle. If the bCreate argument is true, create +** and initialize the underlying tables +** +** If successful, set *pp to point to the new object and return SQLITE_OK. +** Otherwise, set *pp to NULL and return an SQLite error code. +*/ +int sqlite3Fts5StorageOpen( + Fts5Config *pConfig, + Fts5Index *pIndex, + int bCreate, + Fts5Storage **pp, + char **pzErr /* OUT: Error message */ +){ + int rc = SQLITE_OK; + Fts5Storage *p; /* New object */ + int nByte; /* Bytes of space to allocate */ + + nByte = sizeof(Fts5Storage) /* Fts5Storage object */ + + pConfig->nCol * sizeof(i64); /* Fts5Storage.aTotalSize[] */ + *pp = p = (Fts5Storage*)sqlite3_malloc(nByte); + if( !p ) return SQLITE_NOMEM; + + memset(p, 0, nByte); + p->aTotalSize = (i64*)&p[1]; + p->pConfig = pConfig; + p->pIndex = pIndex; + + if( bCreate ){ + if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ + int nDefn = 32 + pConfig->nCol*10; + char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10); + if( zDefn==0 ){ + rc = SQLITE_NOMEM; + }else{ + int i; + int iOff; + sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY"); + iOff = (int)strlen(zDefn); + for(i=0; inCol; i++){ + sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i); + iOff += (int)strlen(&zDefn[iOff]); + } + rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr); + } + sqlite3_free(zDefn); + } + + if( rc==SQLITE_OK && pConfig->bColumnsize ){ + rc = sqlite3Fts5CreateTable( + pConfig, "docsize", "id INTEGER PRIMARY KEY, sz BLOB", 0, pzErr + ); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5CreateTable( + pConfig, "config", "k PRIMARY KEY, v", 1, pzErr + ); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageConfigValue(p, "version", 0, FTS5_CURRENT_VERSION); + } + } + + if( rc ){ + sqlite3Fts5StorageClose(p); + *pp = 0; + } + return rc; +} + +/* +** Close a handle opened by an earlier call to sqlite3Fts5StorageOpen(). +*/ +int sqlite3Fts5StorageClose(Fts5Storage *p){ + int rc = SQLITE_OK; + if( p ){ + int i; + + /* Finalize all SQL statements */ + for(i=0; iaStmt); i++){ + sqlite3_finalize(p->aStmt[i]); + } + + sqlite3_free(p); + } + return rc; +} + +typedef struct Fts5InsertCtx Fts5InsertCtx; +struct Fts5InsertCtx { + Fts5Storage *pStorage; + int iCol; + int szCol; /* Size of column value in tokens */ +}; + +/* +** Tokenization callback used when inserting tokens into the FTS index. +*/ +static int fts5StorageInsertCallback( + void *pContext, /* Pointer to Fts5InsertCtx object */ + int tflags, + const char *pToken, /* Buffer containing token */ + int nToken, /* Size of token in bytes */ + int iUnused1, /* Start offset of token */ + int iUnused2 /* End offset of token */ +){ + Fts5InsertCtx *pCtx = (Fts5InsertCtx*)pContext; + Fts5Index *pIdx = pCtx->pStorage->pIndex; + UNUSED_PARAM2(iUnused1, iUnused2); + if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){ + pCtx->szCol++; + } + return sqlite3Fts5IndexWrite(pIdx, pCtx->iCol, pCtx->szCol-1, pToken, nToken); +} + +/* +** If a row with rowid iDel is present in the %_content table, add the +** delete-markers to the FTS index necessary to delete it. Do not actually +** remove the %_content row at this time though. +*/ +static int fts5StorageDeleteFromIndex( + Fts5Storage *p, + i64 iDel, + sqlite3_value **apVal +){ + Fts5Config *pConfig = p->pConfig; + sqlite3_stmt *pSeek = 0; /* SELECT to read row iDel from %_data */ + int rc; /* Return code */ + int rc2; /* sqlite3_reset() return code */ + int iCol; + Fts5InsertCtx ctx; + + if( apVal==0 ){ + rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0); + if( rc!=SQLITE_OK ) return rc; + sqlite3_bind_int64(pSeek, 1, iDel); + if( sqlite3_step(pSeek)!=SQLITE_ROW ){ + return sqlite3_reset(pSeek); + } + } + + ctx.pStorage = p; + ctx.iCol = -1; + rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 1, iDel); + for(iCol=1; rc==SQLITE_OK && iCol<=pConfig->nCol; iCol++){ + if( pConfig->abUnindexed[iCol-1]==0 ){ + const char *zText; + int nText; + if( pSeek ){ + zText = (const char*)sqlite3_column_text(pSeek, iCol); + nText = sqlite3_column_bytes(pSeek, iCol); + }else{ + zText = (const char*)sqlite3_value_text(apVal[iCol-1]); + nText = sqlite3_value_bytes(apVal[iCol-1]); + } + ctx.szCol = 0; + rc = sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT, + zText, nText, (void*)&ctx, fts5StorageInsertCallback + ); + p->aTotalSize[iCol-1] -= (i64)ctx.szCol; + } + } + p->nTotalRow--; + + rc2 = sqlite3_reset(pSeek); + if( rc==SQLITE_OK ) rc = rc2; + return rc; +} + + +/* +** Insert a record into the %_docsize table. Specifically, do: +** +** INSERT OR REPLACE INTO %_docsize(id, sz) VALUES(iRowid, pBuf); +** +** If there is no %_docsize table (as happens if the columnsize=0 option +** is specified when the FTS5 table is created), this function is a no-op. +*/ +static int fts5StorageInsertDocsize( + Fts5Storage *p, /* Storage module to write to */ + i64 iRowid, /* id value */ + Fts5Buffer *pBuf /* sz value */ +){ + int rc = SQLITE_OK; + if( p->pConfig->bColumnsize ){ + sqlite3_stmt *pReplace = 0; + rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pReplace, 1, iRowid); + sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); + sqlite3_step(pReplace); + rc = sqlite3_reset(pReplace); + } + } + return rc; +} + +/* +** Load the contents of the "averages" record from disk into the +** p->nTotalRow and p->aTotalSize[] variables. If successful, and if +** argument bCache is true, set the p->bTotalsValid flag to indicate +** that the contents of aTotalSize[] and nTotalRow are valid until +** further notice. +** +** Return SQLITE_OK if successful, or an SQLite error code if an error +** occurs. +*/ +static int fts5StorageLoadTotals(Fts5Storage *p, int bCache){ + int rc = SQLITE_OK; + if( p->bTotalsValid==0 ){ + rc = sqlite3Fts5IndexGetAverages(p->pIndex, &p->nTotalRow, p->aTotalSize); + p->bTotalsValid = bCache; + } + return rc; +} + +/* +** Store the current contents of the p->nTotalRow and p->aTotalSize[] +** variables in the "averages" record on disk. +** +** Return SQLITE_OK if successful, or an SQLite error code if an error +** occurs. +*/ +static int fts5StorageSaveTotals(Fts5Storage *p){ + int nCol = p->pConfig->nCol; + int i; + Fts5Buffer buf; + int rc = SQLITE_OK; + memset(&buf, 0, sizeof(buf)); + + sqlite3Fts5BufferAppendVarint(&rc, &buf, p->nTotalRow); + for(i=0; iaTotalSize[i]); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexSetAverages(p->pIndex, buf.p, buf.n); + } + sqlite3_free(buf.p); + + return rc; +} + +/* +** Remove a row from the FTS table. +*/ +int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){ + Fts5Config *pConfig = p->pConfig; + int rc; + sqlite3_stmt *pDel = 0; + + assert( pConfig->eContent!=FTS5_CONTENT_NORMAL || apVal==0 ); + rc = fts5StorageLoadTotals(p, 1); + + /* Delete the index records */ + if( rc==SQLITE_OK ){ + rc = fts5StorageDeleteFromIndex(p, iDel, apVal); + } + + /* Delete the %_docsize record */ + if( rc==SQLITE_OK && pConfig->bColumnsize ){ + rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pDel, 1, iDel); + sqlite3_step(pDel); + rc = sqlite3_reset(pDel); + } + } + + /* Delete the %_content record */ + if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ + if( rc==SQLITE_OK ){ + rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0); + } + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pDel, 1, iDel); + sqlite3_step(pDel); + rc = sqlite3_reset(pDel); + } + } + + /* Write the averages record */ + if( rc==SQLITE_OK ){ + rc = fts5StorageSaveTotals(p); + } + + return rc; +} + +/* +** Delete all entries in the FTS5 index. +*/ +int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){ + Fts5Config *pConfig = p->pConfig; + int rc; + + /* Delete the contents of the %_data and %_docsize tables. */ + rc = fts5ExecPrintf(pConfig->db, 0, + "DELETE FROM %Q.'%q_data';" + "DELETE FROM %Q.'%q_idx';", + pConfig->zDb, pConfig->zName, + pConfig->zDb, pConfig->zName + ); + if( rc==SQLITE_OK && pConfig->bColumnsize ){ + rc = fts5ExecPrintf(pConfig->db, 0, + "DELETE FROM %Q.'%q_docsize';", + pConfig->zDb, pConfig->zName + ); + } + + /* Reinitialize the %_data table. This call creates the initial structure + ** and averages records. */ + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexReinit(p->pIndex); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5StorageConfigValue(p, "version", 0, FTS5_CURRENT_VERSION); + } + return rc; +} + +int sqlite3Fts5StorageRebuild(Fts5Storage *p){ + Fts5Buffer buf = {0,0,0}; + Fts5Config *pConfig = p->pConfig; + sqlite3_stmt *pScan = 0; + Fts5InsertCtx ctx; + int rc; + + memset(&ctx, 0, sizeof(Fts5InsertCtx)); + ctx.pStorage = p; + rc = sqlite3Fts5StorageDeleteAll(p); + if( rc==SQLITE_OK ){ + rc = fts5StorageLoadTotals(p, 1); + } + + if( rc==SQLITE_OK ){ + rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0); + } + + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pScan) ){ + i64 iRowid = sqlite3_column_int64(pScan, 0); + + sqlite3Fts5BufferZero(&buf); + rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid); + for(ctx.iCol=0; rc==SQLITE_OK && ctx.iColnCol; ctx.iCol++){ + ctx.szCol = 0; + if( pConfig->abUnindexed[ctx.iCol]==0 ){ + rc = sqlite3Fts5Tokenize(pConfig, + FTS5_TOKENIZE_DOCUMENT, + (const char*)sqlite3_column_text(pScan, ctx.iCol+1), + sqlite3_column_bytes(pScan, ctx.iCol+1), + (void*)&ctx, + fts5StorageInsertCallback + ); + } + sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol); + p->aTotalSize[ctx.iCol] += (i64)ctx.szCol; + } + p->nTotalRow++; + + if( rc==SQLITE_OK ){ + rc = fts5StorageInsertDocsize(p, iRowid, &buf); + } + } + sqlite3_free(buf.p); + + /* Write the averages record */ + if( rc==SQLITE_OK ){ + rc = fts5StorageSaveTotals(p); + } + return rc; +} + +int sqlite3Fts5StorageOptimize(Fts5Storage *p){ + return sqlite3Fts5IndexOptimize(p->pIndex); +} + +int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge){ + return sqlite3Fts5IndexMerge(p->pIndex, nMerge); +} + +/* +** Allocate a new rowid. This is used for "external content" tables when +** a NULL value is inserted into the rowid column. The new rowid is allocated +** by inserting a dummy row into the %_docsize table. The dummy will be +** overwritten later. +** +** If the %_docsize table does not exist, SQLITE_MISMATCH is returned. In +** this case the user is required to provide a rowid explicitly. +*/ +static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){ + int rc = SQLITE_MISMATCH; + if( p->pConfig->bColumnsize ){ + sqlite3_stmt *pReplace = 0; + rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_null(pReplace, 1); + sqlite3_bind_null(pReplace, 2); + sqlite3_step(pReplace); + rc = sqlite3_reset(pReplace); + } + if( rc==SQLITE_OK ){ + *piRowid = sqlite3_last_insert_rowid(p->pConfig->db); + } + } + return rc; +} + +/* +** Insert a new row into the FTS content table. +*/ +int sqlite3Fts5StorageContentInsert( + Fts5Storage *p, + sqlite3_value **apVal, + i64 *piRowid +){ + Fts5Config *pConfig = p->pConfig; + int rc = SQLITE_OK; + + /* Insert the new row into the %_content table. */ + if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){ + if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){ + *piRowid = sqlite3_value_int64(apVal[1]); + }else{ + rc = fts5StorageNewRowid(p, piRowid); + } + }else{ + sqlite3_stmt *pInsert = 0; /* Statement to write %_content table */ + int i; /* Counter variable */ + rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0); + for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){ + rc = sqlite3_bind_value(pInsert, i, apVal[i]); + } + if( rc==SQLITE_OK ){ + sqlite3_step(pInsert); + rc = sqlite3_reset(pInsert); + } + *piRowid = sqlite3_last_insert_rowid(pConfig->db); + } + + return rc; +} + +/* +** Insert new entries into the FTS index and %_docsize table. +*/ +int sqlite3Fts5StorageIndexInsert( + Fts5Storage *p, + sqlite3_value **apVal, + i64 iRowid +){ + Fts5Config *pConfig = p->pConfig; + int rc = SQLITE_OK; /* Return code */ + Fts5InsertCtx ctx; /* Tokenization callback context object */ + Fts5Buffer buf; /* Buffer used to build up %_docsize blob */ + + memset(&buf, 0, sizeof(Fts5Buffer)); + ctx.pStorage = p; + rc = fts5StorageLoadTotals(p, 1); + + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexBeginWrite(p->pIndex, 0, iRowid); + } + for(ctx.iCol=0; rc==SQLITE_OK && ctx.iColnCol; ctx.iCol++){ + ctx.szCol = 0; + if( pConfig->abUnindexed[ctx.iCol]==0 ){ + rc = sqlite3Fts5Tokenize(pConfig, + FTS5_TOKENIZE_DOCUMENT, + (const char*)sqlite3_value_text(apVal[ctx.iCol+2]), + sqlite3_value_bytes(apVal[ctx.iCol+2]), + (void*)&ctx, + fts5StorageInsertCallback + ); + } + sqlite3Fts5BufferAppendVarint(&rc, &buf, ctx.szCol); + p->aTotalSize[ctx.iCol] += (i64)ctx.szCol; + } + p->nTotalRow++; + + /* Write the %_docsize record */ + if( rc==SQLITE_OK ){ + rc = fts5StorageInsertDocsize(p, iRowid, &buf); + } + sqlite3_free(buf.p); + + /* Write the averages record */ + if( rc==SQLITE_OK ){ + rc = fts5StorageSaveTotals(p); + } + + return rc; +} + +static int fts5StorageCount(Fts5Storage *p, const char *zSuffix, i64 *pnRow){ + Fts5Config *pConfig = p->pConfig; + char *zSql; + int rc; + + zSql = sqlite3_mprintf("SELECT count(*) FROM %Q.'%q_%s'", + pConfig->zDb, pConfig->zName, zSuffix + ); + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3_stmt *pCnt = 0; + rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pCnt, 0); + if( rc==SQLITE_OK ){ + if( SQLITE_ROW==sqlite3_step(pCnt) ){ + *pnRow = sqlite3_column_int64(pCnt, 0); + } + rc = sqlite3_finalize(pCnt); + } + } + + sqlite3_free(zSql); + return rc; +} + +/* +** Context object used by sqlite3Fts5StorageIntegrity(). +*/ +typedef struct Fts5IntegrityCtx Fts5IntegrityCtx; +struct Fts5IntegrityCtx { + i64 iRowid; + int iCol; + int szCol; + u64 cksum; + Fts5Termset *pTermset; + Fts5Config *pConfig; +}; + + +/* +** Tokenization callback used by integrity check. +*/ +static int fts5StorageIntegrityCallback( + void *pContext, /* Pointer to Fts5IntegrityCtx object */ + int tflags, + const char *pToken, /* Buffer containing token */ + int nToken, /* Size of token in bytes */ + int iUnused1, /* Start offset of token */ + int iUnused2 /* End offset of token */ +){ + Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext; + Fts5Termset *pTermset = pCtx->pTermset; + int bPresent; + int ii; + int rc = SQLITE_OK; + int iPos; + int iCol; + + UNUSED_PARAM2(iUnused1, iUnused2); + + if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){ + pCtx->szCol++; + } + + switch( pCtx->pConfig->eDetail ){ + case FTS5_DETAIL_FULL: + iPos = pCtx->szCol-1; + iCol = pCtx->iCol; + break; + + case FTS5_DETAIL_COLUMNS: + iPos = pCtx->iCol; + iCol = 0; + break; + + default: + assert( pCtx->pConfig->eDetail==FTS5_DETAIL_NONE ); + iPos = 0; + iCol = 0; + break; + } + + rc = sqlite3Fts5TermsetAdd(pTermset, 0, pToken, nToken, &bPresent); + if( rc==SQLITE_OK && bPresent==0 ){ + pCtx->cksum ^= sqlite3Fts5IndexEntryCksum( + pCtx->iRowid, iCol, iPos, 0, pToken, nToken + ); + } + + for(ii=0; rc==SQLITE_OK && iipConfig->nPrefix; ii++){ + const int nChar = pCtx->pConfig->aPrefix[ii]; + int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar); + if( nByte ){ + rc = sqlite3Fts5TermsetAdd(pTermset, ii+1, pToken, nByte, &bPresent); + if( bPresent==0 ){ + pCtx->cksum ^= sqlite3Fts5IndexEntryCksum( + pCtx->iRowid, iCol, iPos, ii+1, pToken, nByte + ); + } + } + } + + return rc; +} + +/* +** Check that the contents of the FTS index match that of the %_content +** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return +** some other SQLite error code if an error occurs while attempting to +** determine this. +*/ +int sqlite3Fts5StorageIntegrity(Fts5Storage *p){ + Fts5Config *pConfig = p->pConfig; + int rc; /* Return code */ + int *aColSize; /* Array of size pConfig->nCol */ + i64 *aTotalSize; /* Array of size pConfig->nCol */ + Fts5IntegrityCtx ctx; + sqlite3_stmt *pScan; + + memset(&ctx, 0, sizeof(Fts5IntegrityCtx)); + ctx.pConfig = p->pConfig; + aTotalSize = (i64*)sqlite3_malloc(pConfig->nCol * (sizeof(int)+sizeof(i64))); + if( !aTotalSize ) return SQLITE_NOMEM; + aColSize = (int*)&aTotalSize[pConfig->nCol]; + memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol); + + /* Generate the expected index checksum based on the contents of the + ** %_content table. This block stores the checksum in ctx.cksum. */ + rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0); + if( rc==SQLITE_OK ){ + int rc2; + while( SQLITE_ROW==sqlite3_step(pScan) ){ + int i; + ctx.iRowid = sqlite3_column_int64(pScan, 0); + ctx.szCol = 0; + if( pConfig->bColumnsize ){ + rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize); + } + if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){ + rc = sqlite3Fts5TermsetNew(&ctx.pTermset); + } + for(i=0; rc==SQLITE_OK && inCol; i++){ + if( pConfig->abUnindexed[i] ) continue; + ctx.iCol = i; + ctx.szCol = 0; + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ + rc = sqlite3Fts5TermsetNew(&ctx.pTermset); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5Tokenize(pConfig, + FTS5_TOKENIZE_DOCUMENT, + (const char*)sqlite3_column_text(pScan, i+1), + sqlite3_column_bytes(pScan, i+1), + (void*)&ctx, + fts5StorageIntegrityCallback + ); + } + if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){ + rc = FTS5_CORRUPT; + } + aTotalSize[i] += ctx.szCol; + if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){ + sqlite3Fts5TermsetFree(ctx.pTermset); + ctx.pTermset = 0; + } + } + sqlite3Fts5TermsetFree(ctx.pTermset); + ctx.pTermset = 0; + + if( rc!=SQLITE_OK ) break; + } + rc2 = sqlite3_reset(pScan); + if( rc==SQLITE_OK ) rc = rc2; + } + + /* Test that the "totals" (sometimes called "averages") record looks Ok */ + if( rc==SQLITE_OK ){ + int i; + rc = fts5StorageLoadTotals(p, 0); + for(i=0; rc==SQLITE_OK && inCol; i++){ + if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT; + } + } + + /* Check that the %_docsize and %_content tables contain the expected + ** number of rows. */ + if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){ + i64 nRow = 0; + rc = fts5StorageCount(p, "content", &nRow); + if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; + } + if( rc==SQLITE_OK && pConfig->bColumnsize ){ + i64 nRow = 0; + rc = fts5StorageCount(p, "docsize", &nRow); + if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT; + } + + /* Pass the expected checksum down to the FTS index module. It will + ** verify, amongst other things, that it matches the checksum generated by + ** inspecting the index itself. */ + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum); + } + + sqlite3_free(aTotalSize); + return rc; +} + +/* +** Obtain an SQLite statement handle that may be used to read data from the +** %_content table. +*/ +int sqlite3Fts5StorageStmt( + Fts5Storage *p, + int eStmt, + sqlite3_stmt **pp, + char **pzErrMsg +){ + int rc; + assert( eStmt==FTS5_STMT_SCAN_ASC + || eStmt==FTS5_STMT_SCAN_DESC + || eStmt==FTS5_STMT_LOOKUP + ); + rc = fts5StorageGetStmt(p, eStmt, pp, pzErrMsg); + if( rc==SQLITE_OK ){ + assert( p->aStmt[eStmt]==*pp ); + p->aStmt[eStmt] = 0; + } + return rc; +} + +/* +** Release an SQLite statement handle obtained via an earlier call to +** sqlite3Fts5StorageStmt(). The eStmt parameter passed to this function +** must match that passed to the sqlite3Fts5StorageStmt() call. +*/ +void sqlite3Fts5StorageStmtRelease( + Fts5Storage *p, + int eStmt, + sqlite3_stmt *pStmt +){ + assert( eStmt==FTS5_STMT_SCAN_ASC + || eStmt==FTS5_STMT_SCAN_DESC + || eStmt==FTS5_STMT_LOOKUP + ); + if( p->aStmt[eStmt]==0 ){ + sqlite3_reset(pStmt); + p->aStmt[eStmt] = pStmt; + }else{ + sqlite3_finalize(pStmt); + } +} + +static int fts5StorageDecodeSizeArray( + int *aCol, int nCol, /* Array to populate */ + const u8 *aBlob, int nBlob /* Record to read varints from */ +){ + int i; + int iOff = 0; + for(i=0; i=nBlob ) return 1; + iOff += fts5GetVarint32(&aBlob[iOff], aCol[i]); + } + return (iOff!=nBlob); +} + +/* +** Argument aCol points to an array of integers containing one entry for +** each table column. This function reads the %_docsize record for the +** specified rowid and populates aCol[] with the results. +** +** An SQLite error code is returned if an error occurs, or SQLITE_OK +** otherwise. +*/ +int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){ + int nCol = p->pConfig->nCol; /* Number of user columns in table */ + sqlite3_stmt *pLookup = 0; /* Statement to query %_docsize */ + int rc; /* Return Code */ + + assert( p->pConfig->bColumnsize ); + rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0); + if( rc==SQLITE_OK ){ + int bCorrupt = 1; + sqlite3_bind_int64(pLookup, 1, iRowid); + if( SQLITE_ROW==sqlite3_step(pLookup) ){ + const u8 *aBlob = sqlite3_column_blob(pLookup, 0); + int nBlob = sqlite3_column_bytes(pLookup, 0); + if( 0==fts5StorageDecodeSizeArray(aCol, nCol, aBlob, nBlob) ){ + bCorrupt = 0; + } + } + rc = sqlite3_reset(pLookup); + if( bCorrupt && rc==SQLITE_OK ){ + rc = FTS5_CORRUPT; + } + } + + return rc; +} + +int sqlite3Fts5StorageSize(Fts5Storage *p, int iCol, i64 *pnToken){ + int rc = fts5StorageLoadTotals(p, 0); + if( rc==SQLITE_OK ){ + *pnToken = 0; + if( iCol<0 ){ + int i; + for(i=0; ipConfig->nCol; i++){ + *pnToken += p->aTotalSize[i]; + } + }else if( iColpConfig->nCol ){ + *pnToken = p->aTotalSize[iCol]; + }else{ + rc = SQLITE_RANGE; + } + } + return rc; +} + +int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){ + int rc = fts5StorageLoadTotals(p, 0); + if( rc==SQLITE_OK ){ + *pnRow = p->nTotalRow; + } + return rc; +} + +/* +** Flush any data currently held in-memory to disk. +*/ +int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){ + if( bCommit && p->bTotalsValid ){ + int rc = fts5StorageSaveTotals(p); + p->bTotalsValid = 0; + if( rc!=SQLITE_OK ) return rc; + } + return sqlite3Fts5IndexSync(p->pIndex, bCommit); +} + +int sqlite3Fts5StorageRollback(Fts5Storage *p){ + p->bTotalsValid = 0; + return sqlite3Fts5IndexRollback(p->pIndex); +} + +int sqlite3Fts5StorageConfigValue( + Fts5Storage *p, + const char *z, + sqlite3_value *pVal, + int iVal +){ + sqlite3_stmt *pReplace = 0; + int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_CONFIG, &pReplace, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_text(pReplace, 1, z, -1, SQLITE_STATIC); + if( pVal ){ + sqlite3_bind_value(pReplace, 2, pVal); + }else{ + sqlite3_bind_int(pReplace, 2, iVal); + } + sqlite3_step(pReplace); + rc = sqlite3_reset(pReplace); + } + if( rc==SQLITE_OK && pVal ){ + int iNew = p->pConfig->iCookie + 1; + rc = sqlite3Fts5IndexSetCookie(p->pIndex, iNew); + if( rc==SQLITE_OK ){ + p->pConfig->iCookie = iNew; + } + } + return rc; +} + + diff --git a/ext/fts5/fts5_tcl.c b/ext/fts5/fts5_tcl.c new file mode 100644 index 0000000..72db657 --- /dev/null +++ b/ext/fts5/fts5_tcl.c @@ -0,0 +1,1150 @@ +/* +** 2014 Dec 01 +** +** 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. +** +****************************************************************************** +** +*/ + + +#ifdef SQLITE_TEST +#include + +#ifdef SQLITE_ENABLE_FTS5 + +#include "fts5.h" +#include +#include + +extern int sqlite3_fts5_may_be_corrupt; +extern int sqlite3Fts5TestRegisterMatchinfo(sqlite3*); +extern int sqlite3Fts5TestRegisterTok(sqlite3*, fts5_api*); + +/************************************************************************* +** This is a copy of the first part of the SqliteDb structure in +** tclsqlite.c. We need it here so that the get_sqlite_pointer routine +** can extract the sqlite3* pointer from an existing Tcl SQLite +** connection. +*/ + +extern const char *sqlite3ErrName(int); + +struct SqliteDb { + sqlite3 *db; +}; + +/* +** Decode a pointer to an sqlite3 object. +*/ +static int f5tDbPointer(Tcl_Interp *interp, Tcl_Obj *pObj, sqlite3 **ppDb){ + struct SqliteDb *p; + Tcl_CmdInfo cmdInfo; + char *z = Tcl_GetString(pObj); + if( Tcl_GetCommandInfo(interp, z, &cmdInfo) ){ + p = (struct SqliteDb*)cmdInfo.objClientData; + *ppDb = p->db; + return TCL_OK; + } + return TCL_ERROR; +} + +/* End of code that accesses the SqliteDb struct. +**************************************************************************/ + +static int f5tResultToErrorCode(const char *zRes){ + struct ErrorCode { + int rc; + const char *zError; + } aErr[] = { + { SQLITE_DONE, "SQLITE_DONE" }, + { SQLITE_ERROR, "SQLITE_ERROR" }, + { SQLITE_OK, "SQLITE_OK" }, + { SQLITE_OK, "" }, + }; + int i; + + for(i=0; ipScript); + int rc; + + Tcl_IncrRefCount(pEval); + Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zToken, nToken)); + Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(iStart)); + Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewIntObj(iEnd)); + + rc = Tcl_EvalObjEx(p->interp, pEval, 0); + Tcl_DecrRefCount(pEval); + if( rc==TCL_OK ){ + rc = f5tResultToErrorCode(Tcl_GetStringResult(p->interp)); + } + + return rc; +} + +static int xF5tApi(void*, Tcl_Interp*, int, Tcl_Obj *CONST []); + +static int xQueryPhraseCb( + const Fts5ExtensionApi *pApi, + Fts5Context *pFts, + void *pCtx +){ + F5tFunction *p = (F5tFunction*)pCtx; + static sqlite3_int64 iCmd = 0; + Tcl_Obj *pEval; + int rc; + + char zCmd[64]; + F5tApi sApi; + + sApi.pApi = pApi; + sApi.pFts = pFts; + sprintf(zCmd, "f5t_2_%lld", iCmd++); + Tcl_CreateObjCommand(p->interp, zCmd, xF5tApi, &sApi, 0); + + pEval = Tcl_DuplicateObj(p->pScript); + Tcl_IncrRefCount(pEval); + Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zCmd, -1)); + rc = Tcl_EvalObjEx(p->interp, pEval, 0); + Tcl_DecrRefCount(pEval); + Tcl_DeleteCommand(p->interp, zCmd); + + if( rc==TCL_OK ){ + rc = f5tResultToErrorCode(Tcl_GetStringResult(p->interp)); + } + + return rc; +} + +static void xSetAuxdataDestructor(void *p){ + F5tAuxData *pData = (F5tAuxData*)p; + Tcl_DecrRefCount(pData->pObj); + sqlite3_free(pData); +} + +/* +** api sub-command... +** +** Description... +*/ +static int xF5tApi( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + struct Sub { + const char *zName; + int nArg; + const char *zMsg; + } aSub[] = { + { "xColumnCount", 0, "" }, /* 0 */ + { "xRowCount", 0, "" }, /* 1 */ + { "xColumnTotalSize", 1, "COL" }, /* 2 */ + { "xTokenize", 2, "TEXT SCRIPT" }, /* 3 */ + { "xPhraseCount", 0, "" }, /* 4 */ + { "xPhraseSize", 1, "PHRASE" }, /* 5 */ + { "xInstCount", 0, "" }, /* 6 */ + { "xInst", 1, "IDX" }, /* 7 */ + { "xRowid", 0, "" }, /* 8 */ + { "xColumnText", 1, "COL" }, /* 9 */ + { "xColumnSize", 1, "COL" }, /* 10 */ + { "xQueryPhrase", 2, "PHRASE SCRIPT" }, /* 11 */ + { "xSetAuxdata", 1, "VALUE" }, /* 12 */ + { "xGetAuxdata", 1, "CLEAR" }, /* 13 */ + { "xSetAuxdataInt", 1, "INTEGER" }, /* 14 */ + { "xGetAuxdataInt", 1, "CLEAR" }, /* 15 */ + { "xPhraseForeach", 4, "IPHRASE COLVAR OFFVAR SCRIPT" }, /* 16 */ + { "xPhraseColumnForeach", 3, "IPHRASE COLVAR SCRIPT" }, /* 17 */ + { 0, 0, 0} + }; + + int rc; + int iSub = 0; + F5tApi *p = (F5tApi*)clientData; + + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND"); + return TCL_ERROR; + } + + rc = Tcl_GetIndexFromObjStruct( + interp, objv[1], aSub, sizeof(aSub[0]), "SUB-COMMAND", 0, &iSub + ); + if( rc!=TCL_OK ) return rc; + if( aSub[iSub].nArg!=objc-2 ){ + Tcl_WrongNumArgs(interp, 1, objv, aSub[iSub].zMsg); + return TCL_ERROR; + } + +#define CASE(i,str) case i: assert( strcmp(aSub[i].zName, str)==0 ); + switch( iSub ){ + CASE(0, "xColumnCount") { + int nCol; + nCol = p->pApi->xColumnCount(p->pFts); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(nCol)); + } + break; + } + CASE(1, "xRowCount") { + sqlite3_int64 nRow; + rc = p->pApi->xRowCount(p->pFts, &nRow); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nRow)); + } + break; + } + CASE(2, "xColumnTotalSize") { + int iCol; + sqlite3_int64 nSize; + if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ) return TCL_ERROR; + rc = p->pApi->xColumnTotalSize(p->pFts, iCol, &nSize); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize)); + } + break; + } + CASE(3, "xTokenize") { + int nText; + char *zText = Tcl_GetStringFromObj(objv[2], &nText); + F5tFunction ctx; + ctx.interp = interp; + ctx.pScript = objv[3]; + rc = p->pApi->xTokenize(p->pFts, zText, nText, &ctx, xTokenizeCb); + if( rc==SQLITE_OK ){ + Tcl_ResetResult(interp); + } + return rc; + } + CASE(4, "xPhraseCount") { + int nPhrase; + nPhrase = p->pApi->xPhraseCount(p->pFts); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(nPhrase)); + } + break; + } + CASE(5, "xPhraseSize") { + int iPhrase; + int sz; + if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ){ + return TCL_ERROR; + } + sz = p->pApi->xPhraseSize(p->pFts, iPhrase); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(sz)); + } + break; + } + CASE(6, "xInstCount") { + int nInst; + rc = p->pApi->xInstCount(p->pFts, &nInst); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(nInst)); + } + break; + } + CASE(7, "xInst") { + int iIdx, ip, ic, io; + if( Tcl_GetIntFromObj(interp, objv[2], &iIdx) ){ + return TCL_ERROR; + } + rc = p->pApi->xInst(p->pFts, iIdx, &ip, &ic, &io); + if( rc==SQLITE_OK ){ + Tcl_Obj *pList = Tcl_NewObj(); + Tcl_ListObjAppendElement(interp, pList, Tcl_NewIntObj(ip)); + Tcl_ListObjAppendElement(interp, pList, Tcl_NewIntObj(ic)); + Tcl_ListObjAppendElement(interp, pList, Tcl_NewIntObj(io)); + Tcl_SetObjResult(interp, pList); + } + break; + } + CASE(8, "xRowid") { + sqlite3_int64 iRowid = p->pApi->xRowid(p->pFts); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iRowid)); + break; + } + CASE(9, "xColumnText") { + const char *z = 0; + int n = 0; + int iCol; + if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ){ + return TCL_ERROR; + } + rc = p->pApi->xColumnText(p->pFts, iCol, &z, &n); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewStringObj(z, n)); + } + break; + } + CASE(10, "xColumnSize") { + int n = 0; + int iCol; + if( Tcl_GetIntFromObj(interp, objv[2], &iCol) ){ + return TCL_ERROR; + } + rc = p->pApi->xColumnSize(p->pFts, iCol, &n); + if( rc==SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewIntObj(n)); + } + break; + } + CASE(11, "xQueryPhrase") { + int iPhrase; + F5tFunction ctx; + if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ){ + return TCL_ERROR; + } + ctx.interp = interp; + ctx.pScript = objv[3]; + rc = p->pApi->xQueryPhrase(p->pFts, iPhrase, &ctx, xQueryPhraseCb); + if( rc==SQLITE_OK ){ + Tcl_ResetResult(interp); + } + break; + } + CASE(12, "xSetAuxdata") { + F5tAuxData *pData = (F5tAuxData*)sqlite3_malloc(sizeof(F5tAuxData)); + if( pData==0 ){ + Tcl_AppendResult(interp, "out of memory", 0); + return TCL_ERROR; + } + pData->pObj = objv[2]; + Tcl_IncrRefCount(pData->pObj); + rc = p->pApi->xSetAuxdata(p->pFts, pData, xSetAuxdataDestructor); + break; + } + CASE(13, "xGetAuxdata") { + F5tAuxData *pData; + int bClear; + if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ){ + return TCL_ERROR; + } + pData = (F5tAuxData*)p->pApi->xGetAuxdata(p->pFts, bClear); + if( pData==0 ){ + Tcl_ResetResult(interp); + }else{ + Tcl_SetObjResult(interp, pData->pObj); + if( bClear ){ + xSetAuxdataDestructor((void*)pData); + } + } + break; + } + + /* These two - xSetAuxdataInt and xGetAuxdataInt - are similar to the + ** xSetAuxdata and xGetAuxdata methods implemented above. The difference + ** is that they may only save an integer value as auxiliary data, and + ** do not specify a destructor function. */ + CASE(14, "xSetAuxdataInt") { + int iVal; + if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ) return TCL_ERROR; + rc = p->pApi->xSetAuxdata(p->pFts, (void*)((char*)0 + iVal), 0); + break; + } + CASE(15, "xGetAuxdataInt") { + int iVal; + int bClear; + if( Tcl_GetBooleanFromObj(interp, objv[2], &bClear) ) return TCL_ERROR; + iVal = ((char*)p->pApi->xGetAuxdata(p->pFts, bClear) - (char*)0); + Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); + break; + } + + CASE(16, "xPhraseForeach") { + int iPhrase; + int iCol; + int iOff; + const char *zColvar; + const char *zOffvar; + Tcl_Obj *pScript = objv[5]; + Fts5PhraseIter iter; + + if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ) return TCL_ERROR; + zColvar = Tcl_GetString(objv[3]); + zOffvar = Tcl_GetString(objv[4]); + + rc = p->pApi->xPhraseFirst(p->pFts, iPhrase, &iter, &iCol, &iOff); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); + return TCL_ERROR; + } + for( ;iCol>=0; p->pApi->xPhraseNext(p->pFts, &iter, &iCol, &iOff) ){ + Tcl_SetVar2Ex(interp, zColvar, 0, Tcl_NewIntObj(iCol), 0); + Tcl_SetVar2Ex(interp, zOffvar, 0, Tcl_NewIntObj(iOff), 0); + rc = Tcl_EvalObjEx(interp, pScript, 0); + if( rc==TCL_CONTINUE ) rc = TCL_OK; + if( rc!=TCL_OK ){ + if( rc==TCL_BREAK ) rc = TCL_OK; + break; + } + } + + break; + } + + CASE(17, "xPhraseColumnForeach") { + int iPhrase; + int iCol; + const char *zColvar; + Tcl_Obj *pScript = objv[4]; + Fts5PhraseIter iter; + + if( Tcl_GetIntFromObj(interp, objv[2], &iPhrase) ) return TCL_ERROR; + zColvar = Tcl_GetString(objv[3]); + + rc = p->pApi->xPhraseFirstColumn(p->pFts, iPhrase, &iter, &iCol); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); + return TCL_ERROR; + } + for( ; iCol>=0; p->pApi->xPhraseNextColumn(p->pFts, &iter, &iCol)){ + Tcl_SetVar2Ex(interp, zColvar, 0, Tcl_NewIntObj(iCol), 0); + rc = Tcl_EvalObjEx(interp, pScript, 0); + if( rc==TCL_CONTINUE ) rc = TCL_OK; + if( rc!=TCL_OK ){ + if( rc==TCL_BREAK ) rc = TCL_OK; + break; + } + } + + break; + } + + default: + assert( 0 ); + break; + } +#undef CASE + + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); + return TCL_ERROR; + } + + return TCL_OK; +} + +static void xF5tFunction( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning result/error */ + int nVal, /* Number of values in apVal[] array */ + sqlite3_value **apVal /* Array of trailing arguments */ +){ + F5tFunction *p = (F5tFunction*)pApi->xUserData(pFts); + Tcl_Obj *pEval; /* Script to evaluate */ + int i; + int rc; + + static sqlite3_int64 iCmd = 0; + char zCmd[64]; + F5tApi sApi; + sApi.pApi = pApi; + sApi.pFts = pFts; + + sprintf(zCmd, "f5t_%lld", iCmd++); + Tcl_CreateObjCommand(p->interp, zCmd, xF5tApi, &sApi, 0); + pEval = Tcl_DuplicateObj(p->pScript); + Tcl_IncrRefCount(pEval); + Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zCmd, -1)); + + for(i=0; iinterp, pEval, pObj); + } + + rc = Tcl_EvalObjEx(p->interp, pEval, TCL_GLOBAL_ONLY); + Tcl_DecrRefCount(pEval); + Tcl_DeleteCommand(p->interp, zCmd); + + if( rc!=TCL_OK ){ + sqlite3_result_error(pCtx, Tcl_GetStringResult(p->interp), -1); + }else{ + Tcl_Obj *pVar = Tcl_GetObjResult(p->interp); + int n; + const char *zType = (pVar->typePtr ? pVar->typePtr->name : ""); + char c = zType[0]; + if( c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0 ){ + /* Only return a BLOB type if the Tcl variable is a bytearray and + ** has no string representation. */ + unsigned char *data = Tcl_GetByteArrayFromObj(pVar, &n); + sqlite3_result_blob(pCtx, data, n, SQLITE_TRANSIENT); + }else if( c=='b' && strcmp(zType,"boolean")==0 ){ + Tcl_GetIntFromObj(0, pVar, &n); + sqlite3_result_int(pCtx, n); + }else if( c=='d' && strcmp(zType,"double")==0 ){ + double r; + Tcl_GetDoubleFromObj(0, pVar, &r); + sqlite3_result_double(pCtx, r); + }else if( (c=='w' && strcmp(zType,"wideInt")==0) || + (c=='i' && strcmp(zType,"int")==0) ){ + Tcl_WideInt v; + Tcl_GetWideIntFromObj(0, pVar, &v); + sqlite3_result_int64(pCtx, v); + }else{ + unsigned char *data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); + sqlite3_result_text(pCtx, (char *)data, n, SQLITE_TRANSIENT); + } + } +} + +static void xF5tDestroy(void *pCtx){ + F5tFunction *p = (F5tFunction*)pCtx; + Tcl_DecrRefCount(p->pScript); + ckfree((char *)p); +} + +/* +** sqlite3_fts5_create_function DB NAME SCRIPT +** +** Description... +*/ +static int f5tCreateFunction( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + char *zName; + Tcl_Obj *pScript; + sqlite3 *db = 0; + fts5_api *pApi = 0; + F5tFunction *pCtx = 0; + int rc; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB NAME SCRIPT"); + return TCL_ERROR; + } + if( f5tDbAndApi(interp, objv[1], &db, &pApi) ) return TCL_ERROR; + + zName = Tcl_GetString(objv[2]); + pScript = objv[3]; + pCtx = (F5tFunction*)ckalloc(sizeof(F5tFunction)); + pCtx->interp = interp; + pCtx->pScript = pScript; + Tcl_IncrRefCount(pScript); + + rc = pApi->xCreateFunction( + pApi, zName, (void*)pCtx, xF5tFunction, xF5tDestroy + ); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0); + return TCL_ERROR; + } + + return TCL_OK; +} + +typedef struct F5tTokenizeCtx F5tTokenizeCtx; +struct F5tTokenizeCtx { + Tcl_Obj *pRet; + int bSubst; + const char *zInput; +}; + +static int xTokenizeCb2( + void *pCtx, + int tflags, + const char *zToken, int nToken, + int iStart, int iEnd +){ + F5tTokenizeCtx *p = (F5tTokenizeCtx*)pCtx; + if( p->bSubst ){ + Tcl_ListObjAppendElement(0, p->pRet, Tcl_NewStringObj(zToken, nToken)); + Tcl_ListObjAppendElement( + 0, p->pRet, Tcl_NewStringObj(&p->zInput[iStart], iEnd-iStart) + ); + }else{ + Tcl_ListObjAppendElement(0, p->pRet, Tcl_NewStringObj(zToken, nToken)); + Tcl_ListObjAppendElement(0, p->pRet, Tcl_NewIntObj(iStart)); + Tcl_ListObjAppendElement(0, p->pRet, Tcl_NewIntObj(iEnd)); + } + return SQLITE_OK; +} + + +/* +** sqlite3_fts5_tokenize DB TOKENIZER TEXT +** +** Description... +*/ +static int f5tTokenize( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + char *zText; + int nText; + sqlite3 *db = 0; + fts5_api *pApi = 0; + Fts5Tokenizer *pTok = 0; + fts5_tokenizer tokenizer; + Tcl_Obj *pRet = 0; + void *pUserdata; + int rc; + + int nArg; + const char **azArg; + F5tTokenizeCtx ctx; + + if( objc!=4 && objc!=5 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?-subst? DB NAME TEXT"); + return TCL_ERROR; + } + if( objc==5 ){ + char *zOpt = Tcl_GetString(objv[1]); + if( strcmp("-subst", zOpt) ){ + Tcl_AppendResult(interp, "unrecognized option: ", zOpt, 0); + return TCL_ERROR; + } + } + if( f5tDbAndApi(interp, objv[objc-3], &db, &pApi) ) return TCL_ERROR; + if( Tcl_SplitList(interp, Tcl_GetString(objv[objc-2]), &nArg, &azArg) ){ + return TCL_ERROR; + } + if( nArg==0 ){ + Tcl_AppendResult(interp, "no such tokenizer: ", 0); + Tcl_Free((void*)azArg); + return TCL_ERROR; + } + zText = Tcl_GetStringFromObj(objv[objc-1], &nText); + + rc = pApi->xFindTokenizer(pApi, azArg[0], &pUserdata, &tokenizer); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, "no such tokenizer: ", azArg[0], 0); + return TCL_ERROR; + } + + rc = tokenizer.xCreate(pUserdata, &azArg[1], nArg-1, &pTok); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, "error in tokenizer.xCreate()", 0); + return TCL_ERROR; + } + + pRet = Tcl_NewObj(); + Tcl_IncrRefCount(pRet); + ctx.bSubst = (objc==5); + ctx.pRet = pRet; + ctx.zInput = zText; + rc = tokenizer.xTokenize( + pTok, (void*)&ctx, FTS5_TOKENIZE_DOCUMENT, zText, nText, xTokenizeCb2 + ); + tokenizer.xDelete(pTok); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, "error in tokenizer.xTokenize()", 0); + Tcl_DecrRefCount(pRet); + return TCL_ERROR; + } + + + Tcl_Free((void*)azArg); + Tcl_SetObjResult(interp, pRet); + Tcl_DecrRefCount(pRet); + return TCL_OK; +} + +/************************************************************************* +** Start of tokenizer wrapper. +*/ + +typedef struct F5tTokenizerContext F5tTokenizerContext; +typedef struct F5tTokenizerCb F5tTokenizerCb; +typedef struct F5tTokenizerModule F5tTokenizerModule; +typedef struct F5tTokenizerInstance F5tTokenizerInstance; + +struct F5tTokenizerContext { + void *pCtx; + int (*xToken)(void*, int, const char*, int, int, int); +}; + +struct F5tTokenizerModule { + Tcl_Interp *interp; + Tcl_Obj *pScript; + F5tTokenizerContext *pContext; +}; + +struct F5tTokenizerInstance { + Tcl_Interp *interp; + Tcl_Obj *pScript; + F5tTokenizerContext *pContext; +}; + +static int f5tTokenizerCreate( + void *pCtx, + const char **azArg, + int nArg, + Fts5Tokenizer **ppOut +){ + F5tTokenizerModule *pMod = (F5tTokenizerModule*)pCtx; + Tcl_Obj *pEval; + int rc = TCL_OK; + int i; + + pEval = Tcl_DuplicateObj(pMod->pScript); + Tcl_IncrRefCount(pEval); + for(i=0; rc==TCL_OK && iinterp, pEval, pObj); + } + + if( rc==TCL_OK ){ + rc = Tcl_EvalObjEx(pMod->interp, pEval, TCL_GLOBAL_ONLY); + } + Tcl_DecrRefCount(pEval); + + if( rc==TCL_OK ){ + F5tTokenizerInstance *pInst; + pInst = (F5tTokenizerInstance*)ckalloc(sizeof(F5tTokenizerInstance)); + memset(pInst, 0, sizeof(F5tTokenizerInstance)); + pInst->interp = pMod->interp; + pInst->pScript = Tcl_GetObjResult(pMod->interp); + pInst->pContext = pMod->pContext; + Tcl_IncrRefCount(pInst->pScript); + *ppOut = (Fts5Tokenizer*)pInst; + } + + return rc; +} + + +static void f5tTokenizerDelete(Fts5Tokenizer *p){ + F5tTokenizerInstance *pInst = (F5tTokenizerInstance*)p; + Tcl_DecrRefCount(pInst->pScript); + ckfree((char *)pInst); +} + +static int f5tTokenizerTokenize( + Fts5Tokenizer *p, + void *pCtx, + int flags, + const char *pText, int nText, + int (*xToken)(void*, int, const char*, int, int, int) +){ + F5tTokenizerInstance *pInst = (F5tTokenizerInstance*)p; + void *pOldCtx; + int (*xOldToken)(void*, int, const char*, int, int, int); + Tcl_Obj *pEval; + int rc; + const char *zFlags; + + pOldCtx = pInst->pContext->pCtx; + xOldToken = pInst->pContext->xToken; + + pInst->pContext->pCtx = pCtx; + pInst->pContext->xToken = xToken; + + assert( + flags==FTS5_TOKENIZE_DOCUMENT + || flags==FTS5_TOKENIZE_AUX + || flags==FTS5_TOKENIZE_QUERY + || flags==(FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX) + ); + pEval = Tcl_DuplicateObj(pInst->pScript); + Tcl_IncrRefCount(pEval); + switch( flags ){ + case FTS5_TOKENIZE_DOCUMENT: + zFlags = "document"; + break; + case FTS5_TOKENIZE_AUX: + zFlags = "aux"; + break; + case FTS5_TOKENIZE_QUERY: + zFlags = "query"; + break; + case (FTS5_TOKENIZE_PREFIX | FTS5_TOKENIZE_QUERY): + zFlags = "prefixquery"; + break; + default: + assert( 0 ); + zFlags = "invalid"; + break; + } + + Tcl_ListObjAppendElement(pInst->interp, pEval, Tcl_NewStringObj(zFlags, -1)); + Tcl_ListObjAppendElement(pInst->interp, pEval, Tcl_NewStringObj(pText,nText)); + rc = Tcl_EvalObjEx(pInst->interp, pEval, TCL_GLOBAL_ONLY); + Tcl_DecrRefCount(pEval); + + pInst->pContext->pCtx = pOldCtx; + pInst->pContext->xToken = xOldToken; + return rc; +} + +/* +** sqlite3_fts5_token ?-colocated? TEXT START END +*/ +static int f5tTokenizerReturn( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + F5tTokenizerContext *p = (F5tTokenizerContext*)clientData; + int iStart; + int iEnd; + int nToken; + int tflags = 0; + char *zToken; + int rc; + + if( objc==5 ){ + int nArg; + char *zArg = Tcl_GetStringFromObj(objv[1], &nArg); + if( nArg<=10 && nArg>=2 && memcmp("-colocated", zArg, nArg)==0 ){ + tflags |= FTS5_TOKEN_COLOCATED; + }else{ + goto usage; + } + }else if( objc!=4 ){ + goto usage; + } + + zToken = Tcl_GetStringFromObj(objv[objc-3], &nToken); + if( Tcl_GetIntFromObj(interp, objv[objc-2], &iStart) + || Tcl_GetIntFromObj(interp, objv[objc-1], &iEnd) + ){ + return TCL_ERROR; + } + + if( p->xToken==0 ){ + Tcl_AppendResult(interp, + "sqlite3_fts5_token may only be used by tokenizer callback", 0 + ); + return TCL_ERROR; + } + + rc = p->xToken(p->pCtx, tflags, zToken, nToken, iStart, iEnd); + Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); + return TCL_OK; + + usage: + Tcl_WrongNumArgs(interp, 1, objv, "?-colocated? TEXT START END"); + return TCL_ERROR; +} + +static void f5tDelTokenizer(void *pCtx){ + F5tTokenizerModule *pMod = (F5tTokenizerModule*)pCtx; + Tcl_DecrRefCount(pMod->pScript); + ckfree((char *)pMod); +} + +/* +** sqlite3_fts5_create_tokenizer DB NAME SCRIPT +** +** Register a tokenizer named NAME implemented by script SCRIPT. When +** a tokenizer instance is created (fts5_tokenizer.xCreate), any tokenizer +** arguments are appended to SCRIPT and the result executed. +** +** The value returned by (SCRIPT + args) is itself a tcl script. This +** script - call it SCRIPT2 - is executed to tokenize text using the +** tokenizer instance "returned" by SCRIPT. Specifically, to tokenize +** text SCRIPT2 is invoked with a single argument appended to it - the +** text to tokenize. +** +** SCRIPT2 should invoke the [sqlite3_fts5_token] command once for each +** token within the tokenized text. +*/ +static int f5tCreateTokenizer( + ClientData clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + F5tTokenizerContext *pContext = (F5tTokenizerContext*)clientData; + sqlite3 *db; + fts5_api *pApi; + char *zName; + Tcl_Obj *pScript; + fts5_tokenizer t; + F5tTokenizerModule *pMod; + int rc; + + if( objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB NAME SCRIPT"); + return TCL_ERROR; + } + if( f5tDbAndApi(interp, objv[1], &db, &pApi) ){ + return TCL_ERROR; + } + zName = Tcl_GetString(objv[2]); + pScript = objv[3]; + + t.xCreate = f5tTokenizerCreate; + t.xTokenize = f5tTokenizerTokenize; + t.xDelete = f5tTokenizerDelete; + + pMod = (F5tTokenizerModule*)ckalloc(sizeof(F5tTokenizerModule)); + pMod->interp = interp; + pMod->pScript = pScript; + pMod->pContext = pContext; + Tcl_IncrRefCount(pScript); + rc = pApi->xCreateTokenizer(pApi, zName, (void*)pMod, &t, f5tDelTokenizer); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, "error in fts5_api.xCreateTokenizer()", 0); + return TCL_ERROR; + } + + return TCL_OK; +} + +static void xF5tFree(ClientData clientData){ + ckfree(clientData); +} + +/* +** sqlite3_fts5_may_be_corrupt BOOLEAN +** +** Set or clear the global "may-be-corrupt" flag. Return the old value. +*/ +static int f5tMayBeCorrupt( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int bOld = sqlite3_fts5_may_be_corrupt; + + if( objc!=2 && objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?"); + return TCL_ERROR; + } + if( objc==2 ){ + int bNew; + if( Tcl_GetBooleanFromObj(interp, objv[1], &bNew) ) return TCL_ERROR; + sqlite3_fts5_may_be_corrupt = bNew; + } + + Tcl_SetObjResult(interp, Tcl_NewIntObj(bOld)); + return TCL_OK; +} + + +static unsigned int f5t_fts5HashKey(int nSlot, const char *p, int n){ + int i; + unsigned int h = 13; + for(i=n-1; i>=0; i--){ + h = (h << 3) ^ h ^ p[i]; + } + return (h % nSlot); +} + +static int f5tTokenHash( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + char *z; + int n; + unsigned int iVal; + int nSlot; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "NSLOT TOKEN"); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[1], &nSlot) ){ + return TCL_ERROR; + } + z = Tcl_GetStringFromObj(objv[2], &n); + + iVal = f5t_fts5HashKey(nSlot, z, n); + Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); + return TCL_OK; +} + +static int f5tRegisterMatchinfo( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + sqlite3 *db = 0; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( f5tDbPointer(interp, objv[1], &db) ){ + return TCL_ERROR; + } + + rc = sqlite3Fts5TestRegisterMatchinfo(db); + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); + return TCL_ERROR; + } + return TCL_OK; +} + +static int f5tRegisterTok( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc; + sqlite3 *db = 0; + fts5_api *pApi = 0; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "DB"); + return TCL_ERROR; + } + if( f5tDbAndApi(interp, objv[1], &db, &pApi) ){ + return TCL_ERROR; + } + + rc = sqlite3Fts5TestRegisterTok(db, pApi); + if( rc!=SQLITE_OK ){ + Tcl_SetResult(interp, (char*)sqlite3ErrName(rc), TCL_VOLATILE); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Entry point. +*/ +int Fts5tcl_Init(Tcl_Interp *interp){ + static struct Cmd { + char *zName; + Tcl_ObjCmdProc *xProc; + int bTokenizeCtx; + } aCmd[] = { + { "sqlite3_fts5_create_tokenizer", f5tCreateTokenizer, 1 }, + { "sqlite3_fts5_token", f5tTokenizerReturn, 1 }, + { "sqlite3_fts5_tokenize", f5tTokenize, 0 }, + { "sqlite3_fts5_create_function", f5tCreateFunction, 0 }, + { "sqlite3_fts5_may_be_corrupt", f5tMayBeCorrupt, 0 }, + { "sqlite3_fts5_token_hash", f5tTokenHash, 0 }, + { "sqlite3_fts5_register_matchinfo", f5tRegisterMatchinfo, 0 }, + { "sqlite3_fts5_register_fts5tokenize", f5tRegisterTok, 0 } + }; + int i; + F5tTokenizerContext *pContext; + + pContext = (F5tTokenizerContext*)ckalloc(sizeof(F5tTokenizerContext)); + memset(pContext, 0, sizeof(*pContext)); + + for(i=0; ibTokenizeCtx ) pCtx = (void*)pContext; + Tcl_CreateObjCommand(interp, p->zName, p->xProc, pCtx, (i ? 0 : xF5tFree)); + } + + return TCL_OK; +} +#else /* SQLITE_ENABLE_FTS5 */ +int Fts5tcl_Init(Tcl_Interp *interp){ + return TCL_OK; +} +#endif /* SQLITE_ENABLE_FTS5 */ +#endif /* SQLITE_TEST */ diff --git a/ext/fts5/fts5_test_mi.c b/ext/fts5/fts5_test_mi.c new file mode 100644 index 0000000..2833177 --- /dev/null +++ b/ext/fts5/fts5_test_mi.c @@ -0,0 +1,424 @@ +/* +** 2015 Aug 04 +** +** 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 contains test code only, it is not included in release +** versions of FTS5. It contains the implementation of an FTS5 auxiliary +** function very similar to the FTS4 function matchinfo(): +** +** https://www.sqlite.org/fts3.html#matchinfo +** +** Known differences are that: +** +** 1) this function uses the FTS5 definition of "matchable phrase", which +** excludes any phrases that are part of an expression sub-tree that +** does not match the current row. This comes up for MATCH queries +** such as: +** +** "a OR (b AND c)" +** +** In FTS4, if a single row contains instances of tokens "a" and "c", +** but not "b", all instances of "c" are considered matches. In FTS5, +** they are not (as the "b AND c" sub-tree does not match the current +** row. +** +** 2) For the values returned by 'x' that apply to all rows of the table, +** NEAR constraints are not considered. But for the number of hits in +** the current row, they are. +** +** This file exports a single function that may be called to register the +** matchinfo() implementation with a database handle: +** +** int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db); +*/ + + +#ifdef SQLITE_TEST +#ifdef SQLITE_ENABLE_FTS5 + +#include "fts5.h" +#include +#include +#include + +typedef struct Fts5MatchinfoCtx Fts5MatchinfoCtx; +typedef unsigned int u32; + +struct Fts5MatchinfoCtx { + int nCol; /* Number of cols in FTS5 table */ + int nPhrase; /* Number of phrases in FTS5 query */ + char *zArg; /* nul-term'd copy of 2nd arg */ + int nRet; /* Number of elements in aRet[] */ + u32 *aRet; /* Array of 32-bit unsigned ints to return */ +}; + + + +/* +** Return a pointer to the fts5_api pointer for database connection db. +** If an error occurs, return NULL and leave an error in the database +** handle (accessible using sqlite3_errcode()/errmsg()). +*/ +static fts5_api *fts5_api_from_db(sqlite3 *db){ + fts5_api *pRet = 0; + sqlite3_stmt *pStmt = 0; + + if( SQLITE_OK==sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0) + && SQLITE_ROW==sqlite3_step(pStmt) + && sizeof(pRet)==sqlite3_column_bytes(pStmt, 0) + ){ + memcpy(&pRet, sqlite3_column_blob(pStmt, 0), sizeof(pRet)); + } + sqlite3_finalize(pStmt); + return pRet; +} + + +/* +** Argument f should be a flag accepted by matchinfo() (a valid character +** in the string passed as the second argument). If it is not, -1 is +** returned. Otherwise, if f is a valid matchinfo flag, the value returned +** is the number of 32-bit integers added to the output array if the +** table has nCol columns and the query nPhrase phrases. +*/ +static int fts5MatchinfoFlagsize(int nCol, int nPhrase, char f){ + int ret = -1; + switch( f ){ + case 'p': ret = 1; break; + case 'c': ret = 1; break; + case 'x': ret = 3 * nCol * nPhrase; break; + case 'y': ret = nCol * nPhrase; break; + case 'b': ret = ((nCol + 31) / 32) * nPhrase; break; + case 'n': ret = 1; break; + case 'a': ret = nCol; break; + case 'l': ret = nCol; break; + case 's': ret = nCol; break; + } + return ret; +} + +static int fts5MatchinfoIter( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + Fts5MatchinfoCtx *p, + int(*x)(const Fts5ExtensionApi*,Fts5Context*,Fts5MatchinfoCtx*,char,u32*) +){ + int i; + int n = 0; + int rc = SQLITE_OK; + char f; + for(i=0; (f = p->zArg[i]); i++){ + rc = x(pApi, pFts, p, f, &p->aRet[n]); + if( rc!=SQLITE_OK ) break; + n += fts5MatchinfoFlagsize(p->nCol, p->nPhrase, f); + } + return rc; +} + +static int fts5MatchinfoXCb( + const Fts5ExtensionApi *pApi, + Fts5Context *pFts, + void *pUserData +){ + Fts5PhraseIter iter; + int iCol, iOff; + u32 *aOut = (u32*)pUserData; + int iPrev = -1; + + for(pApi->xPhraseFirst(pFts, 0, &iter, &iCol, &iOff); + iCol>=0; + pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) + ){ + aOut[iCol*3+1]++; + if( iCol!=iPrev ) aOut[iCol*3 + 2]++; + iPrev = iCol; + } + + return SQLITE_OK; +} + +static int fts5MatchinfoGlobalCb( + const Fts5ExtensionApi *pApi, + Fts5Context *pFts, + Fts5MatchinfoCtx *p, + char f, + u32 *aOut +){ + int rc = SQLITE_OK; + switch( f ){ + case 'p': + aOut[0] = p->nPhrase; + break; + + case 'c': + aOut[0] = p->nCol; + break; + + case 'x': { + int i; + for(i=0; inPhrase && rc==SQLITE_OK; i++){ + void *pPtr = (void*)&aOut[i * p->nCol * 3]; + rc = pApi->xQueryPhrase(pFts, i, pPtr, fts5MatchinfoXCb); + } + break; + } + + case 'n': { + sqlite3_int64 nRow; + rc = pApi->xRowCount(pFts, &nRow); + aOut[0] = (u32)nRow; + break; + } + + case 'a': { + sqlite3_int64 nRow = 0; + rc = pApi->xRowCount(pFts, &nRow); + if( nRow==0 ){ + memset(aOut, 0, sizeof(u32) * p->nCol); + }else{ + int i; + for(i=0; rc==SQLITE_OK && inCol; i++){ + sqlite3_int64 nToken; + rc = pApi->xColumnTotalSize(pFts, i, &nToken); + if( rc==SQLITE_OK){ + aOut[i] = (u32)((2*nToken + nRow) / (2*nRow)); + } + } + } + break; + } + + } + return rc; +} + +static int fts5MatchinfoLocalCb( + const Fts5ExtensionApi *pApi, + Fts5Context *pFts, + Fts5MatchinfoCtx *p, + char f, + u32 *aOut +){ + int i; + int rc = SQLITE_OK; + + switch( f ){ + case 'b': { + int iPhrase; + int nInt = ((p->nCol + 31) / 32) * p->nPhrase; + for(i=0; inPhrase; iPhrase++){ + Fts5PhraseIter iter; + int iCol; + for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol); + iCol>=0; + pApi->xPhraseNextColumn(pFts, &iter, &iCol) + ){ + aOut[iPhrase * ((p->nCol+31)/32) + iCol/32] |= ((u32)1 << iCol%32); + } + } + + break; + } + + case 'x': + case 'y': { + int nMul = (f=='x' ? 3 : 1); + int iPhrase; + + for(i=0; i<(p->nCol*p->nPhrase); i++) aOut[i*nMul] = 0; + + for(iPhrase=0; iPhrasenPhrase; iPhrase++){ + Fts5PhraseIter iter; + int iOff, iCol; + for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); + iOff>=0; + pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) + ){ + if( f=='b' ){ + aOut[iPhrase * ((p->nCol+31)/32) + iCol/32] |= ((u32)1 << iCol%32); + }else{ + aOut[nMul * (iCol + iPhrase * p->nCol)]++; + } + } + } + + break; + } + + case 'l': { + for(i=0; rc==SQLITE_OK && inCol; i++){ + int nToken; + rc = pApi->xColumnSize(pFts, i, &nToken); + aOut[i] = (u32)nToken; + } + break; + } + + case 's': { + int nInst; + + memset(aOut, 0, sizeof(u32) * p->nCol); + + rc = pApi->xInstCount(pFts, &nInst); + for(i=0; rc==SQLITE_OK && ixInst(pFts, i, &iPhrase, &iCol, &iOff); + iNextPhrase = iPhrase+1; + iNextOff = iOff+pApi->xPhraseSize(pFts, 0); + for(j=i+1; rc==SQLITE_OK && jxInst(pFts, j, &ip, &ic, &io); + if( ic!=iCol || io>iNextOff ) break; + if( ip==iNextPhrase && io==iNextOff ){ + nSeq++; + iNextPhrase = ip+1; + iNextOff = io + pApi->xPhraseSize(pFts, ip); + } + } + + if( nSeq>aOut[iCol] ) aOut[iCol] = nSeq; + } + + break; + } + } + return rc; +} + +static Fts5MatchinfoCtx *fts5MatchinfoNew( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning error message */ + const char *zArg /* Matchinfo flag string */ +){ + Fts5MatchinfoCtx *p; + int nCol; + int nPhrase; + int i; + int nInt; + int nByte; + int rc; + + nCol = pApi->xColumnCount(pFts); + nPhrase = pApi->xPhraseCount(pFts); + + nInt = 0; + for(i=0; zArg[i]; i++){ + int n = fts5MatchinfoFlagsize(nCol, nPhrase, zArg[i]); + if( n<0 ){ + char *zErr = sqlite3_mprintf("unrecognized matchinfo flag: %c", zArg[i]); + sqlite3_result_error(pCtx, zErr, -1); + sqlite3_free(zErr); + return 0; + } + nInt += n; + } + + nByte = sizeof(Fts5MatchinfoCtx) /* The struct itself */ + + sizeof(u32) * nInt /* The p->aRet[] array */ + + (i+1); /* The p->zArg string */ + p = (Fts5MatchinfoCtx*)sqlite3_malloc(nByte); + if( p==0 ){ + sqlite3_result_error_nomem(pCtx); + return 0; + } + memset(p, 0, nByte); + + p->nCol = nCol; + p->nPhrase = nPhrase; + p->aRet = (u32*)&p[1]; + p->nRet = nInt; + p->zArg = (char*)&p->aRet[nInt]; + memcpy(p->zArg, zArg, i); + + rc = fts5MatchinfoIter(pApi, pFts, p, fts5MatchinfoGlobalCb); + if( rc!=SQLITE_OK ){ + sqlite3_result_error_code(pCtx, rc); + sqlite3_free(p); + p = 0; + } + + return p; +} + +static void fts5MatchinfoFunc( + const Fts5ExtensionApi *pApi, /* API offered by current FTS version */ + Fts5Context *pFts, /* First arg to pass to pApi functions */ + sqlite3_context *pCtx, /* Context for returning result/error */ + int nVal, /* Number of values in apVal[] array */ + sqlite3_value **apVal /* Array of trailing arguments */ +){ + const char *zArg; + Fts5MatchinfoCtx *p; + int rc = SQLITE_OK; + + if( nVal>0 ){ + zArg = (const char*)sqlite3_value_text(apVal[0]); + }else{ + zArg = "pcx"; + } + + p = (Fts5MatchinfoCtx*)pApi->xGetAuxdata(pFts, 0); + if( p==0 || sqlite3_stricmp(zArg, p->zArg) ){ + p = fts5MatchinfoNew(pApi, pFts, pCtx, zArg); + if( p==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = pApi->xSetAuxdata(pFts, p, sqlite3_free); + } + } + + if( rc==SQLITE_OK ){ + rc = fts5MatchinfoIter(pApi, pFts, p, fts5MatchinfoLocalCb); + } + if( rc!=SQLITE_OK ){ + sqlite3_result_error_code(pCtx, rc); + }else{ + /* No errors has occured, so return a copy of the array of integers. */ + int nByte = p->nRet * sizeof(u32); + sqlite3_result_blob(pCtx, (void*)p->aRet, nByte, SQLITE_TRANSIENT); + } +} + +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. */ + pApi = fts5_api_from_db(db); + + /* 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. + */ + if( pApi==0 || pApi->iVersion<1 ){ + return SQLITE_ERROR; + } + + /* Register the implementation of matchinfo() */ + rc = pApi->xCreateFunction(pApi, "matchinfo", 0, fts5MatchinfoFunc, 0); + + return rc; +} + +#endif /* SQLITE_ENABLE_FTS5 */ +#endif /* SQLITE_TEST */ + diff --git a/ext/fts5/fts5_test_tok.c b/ext/fts5/fts5_test_tok.c new file mode 100644 index 0000000..10af126 --- /dev/null +++ b/ext/fts5/fts5_test_tok.c @@ -0,0 +1,482 @@ +/* +** 2013 Apr 22 +** +** 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 contains code for the "fts5tokenize" virtual table module. +** An fts5tokenize virtual table is created as follows: +** +** CREATE VIRTUAL TABLE USING fts5tokenize( +** , , ... +** ); +** +** The table created has the following schema: +** +** CREATE TABLE (input HIDDEN, token, start, end, position) +** +** When queried, the query must include a WHERE clause of type: +** +** input = +** +** The virtual table module tokenizes this , using the FTS3 +** tokenizer specified by the arguments to the CREATE VIRTUAL TABLE +** statement and returns one row for each token in the result. With +** fields set as follows: +** +** input: Always set to a copy of +** token: A token from the input. +** start: Byte offset of the token within the input . +** end: Byte offset of the byte immediately following the end of the +** token within the input string. +** pos: Token offset of token within input. +** +*/ +#if defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5) + +#include +#include +#include + +typedef struct Fts5tokTable Fts5tokTable; +typedef struct Fts5tokCursor Fts5tokCursor; +typedef struct Fts5tokRow Fts5tokRow; + +/* +** Virtual table structure. +*/ +struct Fts5tokTable { + sqlite3_vtab base; /* Base class used by SQLite core */ + fts5_tokenizer tok; /* Tokenizer functions */ + Fts5Tokenizer *pTok; /* Tokenizer instance */ +}; + +/* +** A container for a rows values. +*/ +struct Fts5tokRow { + char *zToken; + int iStart; + int iEnd; + int iPos; +}; + +/* +** Virtual table cursor structure. +*/ +struct Fts5tokCursor { + sqlite3_vtab_cursor base; /* Base class used by SQLite core */ + int iRowid; /* Current 'rowid' value */ + char *zInput; /* Input string */ + int nRow; /* Number of entries in aRow[] */ + Fts5tokRow *aRow; /* Array of rows to return */ +}; + +static void fts5tokDequote(char *z){ + char q = z[0]; + + if( q=='[' || q=='\'' || q=='"' || q=='`' ){ + int iIn = 1; + int iOut = 0; + if( q=='[' ) q = ']'; + + while( z[iIn] ){ + if( z[iIn]==q ){ + if( z[iIn+1]!=q ){ + /* Character iIn was the close quote. */ + iIn++; + break; + }else{ + /* Character iIn and iIn+1 form an escaped quote character. Skip + ** the input cursor past both and copy a single quote character + ** to the output buffer. */ + iIn += 2; + z[iOut++] = q; + } + }else{ + z[iOut++] = z[iIn++]; + } + } + + z[iOut] = '\0'; + } +} + +/* +** The second argument, argv[], is an array of pointers to nul-terminated +** strings. This function makes a copy of the array and strings into a +** single block of memory. It then dequotes any of the strings that appear +** to be quoted. +** +** If successful, output parameter *pazDequote is set to point at the +** array of dequoted strings and SQLITE_OK is returned. The caller is +** responsible for eventually calling sqlite3_free() to free the array +** in this case. Or, if an error occurs, an SQLite error code is returned. +** The final value of *pazDequote is undefined in this case. +*/ +static int fts5tokDequoteArray( + int argc, /* Number of elements in argv[] */ + const char * const *argv, /* Input array */ + char ***pazDequote /* Output array */ +){ + int rc = SQLITE_OK; /* Return code */ + if( argc==0 ){ + *pazDequote = 0; + }else{ + int i; + int nByte = 0; + char **azDequote; + + for(i=0; i0 ){ + zModule = azDequote[0]; + } + + rc = pApi->xFindTokenizer(pApi, zModule, &pTokCtx, &pTab->tok); + if( rc==SQLITE_OK ){ + const char **azArg = (const char **)&azDequote[1]; + int nArg = nDequote>0 ? nDequote-1 : 0; + rc = pTab->tok.xCreate(pTokCtx, azArg, nArg, &pTab->pTok); + } + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(pTab); + pTab = 0; + } + + *ppVtab = (sqlite3_vtab*)pTab; + sqlite3_free(azDequote); + return rc; +} + +/* +** This function does the work for both the xDisconnect and xDestroy methods. +** These tables have no persistent representation of their own, so xDisconnect +** and xDestroy are identical operations. +*/ +static int fts5tokDisconnectMethod(sqlite3_vtab *pVtab){ + Fts5tokTable *pTab = (Fts5tokTable *)pVtab; + if( pTab->pTok ){ + pTab->tok.xDelete(pTab->pTok); + } + sqlite3_free(pTab); + return SQLITE_OK; +} + +/* +** xBestIndex - Analyze a WHERE and ORDER BY clause. +*/ +static int fts5tokBestIndexMethod( + sqlite3_vtab *pVTab, + sqlite3_index_info *pInfo +){ + int i; + + for(i=0; inConstraint; i++){ + if( pInfo->aConstraint[i].usable + && pInfo->aConstraint[i].iColumn==0 + && pInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ + ){ + pInfo->idxNum = 1; + pInfo->aConstraintUsage[i].argvIndex = 1; + pInfo->aConstraintUsage[i].omit = 1; + pInfo->estimatedCost = 1; + return SQLITE_OK; + } + } + + pInfo->idxNum = 0; + assert( pInfo->estimatedCost>1000000.0 ); + + return SQLITE_OK; +} + +/* +** xOpen - Open a cursor. +*/ +static int fts5tokOpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ + Fts5tokCursor *pCsr; + + pCsr = (Fts5tokCursor *)sqlite3_malloc(sizeof(Fts5tokCursor)); + if( pCsr==0 ){ + return SQLITE_NOMEM; + } + memset(pCsr, 0, sizeof(Fts5tokCursor)); + + *ppCsr = (sqlite3_vtab_cursor *)pCsr; + return SQLITE_OK; +} + +/* +** Reset the tokenizer cursor passed as the only argument. As if it had +** just been returned by fts5tokOpenMethod(). +*/ +static void fts5tokResetCursor(Fts5tokCursor *pCsr){ + int i; + for(i=0; inRow; i++){ + sqlite3_free(pCsr->aRow[i].zToken); + } + sqlite3_free(pCsr->zInput); + sqlite3_free(pCsr->aRow); + pCsr->zInput = 0; + pCsr->aRow = 0; + pCsr->nRow = 0; + pCsr->iRowid = 0; +} + +/* +** xClose - Close a cursor. +*/ +static int fts5tokCloseMethod(sqlite3_vtab_cursor *pCursor){ + Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor; + fts5tokResetCursor(pCsr); + sqlite3_free(pCsr); + return SQLITE_OK; +} + +/* +** xNext - Advance the cursor to the next row, if any. +*/ +static int fts5tokNextMethod(sqlite3_vtab_cursor *pCursor){ + Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor; + pCsr->iRowid++; + return SQLITE_OK; +} + +static int fts5tokCb( + void *pCtx, /* Pointer to Fts5tokCursor */ + int tflags, /* Mask of FTS5_TOKEN_* flags */ + const char *pToken, /* Pointer to buffer containing token */ + int nToken, /* Size of token in bytes */ + int iStart, /* Byte offset of token within input text */ + int iEnd /* Byte offset of end of token within input text */ +){ + Fts5tokCursor *pCsr = (Fts5tokCursor*)pCtx; + Fts5tokRow *pRow; + + if( (pCsr->nRow & (pCsr->nRow-1))==0 ){ + int nNew = pCsr->nRow ? pCsr->nRow*2 : 32; + Fts5tokRow *aNew; + aNew = (Fts5tokRow*)sqlite3_realloc(pCsr->aRow, nNew*sizeof(Fts5tokRow)); + if( aNew==0 ) return SQLITE_NOMEM; + memset(&aNew[pCsr->nRow], 0, sizeof(Fts5tokRow)*(nNew-pCsr->nRow)); + pCsr->aRow = aNew; + } + + pRow = &pCsr->aRow[pCsr->nRow]; + pRow->iStart = iStart; + pRow->iEnd = iEnd; + if( pCsr->nRow ){ + pRow->iPos = pRow[-1].iPos + ((tflags & FTS5_TOKEN_COLOCATED) ? 0 : 1); + } + pRow->zToken = sqlite3_malloc(nToken+1); + if( pRow->zToken==0 ) return SQLITE_NOMEM; + memcpy(pRow->zToken, pToken, nToken); + pRow->zToken[nToken] = 0; + pCsr->nRow++; + + return SQLITE_OK; +} + +/* +** xFilter - Initialize a cursor to point at the start of its data. +*/ +static int fts5tokFilterMethod( + sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ + int idxNum, /* Strategy index */ + const char *idxStr, /* Unused */ + int nVal, /* Number of elements in apVal */ + sqlite3_value **apVal /* Arguments for the indexing scheme */ +){ + int rc = SQLITE_ERROR; + Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor; + Fts5tokTable *pTab = (Fts5tokTable *)(pCursor->pVtab); + + fts5tokResetCursor(pCsr); + if( idxNum==1 ){ + const char *zByte = (const char *)sqlite3_value_text(apVal[0]); + int nByte = sqlite3_value_bytes(apVal[0]); + pCsr->zInput = sqlite3_malloc(nByte+1); + if( pCsr->zInput==0 ){ + rc = SQLITE_NOMEM; + }else{ + memcpy(pCsr->zInput, zByte, nByte); + pCsr->zInput[nByte] = 0; + rc = pTab->tok.xTokenize( + pTab->pTok, (void*)pCsr, 0, zByte, nByte, fts5tokCb + ); + } + } + + if( rc!=SQLITE_OK ) return rc; + return fts5tokNextMethod(pCursor); +} + +/* +** xEof - Return true if the cursor is at EOF, or false otherwise. +*/ +static int fts5tokEofMethod(sqlite3_vtab_cursor *pCursor){ + Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor; + return (pCsr->iRowid>pCsr->nRow); +} + +/* +** xColumn - Return a column value. +*/ +static int fts5tokColumnMethod( + sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ + sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ + int iCol /* Index of column to read value from */ +){ + Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor; + Fts5tokRow *pRow = &pCsr->aRow[pCsr->iRowid-1]; + + /* CREATE TABLE x(input, token, start, end, position) */ + switch( iCol ){ + case 0: + sqlite3_result_text(pCtx, pCsr->zInput, -1, SQLITE_TRANSIENT); + break; + case 1: + sqlite3_result_text(pCtx, pRow->zToken, -1, SQLITE_TRANSIENT); + break; + case 2: + sqlite3_result_int(pCtx, pRow->iStart); + break; + case 3: + sqlite3_result_int(pCtx, pRow->iEnd); + break; + default: + assert( iCol==4 ); + sqlite3_result_int(pCtx, pRow->iPos); + break; + } + return SQLITE_OK; +} + +/* +** xRowid - Return the current rowid for the cursor. +*/ +static int fts5tokRowidMethod( + sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ + sqlite_int64 *pRowid /* OUT: Rowid value */ +){ + Fts5tokCursor *pCsr = (Fts5tokCursor *)pCursor; + *pRowid = (sqlite3_int64)pCsr->iRowid; + return SQLITE_OK; +} + +/* +** Register the fts5tok module with database connection db. Return SQLITE_OK +** if successful or an error code if sqlite3_create_module() fails. +*/ +int sqlite3Fts5TestRegisterTok(sqlite3 *db, fts5_api *pApi){ + static const sqlite3_module fts5tok_module = { + 0, /* iVersion */ + fts5tokConnectMethod, /* xCreate */ + fts5tokConnectMethod, /* xConnect */ + fts5tokBestIndexMethod, /* xBestIndex */ + fts5tokDisconnectMethod, /* xDisconnect */ + fts5tokDisconnectMethod, /* xDestroy */ + fts5tokOpenMethod, /* xOpen */ + fts5tokCloseMethod, /* xClose */ + fts5tokFilterMethod, /* xFilter */ + fts5tokNextMethod, /* xNext */ + fts5tokEofMethod, /* xEof */ + fts5tokColumnMethod, /* xColumn */ + fts5tokRowidMethod, /* xRowid */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindFunction */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0 /* xRollbackTo */ + }; + int rc; /* Return code */ + + rc = sqlite3_create_module(db, "fts5tokenize", &fts5tok_module, (void*)pApi); + return rc; +} + +#endif /* defined(SQLITE_TEST) && defined(SQLITE_ENABLE_FTS5) */ diff --git a/ext/fts5/fts5_tokenize.c b/ext/fts5/fts5_tokenize.c new file mode 100644 index 0000000..b72a0c2 --- /dev/null +++ b/ext/fts5/fts5_tokenize.c @@ -0,0 +1,1242 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +*/ + + +#include "fts5Int.h" + +/************************************************************************** +** Start of ascii tokenizer implementation. +*/ + +/* +** For tokenizers with no "unicode" modifier, the set of token characters +** is the same as the set of ASCII range alphanumeric characters. +*/ +static unsigned char aAsciiTokenChar[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00..0x0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10..0x1F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20..0x2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30..0x3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40..0x4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x50..0x5F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60..0x6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70..0x7F */ +}; + +typedef struct AsciiTokenizer AsciiTokenizer; +struct AsciiTokenizer { + unsigned char aTokenChar[128]; +}; + +static void fts5AsciiAddExceptions( + AsciiTokenizer *p, + const char *zArg, + int bTokenChars +){ + int i; + for(i=0; zArg[i]; i++){ + if( (zArg[i] & 0x80)==0 ){ + p->aTokenChar[(int)zArg[i]] = (unsigned char)bTokenChars; + } + } +} + +/* +** Delete a "ascii" tokenizer. +*/ +static void fts5AsciiDelete(Fts5Tokenizer *p){ + sqlite3_free(p); +} + +/* +** Create an "ascii" tokenizer. +*/ +static int fts5AsciiCreate( + void *pUnused, + const char **azArg, int nArg, + Fts5Tokenizer **ppOut +){ + int rc = SQLITE_OK; + AsciiTokenizer *p = 0; + UNUSED_PARAM(pUnused); + if( nArg%2 ){ + rc = SQLITE_ERROR; + }else{ + p = sqlite3_malloc(sizeof(AsciiTokenizer)); + if( p==0 ){ + rc = SQLITE_NOMEM; + }else{ + int i; + memset(p, 0, sizeof(AsciiTokenizer)); + memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar)); + for(i=0; rc==SQLITE_OK && i='A' && c<='Z' ) c += 32; + aOut[i] = c; + } +} + +/* +** Tokenize some text using the ascii tokenizer. +*/ +static int fts5AsciiTokenize( + Fts5Tokenizer *pTokenizer, + void *pCtx, + int iUnused, + const char *pText, int nText, + int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd) +){ + AsciiTokenizer *p = (AsciiTokenizer*)pTokenizer; + int rc = SQLITE_OK; + int ie; + int is = 0; + + char aFold[64]; + int nFold = sizeof(aFold); + char *pFold = aFold; + unsigned char *a = p->aTokenChar; + + UNUSED_PARAM(iUnused); + + while( isnFold ){ + if( pFold!=aFold ) sqlite3_free(pFold); + pFold = sqlite3_malloc(nByte*2); + if( pFold==0 ){ + rc = SQLITE_NOMEM; + break; + } + nFold = nByte*2; + } + asciiFold(pFold, &pText[is], nByte); + + /* Invoke the token callback */ + rc = xToken(pCtx, 0, pFold, nByte, is, ie); + is = ie+1; + } + + if( pFold!=aFold ) sqlite3_free(pFold); + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + return rc; +} + +/************************************************************************** +** Start of unicode61 tokenizer implementation. +*/ + + +/* +** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied +** from the sqlite3 source file utf.c. If this file is compiled as part +** of the amalgamation, they are not required. +*/ +#ifndef SQLITE_AMALGAMATION + +static const unsigned char sqlite3Utf8Trans1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, +}; + +#define READ_UTF8(zIn, zTerm, c) \ + c = *(zIn++); \ + if( c>=0xc0 ){ \ + c = sqlite3Utf8Trans1[c-0xc0]; \ + while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \ + c = (c<<6) + (0x3f & *(zIn++)); \ + } \ + if( c<0x80 \ + || (c&0xFFFFF800)==0xD800 \ + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ + } + + +#define WRITE_UTF8(zOut, c) { \ + if( c<0x00080 ){ \ + *zOut++ = (unsigned char)(c&0xFF); \ + } \ + else if( c<0x00800 ){ \ + *zOut++ = 0xC0 + (unsigned char)((c>>6)&0x1F); \ + *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ + } \ + else if( c<0x10000 ){ \ + *zOut++ = 0xE0 + (unsigned char)((c>>12)&0x0F); \ + *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \ + *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ + }else{ \ + *zOut++ = 0xF0 + (unsigned char)((c>>18) & 0x07); \ + *zOut++ = 0x80 + (unsigned char)((c>>12) & 0x3F); \ + *zOut++ = 0x80 + (unsigned char)((c>>6) & 0x3F); \ + *zOut++ = 0x80 + (unsigned char)(c & 0x3F); \ + } \ +} + +#endif /* ifndef SQLITE_AMALGAMATION */ + +typedef struct Unicode61Tokenizer Unicode61Tokenizer; +struct Unicode61Tokenizer { + unsigned char aTokenChar[128]; /* ASCII range token characters */ + char *aFold; /* Buffer to fold text into */ + int nFold; /* Size of aFold[] in bytes */ + int bRemoveDiacritic; /* True if remove_diacritics=1 is set */ + int nException; + int *aiException; +}; + +static int fts5UnicodeAddExceptions( + Unicode61Tokenizer *p, /* Tokenizer object */ + const char *z, /* Characters to treat as exceptions */ + int bTokenChars /* 1 for 'tokenchars', 0 for 'separators' */ +){ + int rc = SQLITE_OK; + int n = (int)strlen(z); + int *aNew; + + if( n>0 ){ + aNew = (int*)sqlite3_realloc(p->aiException, (n+p->nException)*sizeof(int)); + if( aNew ){ + int nNew = p->nException; + const unsigned char *zCsr = (const unsigned char*)z; + const unsigned char *zTerm = (const unsigned char*)&z[n]; + while( zCsraTokenChar[iCode] = (unsigned char)bTokenChars; + }else{ + bToken = sqlite3Fts5UnicodeIsalnum(iCode); + assert( (bToken==0 || bToken==1) ); + assert( (bTokenChars==0 || bTokenChars==1) ); + if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){ + int i; + for(i=0; iiCode ) break; + } + memmove(&aNew[i+1], &aNew[i], (nNew-i)*sizeof(int)); + aNew[i] = iCode; + nNew++; + } + } + } + p->aiException = aNew; + p->nException = nNew; + }else{ + rc = SQLITE_NOMEM; + } + } + + return rc; +} + +/* +** Return true if the p->aiException[] array contains the value iCode. +*/ +static int fts5UnicodeIsException(Unicode61Tokenizer *p, int iCode){ + if( p->nException>0 ){ + int *a = p->aiException; + int iLo = 0; + int iHi = p->nException-1; + + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + if( iCode==a[iTest] ){ + return 1; + }else if( iCode>a[iTest] ){ + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + } + + return 0; +} + +/* +** Delete a "unicode61" tokenizer. +*/ +static void fts5UnicodeDelete(Fts5Tokenizer *pTok){ + if( pTok ){ + Unicode61Tokenizer *p = (Unicode61Tokenizer*)pTok; + sqlite3_free(p->aiException); + sqlite3_free(p->aFold); + sqlite3_free(p); + } + return; +} + +/* +** Create a "unicode61" tokenizer. +*/ +static int fts5UnicodeCreate( + void *pUnused, + const char **azArg, int nArg, + Fts5Tokenizer **ppOut +){ + int rc = SQLITE_OK; /* Return code */ + Unicode61Tokenizer *p = 0; /* New tokenizer object */ + + UNUSED_PARAM(pUnused); + + if( nArg%2 ){ + rc = SQLITE_ERROR; + }else{ + p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer)); + if( p ){ + int i; + memset(p, 0, sizeof(Unicode61Tokenizer)); + memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar)); + p->bRemoveDiacritic = 1; + p->nFold = 64; + p->aFold = sqlite3_malloc(p->nFold * sizeof(char)); + if( p->aFold==0 ){ + rc = SQLITE_NOMEM; + } + for(i=0; rc==SQLITE_OK && ibRemoveDiacritic = (zArg[0]=='1'); + }else + if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){ + rc = fts5UnicodeAddExceptions(p, zArg, 1); + }else + if( 0==sqlite3_stricmp(azArg[i], "separators") ){ + rc = fts5UnicodeAddExceptions(p, zArg, 0); + }else{ + rc = SQLITE_ERROR; + } + } + }else{ + rc = SQLITE_NOMEM; + } + if( rc!=SQLITE_OK ){ + fts5UnicodeDelete((Fts5Tokenizer*)p); + p = 0; + } + *ppOut = (Fts5Tokenizer*)p; + } + return rc; +} + +/* +** Return true if, for the purposes of tokenizing with the tokenizer +** passed as the first argument, codepoint iCode is considered a token +** character (not a separator). +*/ +static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){ + assert( (sqlite3Fts5UnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 ); + return sqlite3Fts5UnicodeIsalnum(iCode) ^ fts5UnicodeIsException(p, iCode); +} + +static int fts5UnicodeTokenize( + Fts5Tokenizer *pTokenizer, + void *pCtx, + int iUnused, + const char *pText, int nText, + int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd) +){ + Unicode61Tokenizer *p = (Unicode61Tokenizer*)pTokenizer; + int rc = SQLITE_OK; + unsigned char *a = p->aTokenChar; + + unsigned char *zTerm = (unsigned char*)&pText[nText]; + unsigned char *zCsr = (unsigned char *)pText; + + /* Output buffer */ + char *aFold = p->aFold; + int nFold = p->nFold; + const char *pEnd = &aFold[nFold-6]; + + UNUSED_PARAM(iUnused); + + /* Each iteration of this loop gobbles up a contiguous run of separators, + ** then the next token. */ + while( rc==SQLITE_OK ){ + int iCode; /* non-ASCII codepoint read from input */ + char *zOut = aFold; + int is; + int ie; + + /* Skip any separator characters. */ + while( 1 ){ + if( zCsr>=zTerm ) goto tokenize_done; + if( *zCsr & 0x80 ) { + /* A character outside of the ascii range. Skip past it if it is + ** a separator character. Or break out of the loop if it is not. */ + is = zCsr - (unsigned char*)pText; + READ_UTF8(zCsr, zTerm, iCode); + if( fts5UnicodeIsAlnum(p, iCode) ){ + goto non_ascii_tokenchar; + } + }else{ + if( a[*zCsr] ){ + is = zCsr - (unsigned char*)pText; + goto ascii_tokenchar; + } + zCsr++; + } + } + + /* Run through the tokenchars. Fold them into the output buffer along + ** the way. */ + while( zCsrpEnd ){ + aFold = sqlite3_malloc(nFold*2); + if( aFold==0 ){ + rc = SQLITE_NOMEM; + goto tokenize_done; + } + zOut = &aFold[zOut - p->aFold]; + memcpy(aFold, p->aFold, nFold); + sqlite3_free(p->aFold); + p->aFold = aFold; + p->nFold = nFold = nFold*2; + pEnd = &aFold[nFold-6]; + } + + if( *zCsr & 0x80 ){ + /* An non-ascii-range character. Fold it into the output buffer if + ** it is a token character, or break out of the loop if it is not. */ + READ_UTF8(zCsr, zTerm, iCode); + if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){ + non_ascii_tokenchar: + iCode = sqlite3Fts5UnicodeFold(iCode, p->bRemoveDiacritic); + if( iCode ) WRITE_UTF8(zOut, iCode); + }else{ + break; + } + }else if( a[*zCsr]==0 ){ + /* An ascii-range separator character. End of token. */ + break; + }else{ + ascii_tokenchar: + if( *zCsr>='A' && *zCsr<='Z' ){ + *zOut++ = *zCsr + 32; + }else{ + *zOut++ = *zCsr; + } + zCsr++; + } + ie = zCsr - (unsigned char*)pText; + } + + /* Invoke the token callback */ + rc = xToken(pCtx, 0, aFold, zOut-aFold, is, ie); + } + + tokenize_done: + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + return rc; +} + +/************************************************************************** +** Start of porter stemmer implementation. +*/ + +/* Any tokens larger than this (in bytes) are passed through without +** stemming. */ +#define FTS5_PORTER_MAX_TOKEN 64 + +typedef struct PorterTokenizer PorterTokenizer; +struct PorterTokenizer { + fts5_tokenizer tokenizer; /* Parent tokenizer module */ + Fts5Tokenizer *pTokenizer; /* Parent tokenizer instance */ + char aBuf[FTS5_PORTER_MAX_TOKEN + 64]; +}; + +/* +** Delete a "porter" tokenizer. +*/ +static void fts5PorterDelete(Fts5Tokenizer *pTok){ + if( pTok ){ + PorterTokenizer *p = (PorterTokenizer*)pTok; + if( p->pTokenizer ){ + p->tokenizer.xDelete(p->pTokenizer); + } + sqlite3_free(p); + } +} + +/* +** Create a "porter" tokenizer. +*/ +static int fts5PorterCreate( + void *pCtx, + const char **azArg, int nArg, + Fts5Tokenizer **ppOut +){ + fts5_api *pApi = (fts5_api*)pCtx; + int rc = SQLITE_OK; + PorterTokenizer *pRet; + void *pUserdata = 0; + const char *zBase = "unicode61"; + + if( nArg>0 ){ + zBase = azArg[0]; + } + + pRet = (PorterTokenizer*)sqlite3_malloc(sizeof(PorterTokenizer)); + if( pRet ){ + memset(pRet, 0, sizeof(PorterTokenizer)); + rc = pApi->xFindTokenizer(pApi, zBase, &pUserdata, &pRet->tokenizer); + }else{ + rc = SQLITE_NOMEM; + } + if( rc==SQLITE_OK ){ + int nArg2 = (nArg>0 ? nArg-1 : 0); + const char **azArg2 = (nArg2 ? &azArg[1] : 0); + rc = pRet->tokenizer.xCreate(pUserdata, azArg2, nArg2, &pRet->pTokenizer); + } + + if( rc!=SQLITE_OK ){ + fts5PorterDelete((Fts5Tokenizer*)pRet); + pRet = 0; + } + *ppOut = (Fts5Tokenizer*)pRet; + return rc; +} + +typedef struct PorterContext PorterContext; +struct PorterContext { + void *pCtx; + int (*xToken)(void*, int, const char*, int, int, int); + char *aBuf; +}; + +typedef struct PorterRule PorterRule; +struct PorterRule { + const char *zSuffix; + int nSuffix; + int (*xCond)(char *zStem, int nStem); + const char *zOutput; + int nOutput; +}; + +#if 0 +static int fts5PorterApply(char *aBuf, int *pnBuf, PorterRule *aRule){ + int ret = -1; + int nBuf = *pnBuf; + PorterRule *p; + + for(p=aRule; p->zSuffix; p++){ + assert( strlen(p->zSuffix)==p->nSuffix ); + assert( strlen(p->zOutput)==p->nOutput ); + if( nBufnSuffix ) continue; + if( 0==memcmp(&aBuf[nBuf - p->nSuffix], p->zSuffix, p->nSuffix) ) break; + } + + if( p->zSuffix ){ + int nStem = nBuf - p->nSuffix; + if( p->xCond==0 || p->xCond(aBuf, nStem) ){ + memcpy(&aBuf[nStem], p->zOutput, p->nOutput); + *pnBuf = nStem + p->nOutput; + ret = p - aRule; + } + } + + return ret; +} +#endif + +static int fts5PorterIsVowel(char c, int bYIsVowel){ + return ( + c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || (bYIsVowel && c=='y') + ); +} + +static int fts5PorterGobbleVC(char *zStem, int nStem, int bPrevCons){ + int i; + int bCons = bPrevCons; + + /* Scan for a vowel */ + for(i=0; i 0) */ +static int fts5Porter_MGt0(char *zStem, int nStem){ + return !!fts5PorterGobbleVC(zStem, nStem, 0); +} + +/* porter rule condition: (m > 1) */ +static int fts5Porter_MGt1(char *zStem, int nStem){ + int n; + n = fts5PorterGobbleVC(zStem, nStem, 0); + if( n && fts5PorterGobbleVC(&zStem[n], nStem-n, 1) ){ + return 1; + } + return 0; +} + +/* porter rule condition: (m = 1) */ +static int fts5Porter_MEq1(char *zStem, int nStem){ + int n; + n = fts5PorterGobbleVC(zStem, nStem, 0); + if( n && 0==fts5PorterGobbleVC(&zStem[n], nStem-n, 1) ){ + return 1; + } + return 0; +} + +/* porter rule condition: (*o) */ +static int fts5Porter_Ostar(char *zStem, int nStem){ + if( zStem[nStem-1]=='w' || zStem[nStem-1]=='x' || zStem[nStem-1]=='y' ){ + return 0; + }else{ + int i; + int mask = 0; + int bCons = 0; + for(i=0; i 1 and (*S or *T)) */ +static int fts5Porter_MGt1_and_S_or_T(char *zStem, int nStem){ + assert( nStem>0 ); + return (zStem[nStem-1]=='s' || zStem[nStem-1]=='t') + && fts5Porter_MGt1(zStem, nStem); +} + +/* porter rule condition: (*v*) */ +static int fts5Porter_Vowel(char *zStem, int nStem){ + int i; + for(i=0; i0) ){ + return 1; + } + } + return 0; +} + + +/************************************************************************** +*************************************************************************** +** GENERATED CODE STARTS HERE (mkportersteps.tcl) +*/ + +static int fts5PorterStep4(char *aBuf, int *pnBuf){ + int ret = 0; + int nBuf = *pnBuf; + switch( aBuf[nBuf-2] ){ + + case 'a': + if( nBuf>2 && 0==memcmp("al", &aBuf[nBuf-2], 2) ){ + if( fts5Porter_MGt1(aBuf, nBuf-2) ){ + *pnBuf = nBuf - 2; + } + } + break; + + case 'c': + if( nBuf>4 && 0==memcmp("ance", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt1(aBuf, nBuf-4) ){ + *pnBuf = nBuf - 4; + } + }else if( nBuf>4 && 0==memcmp("ence", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt1(aBuf, nBuf-4) ){ + *pnBuf = nBuf - 4; + } + } + break; + + case 'e': + if( nBuf>2 && 0==memcmp("er", &aBuf[nBuf-2], 2) ){ + if( fts5Porter_MGt1(aBuf, nBuf-2) ){ + *pnBuf = nBuf - 2; + } + } + break; + + case 'i': + if( nBuf>2 && 0==memcmp("ic", &aBuf[nBuf-2], 2) ){ + if( fts5Porter_MGt1(aBuf, nBuf-2) ){ + *pnBuf = nBuf - 2; + } + } + break; + + case 'l': + if( nBuf>4 && 0==memcmp("able", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt1(aBuf, nBuf-4) ){ + *pnBuf = nBuf - 4; + } + }else if( nBuf>4 && 0==memcmp("ible", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt1(aBuf, nBuf-4) ){ + *pnBuf = nBuf - 4; + } + } + break; + + case 'n': + if( nBuf>3 && 0==memcmp("ant", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + }else if( nBuf>5 && 0==memcmp("ement", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt1(aBuf, nBuf-5) ){ + *pnBuf = nBuf - 5; + } + }else if( nBuf>4 && 0==memcmp("ment", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt1(aBuf, nBuf-4) ){ + *pnBuf = nBuf - 4; + } + }else if( nBuf>3 && 0==memcmp("ent", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + } + break; + + case 'o': + if( nBuf>3 && 0==memcmp("ion", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1_and_S_or_T(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + }else if( nBuf>2 && 0==memcmp("ou", &aBuf[nBuf-2], 2) ){ + if( fts5Porter_MGt1(aBuf, nBuf-2) ){ + *pnBuf = nBuf - 2; + } + } + break; + + case 's': + if( nBuf>3 && 0==memcmp("ism", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + } + break; + + case 't': + if( nBuf>3 && 0==memcmp("ate", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + }else if( nBuf>3 && 0==memcmp("iti", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + } + break; + + case 'u': + if( nBuf>3 && 0==memcmp("ous", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + } + break; + + case 'v': + if( nBuf>3 && 0==memcmp("ive", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + } + break; + + case 'z': + if( nBuf>3 && 0==memcmp("ize", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt1(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + } + break; + + } + return ret; +} + + +static int fts5PorterStep1B2(char *aBuf, int *pnBuf){ + int ret = 0; + int nBuf = *pnBuf; + switch( aBuf[nBuf-2] ){ + + case 'a': + if( nBuf>2 && 0==memcmp("at", &aBuf[nBuf-2], 2) ){ + memcpy(&aBuf[nBuf-2], "ate", 3); + *pnBuf = nBuf - 2 + 3; + ret = 1; + } + break; + + case 'b': + if( nBuf>2 && 0==memcmp("bl", &aBuf[nBuf-2], 2) ){ + memcpy(&aBuf[nBuf-2], "ble", 3); + *pnBuf = nBuf - 2 + 3; + ret = 1; + } + break; + + case 'i': + if( nBuf>2 && 0==memcmp("iz", &aBuf[nBuf-2], 2) ){ + memcpy(&aBuf[nBuf-2], "ize", 3); + *pnBuf = nBuf - 2 + 3; + ret = 1; + } + break; + + } + return ret; +} + + +static int fts5PorterStep2(char *aBuf, int *pnBuf){ + int ret = 0; + int nBuf = *pnBuf; + switch( aBuf[nBuf-2] ){ + + case 'a': + if( nBuf>7 && 0==memcmp("ational", &aBuf[nBuf-7], 7) ){ + if( fts5Porter_MGt0(aBuf, nBuf-7) ){ + memcpy(&aBuf[nBuf-7], "ate", 3); + *pnBuf = nBuf - 7 + 3; + } + }else if( nBuf>6 && 0==memcmp("tional", &aBuf[nBuf-6], 6) ){ + if( fts5Porter_MGt0(aBuf, nBuf-6) ){ + memcpy(&aBuf[nBuf-6], "tion", 4); + *pnBuf = nBuf - 6 + 4; + } + } + break; + + case 'c': + if( nBuf>4 && 0==memcmp("enci", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt0(aBuf, nBuf-4) ){ + memcpy(&aBuf[nBuf-4], "ence", 4); + *pnBuf = nBuf - 4 + 4; + } + }else if( nBuf>4 && 0==memcmp("anci", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt0(aBuf, nBuf-4) ){ + memcpy(&aBuf[nBuf-4], "ance", 4); + *pnBuf = nBuf - 4 + 4; + } + } + break; + + case 'e': + if( nBuf>4 && 0==memcmp("izer", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt0(aBuf, nBuf-4) ){ + memcpy(&aBuf[nBuf-4], "ize", 3); + *pnBuf = nBuf - 4 + 3; + } + } + break; + + case 'g': + if( nBuf>4 && 0==memcmp("logi", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt0(aBuf, nBuf-4) ){ + memcpy(&aBuf[nBuf-4], "log", 3); + *pnBuf = nBuf - 4 + 3; + } + } + break; + + case 'l': + if( nBuf>3 && 0==memcmp("bli", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt0(aBuf, nBuf-3) ){ + memcpy(&aBuf[nBuf-3], "ble", 3); + *pnBuf = nBuf - 3 + 3; + } + }else if( nBuf>4 && 0==memcmp("alli", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt0(aBuf, nBuf-4) ){ + memcpy(&aBuf[nBuf-4], "al", 2); + *pnBuf = nBuf - 4 + 2; + } + }else if( nBuf>5 && 0==memcmp("entli", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "ent", 3); + *pnBuf = nBuf - 5 + 3; + } + }else if( nBuf>3 && 0==memcmp("eli", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt0(aBuf, nBuf-3) ){ + memcpy(&aBuf[nBuf-3], "e", 1); + *pnBuf = nBuf - 3 + 1; + } + }else if( nBuf>5 && 0==memcmp("ousli", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "ous", 3); + *pnBuf = nBuf - 5 + 3; + } + } + break; + + case 'o': + if( nBuf>7 && 0==memcmp("ization", &aBuf[nBuf-7], 7) ){ + if( fts5Porter_MGt0(aBuf, nBuf-7) ){ + memcpy(&aBuf[nBuf-7], "ize", 3); + *pnBuf = nBuf - 7 + 3; + } + }else if( nBuf>5 && 0==memcmp("ation", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "ate", 3); + *pnBuf = nBuf - 5 + 3; + } + }else if( nBuf>4 && 0==memcmp("ator", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt0(aBuf, nBuf-4) ){ + memcpy(&aBuf[nBuf-4], "ate", 3); + *pnBuf = nBuf - 4 + 3; + } + } + break; + + case 's': + if( nBuf>5 && 0==memcmp("alism", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "al", 2); + *pnBuf = nBuf - 5 + 2; + } + }else if( nBuf>7 && 0==memcmp("iveness", &aBuf[nBuf-7], 7) ){ + if( fts5Porter_MGt0(aBuf, nBuf-7) ){ + memcpy(&aBuf[nBuf-7], "ive", 3); + *pnBuf = nBuf - 7 + 3; + } + }else if( nBuf>7 && 0==memcmp("fulness", &aBuf[nBuf-7], 7) ){ + if( fts5Porter_MGt0(aBuf, nBuf-7) ){ + memcpy(&aBuf[nBuf-7], "ful", 3); + *pnBuf = nBuf - 7 + 3; + } + }else if( nBuf>7 && 0==memcmp("ousness", &aBuf[nBuf-7], 7) ){ + if( fts5Porter_MGt0(aBuf, nBuf-7) ){ + memcpy(&aBuf[nBuf-7], "ous", 3); + *pnBuf = nBuf - 7 + 3; + } + } + break; + + case 't': + if( nBuf>5 && 0==memcmp("aliti", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "al", 2); + *pnBuf = nBuf - 5 + 2; + } + }else if( nBuf>5 && 0==memcmp("iviti", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "ive", 3); + *pnBuf = nBuf - 5 + 3; + } + }else if( nBuf>6 && 0==memcmp("biliti", &aBuf[nBuf-6], 6) ){ + if( fts5Porter_MGt0(aBuf, nBuf-6) ){ + memcpy(&aBuf[nBuf-6], "ble", 3); + *pnBuf = nBuf - 6 + 3; + } + } + break; + + } + return ret; +} + + +static int fts5PorterStep3(char *aBuf, int *pnBuf){ + int ret = 0; + int nBuf = *pnBuf; + switch( aBuf[nBuf-2] ){ + + case 'a': + if( nBuf>4 && 0==memcmp("ical", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt0(aBuf, nBuf-4) ){ + memcpy(&aBuf[nBuf-4], "ic", 2); + *pnBuf = nBuf - 4 + 2; + } + } + break; + + case 's': + if( nBuf>4 && 0==memcmp("ness", &aBuf[nBuf-4], 4) ){ + if( fts5Porter_MGt0(aBuf, nBuf-4) ){ + *pnBuf = nBuf - 4; + } + } + break; + + case 't': + if( nBuf>5 && 0==memcmp("icate", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "ic", 2); + *pnBuf = nBuf - 5 + 2; + } + }else if( nBuf>5 && 0==memcmp("iciti", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "ic", 2); + *pnBuf = nBuf - 5 + 2; + } + } + break; + + case 'u': + if( nBuf>3 && 0==memcmp("ful", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt0(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + } + } + break; + + case 'v': + if( nBuf>5 && 0==memcmp("ative", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + *pnBuf = nBuf - 5; + } + } + break; + + case 'z': + if( nBuf>5 && 0==memcmp("alize", &aBuf[nBuf-5], 5) ){ + if( fts5Porter_MGt0(aBuf, nBuf-5) ){ + memcpy(&aBuf[nBuf-5], "al", 2); + *pnBuf = nBuf - 5 + 2; + } + } + break; + + } + return ret; +} + + +static int fts5PorterStep1B(char *aBuf, int *pnBuf){ + int ret = 0; + int nBuf = *pnBuf; + switch( aBuf[nBuf-2] ){ + + case 'e': + if( nBuf>3 && 0==memcmp("eed", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_MGt0(aBuf, nBuf-3) ){ + memcpy(&aBuf[nBuf-3], "ee", 2); + *pnBuf = nBuf - 3 + 2; + } + }else if( nBuf>2 && 0==memcmp("ed", &aBuf[nBuf-2], 2) ){ + if( fts5Porter_Vowel(aBuf, nBuf-2) ){ + *pnBuf = nBuf - 2; + ret = 1; + } + } + break; + + case 'n': + if( nBuf>3 && 0==memcmp("ing", &aBuf[nBuf-3], 3) ){ + if( fts5Porter_Vowel(aBuf, nBuf-3) ){ + *pnBuf = nBuf - 3; + ret = 1; + } + } + break; + + } + return ret; +} + +/* +** GENERATED CODE ENDS HERE (mkportersteps.tcl) +*************************************************************************** +**************************************************************************/ + +static void fts5PorterStep1A(char *aBuf, int *pnBuf){ + int nBuf = *pnBuf; + if( aBuf[nBuf-1]=='s' ){ + if( aBuf[nBuf-2]=='e' ){ + if( (nBuf>4 && aBuf[nBuf-4]=='s' && aBuf[nBuf-3]=='s') + || (nBuf>3 && aBuf[nBuf-3]=='i' ) + ){ + *pnBuf = nBuf-2; + }else{ + *pnBuf = nBuf-1; + } + } + else if( aBuf[nBuf-2]!='s' ){ + *pnBuf = nBuf-1; + } + } +} + +static int fts5PorterCb( + void *pCtx, + int tflags, + const char *pToken, + int nToken, + int iStart, + int iEnd +){ + PorterContext *p = (PorterContext*)pCtx; + + char *aBuf; + int nBuf; + + if( nToken>FTS5_PORTER_MAX_TOKEN || nToken<3 ) goto pass_through; + aBuf = p->aBuf; + nBuf = nToken; + memcpy(aBuf, pToken, nBuf); + + /* Step 1. */ + fts5PorterStep1A(aBuf, &nBuf); + if( fts5PorterStep1B(aBuf, &nBuf) ){ + if( fts5PorterStep1B2(aBuf, &nBuf)==0 ){ + char c = aBuf[nBuf-1]; + if( fts5PorterIsVowel(c, 0)==0 + && c!='l' && c!='s' && c!='z' && c==aBuf[nBuf-2] + ){ + nBuf--; + }else if( fts5Porter_MEq1(aBuf, nBuf) && fts5Porter_Ostar(aBuf, nBuf) ){ + aBuf[nBuf++] = 'e'; + } + } + } + + /* Step 1C. */ + if( aBuf[nBuf-1]=='y' && fts5Porter_Vowel(aBuf, nBuf-1) ){ + aBuf[nBuf-1] = 'i'; + } + + /* Steps 2 through 4. */ + fts5PorterStep2(aBuf, &nBuf); + fts5PorterStep3(aBuf, &nBuf); + fts5PorterStep4(aBuf, &nBuf); + + /* Step 5a. */ + assert( nBuf>0 ); + if( aBuf[nBuf-1]=='e' ){ + if( fts5Porter_MGt1(aBuf, nBuf-1) + || (fts5Porter_MEq1(aBuf, nBuf-1) && !fts5Porter_Ostar(aBuf, nBuf-1)) + ){ + nBuf--; + } + } + + /* Step 5b. */ + if( nBuf>1 && aBuf[nBuf-1]=='l' + && aBuf[nBuf-2]=='l' && fts5Porter_MGt1(aBuf, nBuf-1) + ){ + nBuf--; + } + + return p->xToken(p->pCtx, tflags, aBuf, nBuf, iStart, iEnd); + + pass_through: + return p->xToken(p->pCtx, tflags, pToken, nToken, iStart, iEnd); +} + +/* +** Tokenize using the porter tokenizer. +*/ +static int fts5PorterTokenize( + Fts5Tokenizer *pTokenizer, + void *pCtx, + int flags, + const char *pText, int nText, + int (*xToken)(void*, int, const char*, int nToken, int iStart, int iEnd) +){ + PorterTokenizer *p = (PorterTokenizer*)pTokenizer; + PorterContext sCtx; + sCtx.xToken = xToken; + sCtx.pCtx = pCtx; + sCtx.aBuf = p->aBuf; + return p->tokenizer.xTokenize( + p->pTokenizer, (void*)&sCtx, flags, pText, nText, fts5PorterCb + ); +} + +/* +** Register all built-in tokenizers with FTS5. +*/ +int sqlite3Fts5TokenizerInit(fts5_api *pApi){ + struct BuiltinTokenizer { + const char *zName; + fts5_tokenizer x; + } aBuiltin[] = { + { "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}}, + { "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }}, + { "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }}, + }; + + int rc = SQLITE_OK; /* Return code */ + int i; /* To iterate through builtin functions */ + + for(i=0; rc==SQLITE_OK && ixCreateTokenizer(pApi, + aBuiltin[i].zName, + (void*)pApi, + &aBuiltin[i].x, + 0 + ); + } + + return rc; +} + + diff --git a/ext/fts5/fts5_unicode2.c b/ext/fts5/fts5_unicode2.c new file mode 100644 index 0000000..1ef56f6 --- /dev/null +++ b/ext/fts5/fts5_unicode2.c @@ -0,0 +1,360 @@ +/* +** 2012 May 25 +** +** 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. +** +****************************************************************************** +*/ + +/* +** DO NOT EDIT THIS MACHINE GENERATED FILE. +*/ + + +#include + +/* +** Return true if the argument corresponds to a unicode codepoint +** classified as either a letter or a number. Otherwise false. +** +** The results are undefined if the value passed to this function +** is less than zero. +*/ +int sqlite3Fts5UnicodeIsalnum(int c){ + /* Each unsigned integer in the following array corresponds to a contiguous + ** range of unicode codepoints that are not either letters or numbers (i.e. + ** codepoints for which this function should return 0). + ** + ** The most significant 22 bits in each 32-bit value contain the first + ** codepoint in the range. The least significant 10 bits are used to store + ** the size of the range (always at least 1). In other words, the value + ** ((C<<22) + N) represents a range of N codepoints starting with codepoint + ** C. It is not possible to represent a range larger than 1023 codepoints + ** using this format. + */ + static const unsigned int aEntry[] = { + 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, + 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, + 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, + 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, + 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, + 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, + 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, + 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, + 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, + 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, + 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, + 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, + 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, + 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, + 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, + 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, + 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, + 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, + 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, + 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, + 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, + 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, + 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, + 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, + 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, + 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, + 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, + 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, + 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, + 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, + 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, + 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, + 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, + 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, + 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, + 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, + 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, + 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, + 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, + 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, + 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, + 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, + 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, + 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, + 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, + 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, + 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, + 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, + 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, + 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, + 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, + 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, + 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, + 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, + 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, + 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, + 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, + 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, + 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, + 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, + 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, + 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, + 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013, + 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06, + 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003, + 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01, + 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403, + 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009, + 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003, + 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003, + 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E, + 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046, + 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401, + 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401, + 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F, + 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C, + 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002, + 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025, + 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6, + 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46, + 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060, + 0x380400F0, + }; + static const unsigned int aAscii[4] = { + 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, + }; + + if( (unsigned int)c<128 ){ + return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); + }else if( (unsigned int)c<(1<<22) ){ + unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; + int iRes = 0; + int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; + int iLo = 0; + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + if( key >= aEntry[iTest] ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + assert( aEntry[0]=aEntry[iRes] ); + return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); + } + return 1; +} + + +/* +** If the argument is a codepoint corresponding to a lowercase letter +** in the ASCII range with a diacritic added, return the codepoint +** of the ASCII letter only. For example, if passed 235 - "LATIN +** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER +** E"). The resuls of passing a codepoint that corresponds to an +** uppercase letter are undefined. +*/ +static int fts5_remove_diacritic(int c){ + unsigned short aDia[] = { + 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, + 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, + 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, + 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, + 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928, + 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234, + 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504, + 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529, + 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, + 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122, + 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536, + 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730, + 62924, 63050, 63082, 63274, 63390, + }; + char aChar[] = { + '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c', + 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', + 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', + 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', + 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', + 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', + 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', + 'e', 'i', 'o', 'u', 'y', + }; + + unsigned int key = (((unsigned int)c)<<3) | 0x00000007; + int iRes = 0; + int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; + int iLo = 0; + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + if( key >= aDia[iTest] ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + assert( key>=aDia[iRes] ); + return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]); +} + + +/* +** Return true if the argument interpreted as a unicode codepoint +** is a diacritical modifier character. +*/ +int sqlite3Fts5UnicodeIsdiacritic(int c){ + unsigned int mask0 = 0x08029FDF; + unsigned int mask1 = 0x000361F8; + if( c<768 || c>817 ) return 0; + return (c < 768+32) ? + (mask0 & (1 << (c-768))) : + (mask1 & (1 << (c-768-32))); +} + + +/* +** Interpret the argument as a unicode codepoint. If the codepoint +** is an upper case character that has a lower case equivalent, +** return the codepoint corresponding to the lower case version. +** Otherwise, return a copy of the argument. +** +** The results are undefined if the value passed to this function +** is less than zero. +*/ +int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){ + /* Each entry in the following array defines a rule for folding a range + ** of codepoints to lower case. The rule applies to a range of nRange + ** codepoints starting at codepoint iCode. + ** + ** If the least significant bit in flags is clear, then the rule applies + ** to all nRange codepoints (i.e. all nRange codepoints are upper case and + ** need to be folded). Or, if it is set, then the rule only applies to + ** every second codepoint in the range, starting with codepoint C. + ** + ** The 7 most significant bits in flags are an index into the aiOff[] + ** array. If a specific codepoint C does require folding, then its lower + ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF). + ** + ** The contents of this array are generated by parsing the CaseFolding.txt + ** file distributed as part of the "Unicode Character Database". See + ** http://www.unicode.org for details. + */ + static const struct TableEntry { + unsigned short iCode; + unsigned char flags; + unsigned char nRange; + } aEntry[] = { + {65, 14, 26}, {181, 64, 1}, {192, 14, 23}, + {216, 14, 7}, {256, 1, 48}, {306, 1, 6}, + {313, 1, 16}, {330, 1, 46}, {376, 116, 1}, + {377, 1, 6}, {383, 104, 1}, {385, 50, 1}, + {386, 1, 4}, {390, 44, 1}, {391, 0, 1}, + {393, 42, 2}, {395, 0, 1}, {398, 32, 1}, + {399, 38, 1}, {400, 40, 1}, {401, 0, 1}, + {403, 42, 1}, {404, 46, 1}, {406, 52, 1}, + {407, 48, 1}, {408, 0, 1}, {412, 52, 1}, + {413, 54, 1}, {415, 56, 1}, {416, 1, 6}, + {422, 60, 1}, {423, 0, 1}, {425, 60, 1}, + {428, 0, 1}, {430, 60, 1}, {431, 0, 1}, + {433, 58, 2}, {435, 1, 4}, {439, 62, 1}, + {440, 0, 1}, {444, 0, 1}, {452, 2, 1}, + {453, 0, 1}, {455, 2, 1}, {456, 0, 1}, + {458, 2, 1}, {459, 1, 18}, {478, 1, 18}, + {497, 2, 1}, {498, 1, 4}, {502, 122, 1}, + {503, 134, 1}, {504, 1, 40}, {544, 110, 1}, + {546, 1, 18}, {570, 70, 1}, {571, 0, 1}, + {573, 108, 1}, {574, 68, 1}, {577, 0, 1}, + {579, 106, 1}, {580, 28, 1}, {581, 30, 1}, + {582, 1, 10}, {837, 36, 1}, {880, 1, 4}, + {886, 0, 1}, {902, 18, 1}, {904, 16, 3}, + {908, 26, 1}, {910, 24, 2}, {913, 14, 17}, + {931, 14, 9}, {962, 0, 1}, {975, 4, 1}, + {976, 140, 1}, {977, 142, 1}, {981, 146, 1}, + {982, 144, 1}, {984, 1, 24}, {1008, 136, 1}, + {1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1}, + {1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1}, + {1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32}, + {1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1}, + {1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38}, + {4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1}, + {7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1}, + {7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6}, + {7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6}, + {8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8}, + {8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2}, + {8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1}, + {8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2}, + {8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2}, + {8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2}, + {8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1}, + {8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16}, + {8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47}, + {11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1}, + {11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1}, + {11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1}, + {11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2}, + {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1}, + {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14}, + {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1}, + {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1}, + {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1}, + {65313, 14, 26}, + }; + static const unsigned short aiOff[] = { + 1, 2, 8, 15, 16, 26, 28, 32, + 37, 38, 40, 48, 63, 64, 69, 71, + 79, 80, 116, 202, 203, 205, 206, 207, + 209, 210, 211, 213, 214, 217, 218, 219, + 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, + 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, + 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, + 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, + 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, + 65514, 65521, 65527, 65528, 65529, + }; + + int ret = c; + + assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); + + if( c<128 ){ + if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); + }else if( c<65536 ){ + const struct TableEntry *p; + int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; + int iLo = 0; + int iRes = -1; + + assert( c>aEntry[0].iCode ); + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + int cmp = (c - aEntry[iTest].iCode); + if( cmp>=0 ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + + assert( iRes>=0 && c>=aEntry[iRes].iCode ); + p = &aEntry[iRes]; + if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ + ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; + assert( ret>0 ); + } + + if( bRemoveDiacritic ) ret = fts5_remove_diacritic(ret); + } + + else if( c>=66560 && c<66600 ){ + ret = c + 40; + } + + return ret; +} diff --git a/ext/fts5/fts5_varint.c b/ext/fts5/fts5_varint.c new file mode 100644 index 0000000..bb212ab --- /dev/null +++ b/ext/fts5/fts5_varint.c @@ -0,0 +1,345 @@ +/* +** 2015 May 30 +** +** 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. +** +****************************************************************************** +** +** Routines for varint serialization and deserialization. +*/ + + +#include "fts5Int.h" + +/* +** This is a copy of the sqlite3GetVarint32() routine from the SQLite core. +** Except, this version does handle the single byte case that the core +** version depends on being handled before its function is called. +*/ +int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v){ + u32 a,b; + + /* The 1-byte case. Overwhelmingly the most common. */ + a = *p; + /* a: p0 (unmasked) */ + if (!(a&0x80)) + { + /* Values between 0 and 127 */ + *v = a; + return 1; + } + + /* The 2-byte case */ + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + /* Values between 128 and 16383 */ + a &= 0x7f; + a = a<<7; + *v = a | b; + return 2; + } + + /* The 3-byte case */ + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + /* Values between 16384 and 2097151 */ + a &= (0x7f<<14)|(0x7f); + b &= 0x7f; + b = b<<7; + *v = a | b; + return 3; + } + + /* A 32-bit varint is used to store size information in btrees. + ** Objects are rarely larger than 2MiB limit of a 3-byte varint. + ** A 3-byte varint is sufficient, for example, to record the size + ** of a 1048569-byte BLOB or string. + ** + ** We only unroll the first 1-, 2-, and 3- byte cases. The very + ** rare larger cases can be handled by the slower 64-bit varint + ** routine. + */ + { + u64 v64; + u8 n; + p -= 2; + n = sqlite3Fts5GetVarint(p, &v64); + *v = (u32)v64; + assert( n>3 && n<=9 ); + return n; + } +} + + +/* +** Bitmasks used by sqlite3GetVarint(). These precomputed constants +** are defined here rather than simply putting the constant expressions +** inline in order to work around bugs in the RVT compiler. +** +** SLOT_2_0 A mask for (0x7f<<14) | 0x7f +** +** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0 +*/ +#define SLOT_2_0 0x001fc07f +#define SLOT_4_2_0 0xf01fc07f + +/* +** Read a 64-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read. The value is stored in *v. +*/ +u8 sqlite3Fts5GetVarint(const unsigned char *p, u64 *v){ + u32 a,b,s; + + a = *p; + /* a: p0 (unmasked) */ + if (!(a&0x80)) + { + *v = a; + return 1; + } + + p++; + b = *p; + /* b: p1 (unmasked) */ + if (!(b&0x80)) + { + a &= 0x7f; + a = a<<7; + a |= b; + *v = a; + return 2; + } + + /* Verify that constants are precomputed correctly */ + assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) ); + assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) ); + + p++; + a = a<<14; + a |= *p; + /* a: p0<<14 | p2 (unmasked) */ + if (!(a&0x80)) + { + a &= SLOT_2_0; + b &= 0x7f; + b = b<<7; + a |= b; + *v = a; + return 3; + } + + /* CSE1 from below */ + a &= SLOT_2_0; + p++; + b = b<<14; + b |= *p; + /* b: p1<<14 | p3 (unmasked) */ + if (!(b&0x80)) + { + b &= SLOT_2_0; + /* moved CSE1 up */ + /* a &= (0x7f<<14)|(0x7f); */ + a = a<<7; + a |= b; + *v = a; + return 4; + } + + /* a: p0<<14 | p2 (masked) */ + /* b: p1<<14 | p3 (unmasked) */ + /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + /* moved CSE1 up */ + /* a &= (0x7f<<14)|(0x7f); */ + b &= SLOT_2_0; + s = a; + /* s: p0<<14 | p2 (masked) */ + + p++; + a = a<<14; + a |= *p; + /* a: p0<<28 | p2<<14 | p4 (unmasked) */ + if (!(a&0x80)) + { + /* we can skip these cause they were (effectively) done above in calc'ing s */ + /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ + /* b &= (0x7f<<14)|(0x7f); */ + b = b<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 5; + } + + /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + s = s<<7; + s |= b; + /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */ + + p++; + b = b<<14; + b |= *p; + /* b: p1<<28 | p3<<14 | p5 (unmasked) */ + if (!(b&0x80)) + { + /* we can skip this cause it was (effectively) done above in calc'ing s */ + /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */ + a &= SLOT_2_0; + a = a<<7; + a |= b; + s = s>>18; + *v = ((u64)s)<<32 | a; + return 6; + } + + p++; + a = a<<14; + a |= *p; + /* a: p2<<28 | p4<<14 | p6 (unmasked) */ + if (!(a&0x80)) + { + a &= SLOT_4_2_0; + b &= SLOT_2_0; + b = b<<7; + a |= b; + s = s>>11; + *v = ((u64)s)<<32 | a; + return 7; + } + + /* CSE2 from below */ + a &= SLOT_2_0; + p++; + b = b<<14; + b |= *p; + /* b: p3<<28 | p5<<14 | p7 (unmasked) */ + if (!(b&0x80)) + { + b &= SLOT_4_2_0; + /* moved CSE2 up */ + /* a &= (0x7f<<14)|(0x7f); */ + a = a<<7; + a |= b; + s = s>>4; + *v = ((u64)s)<<32 | a; + return 8; + } + + p++; + a = a<<15; + a |= *p; + /* a: p4<<29 | p6<<15 | p8 (unmasked) */ + + /* moved CSE2 up */ + /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */ + b &= SLOT_2_0; + b = b<<8; + a |= b; + + s = s<<4; + b = p[-4]; + b &= 0x7f; + b = b>>3; + s |= b; + + *v = ((u64)s)<<32 | a; + + return 9; +} + +/* +** The variable-length integer encoding is as follows: +** +** KEY: +** A = 0xxxxxxx 7 bits of data and one flag bit +** B = 1xxxxxxx 7 bits of data and one flag bit +** C = xxxxxxxx 8 bits of data +** +** 7 bits - A +** 14 bits - BA +** 21 bits - BBA +** 28 bits - BBBA +** 35 bits - BBBBA +** 42 bits - BBBBBA +** 49 bits - BBBBBBA +** 56 bits - BBBBBBBA +** 64 bits - BBBBBBBBC +*/ + +#ifdef SQLITE_NOINLINE +# define FTS5_NOINLINE SQLITE_NOINLINE +#else +# define FTS5_NOINLINE +#endif + +/* +** Write a 64-bit variable-length integer to memory starting at p[0]. +** The length of data write will be between 1 and 9 bytes. The number +** of bytes written is returned. +** +** A variable-length integer consists of the lower 7 bits of each byte +** for all bytes that have the 8th bit set and one byte with the 8th +** bit clear. Except, if we get to the 9th byte, it stores the full +** 8 bits and is the last byte. +*/ +static int FTS5_NOINLINE fts5PutVarint64(unsigned char *p, u64 v){ + int i, j, n; + u8 buf[10]; + if( v & (((u64)0xff000000)<<32) ){ + p[8] = (u8)v; + v >>= 8; + for(i=7; i>=0; i--){ + p[i] = (u8)((v & 0x7f) | 0x80); + v >>= 7; + } + return 9; + } + n = 0; + do{ + buf[n++] = (u8)((v & 0x7f) | 0x80); + v >>= 7; + }while( v!=0 ); + buf[0] &= 0x7f; + assert( n<=9 ); + for(i=0, j=n-1; j>=0; j--, i++){ + p[i] = buf[j]; + } + return n; +} + +int sqlite3Fts5PutVarint(unsigned char *p, u64 v){ + if( v<=0x7f ){ + p[0] = v&0x7f; + return 1; + } + if( v<=0x3fff ){ + p[0] = ((v>>7)&0x7f)|0x80; + p[1] = v&0x7f; + return 2; + } + return fts5PutVarint64(p,v); +} + + +int sqlite3Fts5GetVarintLen(u32 iVal){ +#if 0 + if( iVal<(1 << 7 ) ) return 1; +#endif + assert( iVal>=(1 << 7) ); + if( iVal<(1 << 14) ) return 2; + if( iVal<(1 << 21) ) return 3; + if( iVal<(1 << 28) ) return 4; + return 5; +} + diff --git a/ext/fts5/fts5_vocab.c b/ext/fts5/fts5_vocab.c new file mode 100644 index 0000000..f3a2381 --- /dev/null +++ b/ext/fts5/fts5_vocab.c @@ -0,0 +1,641 @@ +/* +** 2015 May 08 +** +** 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 is an SQLite virtual table module implementing direct access to an +** existing FTS5 index. The module may create several different types of +** tables: +** +** col: +** CREATE TABLE vocab(term, col, doc, cnt, PRIMARY KEY(term, col)); +** +** One row for each term/column combination. The value of $doc is set to +** the number of fts5 rows that contain at least one instance of term +** $term within column $col. Field $cnt is set to the total number of +** instances of term $term in column $col (in any row of the fts5 table). +** +** row: +** CREATE TABLE vocab(term, doc, cnt, PRIMARY KEY(term)); +** +** One row for each term in the database. The value of $doc is set to +** the number of fts5 rows that contain at least one instance of term +** $term. Field $cnt is set to the total number of instances of term +** $term in the database. +*/ + + +#include "fts5Int.h" + + +typedef struct Fts5VocabTable Fts5VocabTable; +typedef struct Fts5VocabCursor Fts5VocabCursor; + +struct Fts5VocabTable { + sqlite3_vtab base; + char *zFts5Tbl; /* Name of fts5 table */ + char *zFts5Db; /* Db containing fts5 table */ + sqlite3 *db; /* Database handle */ + Fts5Global *pGlobal; /* FTS5 global object for this database */ + int eType; /* FTS5_VOCAB_COL or ROW */ +}; + +struct Fts5VocabCursor { + sqlite3_vtab_cursor base; + sqlite3_stmt *pStmt; /* Statement holding lock on pIndex */ + Fts5Index *pIndex; /* Associated FTS5 index */ + + int bEof; /* True if this cursor is at EOF */ + Fts5IndexIter *pIter; /* Term/rowid iterator object */ + + int nLeTerm; /* Size of zLeTerm in bytes */ + char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */ + + /* These are used by 'col' tables only */ + Fts5Config *pConfig; /* Fts5 table configuration */ + int iCol; + i64 *aCnt; + i64 *aDoc; + + /* Output values used by 'row' and 'col' tables */ + i64 rowid; /* This table's current rowid value */ + Fts5Buffer term; /* Current value of 'term' column */ +}; + +#define FTS5_VOCAB_COL 0 +#define FTS5_VOCAB_ROW 1 + +#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt" +#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt" + +/* +** Bits for the mask used as the idxNum value by xBestIndex/xFilter. +*/ +#define FTS5_VOCAB_TERM_EQ 0x01 +#define FTS5_VOCAB_TERM_GE 0x02 +#define FTS5_VOCAB_TERM_LE 0x04 + + +/* +** Translate a string containing an fts5vocab table type to an +** FTS5_VOCAB_XXX constant. If successful, set *peType to the output +** value and return SQLITE_OK. Otherwise, set *pzErr to an error message +** and return SQLITE_ERROR. +*/ +static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){ + int rc = SQLITE_OK; + char *zCopy = sqlite3Fts5Strndup(&rc, zType, -1); + if( rc==SQLITE_OK ){ + sqlite3Fts5Dequote(zCopy); + if( sqlite3_stricmp(zCopy, "col")==0 ){ + *peType = FTS5_VOCAB_COL; + }else + + if( sqlite3_stricmp(zCopy, "row")==0 ){ + *peType = FTS5_VOCAB_ROW; + }else + { + *pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy); + rc = SQLITE_ERROR; + } + sqlite3_free(zCopy); + } + + return rc; +} + + +/* +** The xDisconnect() virtual table method. +*/ +static int fts5VocabDisconnectMethod(sqlite3_vtab *pVtab){ + Fts5VocabTable *pTab = (Fts5VocabTable*)pVtab; + sqlite3_free(pTab); + return SQLITE_OK; +} + +/* +** The xDestroy() virtual table method. +*/ +static int fts5VocabDestroyMethod(sqlite3_vtab *pVtab){ + Fts5VocabTable *pTab = (Fts5VocabTable*)pVtab; + sqlite3_free(pTab); + return SQLITE_OK; +} + +/* +** This function is the implementation of both the xConnect and xCreate +** methods of the FTS3 virtual table. +** +** The argv[] array contains the following: +** +** argv[0] -> module name ("fts5vocab") +** argv[1] -> database name +** argv[2] -> table name +** +** then: +** +** argv[3] -> name of fts5 table +** argv[4] -> type of fts5vocab table +** +** or, for tables in the TEMP schema only. +** +** argv[3] -> name of fts5 tables database +** argv[4] -> name of fts5 table +** argv[5] -> type of fts5vocab table +*/ +static int fts5VocabInitVtab( + sqlite3 *db, /* The SQLite database connection */ + void *pAux, /* Pointer to Fts5Global object */ + int argc, /* Number of elements in argv array */ + const char * const *argv, /* xCreate/xConnect argument array */ + sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ + char **pzErr /* Write any error message here */ +){ + const char *azSchema[] = { + "CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")", + "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")" + }; + + Fts5VocabTable *pRet = 0; + int rc = SQLITE_OK; /* Return code */ + int bDb; + + bDb = (argc==6 && strlen(argv[1])==4 && memcmp("temp", argv[1], 4)==0); + + if( argc!=5 && bDb==0 ){ + *pzErr = sqlite3_mprintf("wrong number of vtable arguments"); + rc = SQLITE_ERROR; + }else{ + 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]; + int nDb = (int)strlen(zDb)+1; + int nTab = (int)strlen(zTab)+1; + int eType = 0; + + rc = fts5VocabTableType(zType, pzErr, &eType); + if( rc==SQLITE_OK ){ + assert( eType>=0 && eTypepGlobal = (Fts5Global*)pAux; + pRet->eType = eType; + pRet->db = db; + pRet->zFts5Tbl = (char*)&pRet[1]; + pRet->zFts5Db = &pRet->zFts5Tbl[nTab]; + memcpy(pRet->zFts5Tbl, zTab, nTab); + memcpy(pRet->zFts5Db, zDb, nDb); + sqlite3Fts5Dequote(pRet->zFts5Tbl); + sqlite3Fts5Dequote(pRet->zFts5Db); + } + } + + *ppVTab = (sqlite3_vtab*)pRet; + return rc; +} + + +/* +** The xConnect() and xCreate() methods for the virtual table. All the +** work is done in function fts5VocabInitVtab(). +*/ +static int fts5VocabConnectMethod( + sqlite3 *db, /* Database connection */ + void *pAux, /* Pointer to tokenizer hash table */ + int argc, /* Number of elements in argv array */ + const char * const *argv, /* xCreate/xConnect argument array */ + sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ + char **pzErr /* OUT: sqlite3_malloc'd error message */ +){ + return fts5VocabInitVtab(db, pAux, argc, argv, ppVtab, pzErr); +} +static int fts5VocabCreateMethod( + sqlite3 *db, /* Database connection */ + void *pAux, /* Pointer to tokenizer hash table */ + int argc, /* Number of elements in argv array */ + const char * const *argv, /* xCreate/xConnect argument array */ + sqlite3_vtab **ppVtab, /* OUT: New sqlite3_vtab object */ + char **pzErr /* OUT: sqlite3_malloc'd error message */ +){ + return fts5VocabInitVtab(db, pAux, argc, argv, ppVtab, pzErr); +} + +/* +** Implementation of the xBestIndex method. +*/ +static int fts5VocabBestIndexMethod( + sqlite3_vtab *pUnused, + sqlite3_index_info *pInfo +){ + int i; + int iTermEq = -1; + int iTermGe = -1; + int iTermLe = -1; + int idxNum = 0; + int nArg = 0; + + UNUSED_PARAM(pUnused); + + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; + if( p->usable==0 ) continue; + if( p->iColumn==0 ){ /* term column */ + if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i; + if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i; + if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i; + if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i; + if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i; + } + } + + if( iTermEq>=0 ){ + idxNum |= FTS5_VOCAB_TERM_EQ; + pInfo->aConstraintUsage[iTermEq].argvIndex = ++nArg; + pInfo->estimatedCost = 100; + }else{ + pInfo->estimatedCost = 1000000; + if( iTermGe>=0 ){ + idxNum |= FTS5_VOCAB_TERM_GE; + pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg; + pInfo->estimatedCost = pInfo->estimatedCost / 2; + } + if( iTermLe>=0 ){ + idxNum |= FTS5_VOCAB_TERM_LE; + pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg; + pInfo->estimatedCost = pInfo->estimatedCost / 2; + } + } + + pInfo->idxNum = idxNum; + + return SQLITE_OK; +} + +/* +** Implementation of xOpen method. +*/ +static int fts5VocabOpenMethod( + sqlite3_vtab *pVTab, + sqlite3_vtab_cursor **ppCsr +){ + Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab; + Fts5Index *pIndex = 0; + Fts5Config *pConfig = 0; + Fts5VocabCursor *pCsr = 0; + int rc = SQLITE_OK; + sqlite3_stmt *pStmt = 0; + char *zSql = 0; + + zSql = sqlite3Fts5Mprintf(&rc, + "SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'", + pTab->zFts5Tbl, pTab->zFts5Db, pTab->zFts5Tbl, pTab->zFts5Tbl + ); + if( zSql ){ + rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0); + } + sqlite3_free(zSql); + assert( rc==SQLITE_OK || pStmt==0 ); + if( rc==SQLITE_ERROR ) rc = SQLITE_OK; + + if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ + i64 iId = sqlite3_column_int64(pStmt, 0); + pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig); + } + + if( rc==SQLITE_OK && pIndex==0 ){ + rc = sqlite3_finalize(pStmt); + pStmt = 0; + if( rc==SQLITE_OK ){ + pVTab->zErrMsg = sqlite3_mprintf( + "no such fts5 table: %s.%s", pTab->zFts5Db, pTab->zFts5Tbl + ); + rc = SQLITE_ERROR; + } + } + + if( rc==SQLITE_OK ){ + int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor); + pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte); + } + + if( pCsr ){ + pCsr->pIndex = pIndex; + pCsr->pStmt = pStmt; + pCsr->pConfig = pConfig; + pCsr->aCnt = (i64*)&pCsr[1]; + pCsr->aDoc = &pCsr->aCnt[pConfig->nCol]; + }else{ + sqlite3_finalize(pStmt); + } + + *ppCsr = (sqlite3_vtab_cursor*)pCsr; + return rc; +} + +static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){ + pCsr->rowid = 0; + sqlite3Fts5IterClose(pCsr->pIter); + pCsr->pIter = 0; + sqlite3_free(pCsr->zLeTerm); + pCsr->nLeTerm = -1; + pCsr->zLeTerm = 0; +} + +/* +** Close the cursor. For additional information see the documentation +** on the xClose method of the virtual table interface. +*/ +static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){ + Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; + fts5VocabResetCursor(pCsr); + sqlite3Fts5BufferFree(&pCsr->term); + sqlite3_finalize(pCsr->pStmt); + sqlite3_free(pCsr); + return SQLITE_OK; +} + + +/* +** Advance the cursor to the next row in the table. +*/ +static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ + Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; + Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab; + int rc = SQLITE_OK; + int nCol = pCsr->pConfig->nCol; + + pCsr->rowid++; + + if( pTab->eType==FTS5_VOCAB_COL ){ + for(pCsr->iCol++; pCsr->iColiCol++){ + if( pCsr->aDoc[pCsr->iCol] ) break; + } + } + + if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){ + if( sqlite3Fts5IterEof(pCsr->pIter) ){ + pCsr->bEof = 1; + }else{ + const char *zTerm; + int nTerm; + + zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); + if( pCsr->nLeTerm>=0 ){ + int nCmp = MIN(nTerm, pCsr->nLeTerm); + int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp); + if( bCmp<0 || (bCmp==0 && pCsr->nLeTermbEof = 1; + return SQLITE_OK; + } + } + + sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm); + memset(pCsr->aCnt, 0, nCol * sizeof(i64)); + memset(pCsr->aDoc, 0, nCol * sizeof(i64)); + pCsr->iCol = 0; + + assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); + while( rc==SQLITE_OK ){ + const u8 *pPos; int nPos; /* Position list */ + i64 iPos = 0; /* 64-bit position read from poslist */ + int iOff = 0; /* Current offset within position list */ + + pPos = pCsr->pIter->pData; + nPos = pCsr->pIter->nData; + switch( pCsr->pConfig->eDetail ){ + case FTS5_DETAIL_FULL: + pPos = pCsr->pIter->pData; + nPos = pCsr->pIter->nData; + if( pTab->eType==FTS5_VOCAB_ROW ){ + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ + pCsr->aCnt[0]++; + } + pCsr->aDoc[0]++; + }else{ + int iCol = -1; + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ + int ii = FTS5_POS2COLUMN(iPos); + pCsr->aCnt[ii]++; + if( iCol!=ii ){ + if( ii>=nCol ){ + rc = FTS5_CORRUPT; + break; + } + pCsr->aDoc[ii]++; + iCol = ii; + } + } + } + break; + + case FTS5_DETAIL_COLUMNS: + if( pTab->eType==FTS5_VOCAB_ROW ){ + pCsr->aDoc[0]++; + }else{ + while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ + assert_nc( iPos>=0 && iPos=nCol ){ + rc = FTS5_CORRUPT; + break; + } + pCsr->aDoc[iPos]++; + } + } + break; + + default: + assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); + pCsr->aDoc[0]++; + break; + } + + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IterNextScan(pCsr->pIter); + } + + if( rc==SQLITE_OK ){ + zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm); + if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){ + break; + } + if( sqlite3Fts5IterEof(pCsr->pIter) ) break; + } + } + } + } + + if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){ + while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++; + assert( pCsr->iColpConfig->nCol ); + } + return rc; +} + +/* +** This is the xFilter implementation for the virtual table. +*/ +static int fts5VocabFilterMethod( + sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ + int idxNum, /* Strategy index */ + const char *zUnused, /* Unused */ + int nUnused, /* Number of elements in apVal */ + sqlite3_value **apVal /* Arguments for the indexing scheme */ +){ + Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; + int rc = SQLITE_OK; + + int iVal = 0; + int f = FTS5INDEX_QUERY_SCAN; + const char *zTerm = 0; + int nTerm = 0; + + sqlite3_value *pEq = 0; + sqlite3_value *pGe = 0; + sqlite3_value *pLe = 0; + + UNUSED_PARAM2(zUnused, nUnused); + + fts5VocabResetCursor(pCsr); + if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++]; + if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++]; + if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++]; + + if( pEq ){ + zTerm = (const char *)sqlite3_value_text(pEq); + nTerm = sqlite3_value_bytes(pEq); + f = 0; + }else{ + if( pGe ){ + zTerm = (const char *)sqlite3_value_text(pGe); + nTerm = sqlite3_value_bytes(pGe); + } + if( pLe ){ + const char *zCopy = (const char *)sqlite3_value_text(pLe); + pCsr->nLeTerm = sqlite3_value_bytes(pLe); + pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1); + if( pCsr->zLeTerm==0 ){ + rc = SQLITE_NOMEM; + }else{ + memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1); + } + } + } + + + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter); + } + if( rc==SQLITE_OK ){ + rc = fts5VocabNextMethod(pCursor); + } + + return rc; +} + +/* +** This is the xEof method of the virtual table. SQLite calls this +** routine to find out if it has reached the end of a result set. +*/ +static int fts5VocabEofMethod(sqlite3_vtab_cursor *pCursor){ + Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; + return pCsr->bEof; +} + +static int fts5VocabColumnMethod( + sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ + sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ + int iCol /* Index of column to read value from */ +){ + Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; + int eDetail = pCsr->pConfig->eDetail; + int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType; + i64 iVal = 0; + + if( iCol==0 ){ + sqlite3_result_text( + pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT + ); + }else if( eType==FTS5_VOCAB_COL ){ + assert( iCol==1 || iCol==2 || iCol==3 ); + if( iCol==1 ){ + if( eDetail!=FTS5_DETAIL_NONE ){ + const char *z = pCsr->pConfig->azCol[pCsr->iCol]; + sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); + } + }else if( iCol==2 ){ + iVal = pCsr->aDoc[pCsr->iCol]; + }else{ + iVal = pCsr->aCnt[pCsr->iCol]; + } + }else{ + assert( iCol==1 || iCol==2 ); + if( iCol==1 ){ + iVal = pCsr->aDoc[0]; + }else{ + iVal = pCsr->aCnt[0]; + } + } + + if( iVal>0 ) sqlite3_result_int64(pCtx, iVal); + return SQLITE_OK; +} + +/* +** This is the xRowid method. The SQLite core calls this routine to +** retrieve the rowid for the current row of the result set. The +** rowid should be written to *pRowid. +*/ +static int fts5VocabRowidMethod( + sqlite3_vtab_cursor *pCursor, + sqlite_int64 *pRowid +){ + Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; + *pRowid = pCsr->rowid; + return SQLITE_OK; +} + +int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){ + static const sqlite3_module fts5Vocab = { + /* iVersion */ 2, + /* xCreate */ fts5VocabCreateMethod, + /* xConnect */ fts5VocabConnectMethod, + /* xBestIndex */ fts5VocabBestIndexMethod, + /* xDisconnect */ fts5VocabDisconnectMethod, + /* xDestroy */ fts5VocabDestroyMethod, + /* xOpen */ fts5VocabOpenMethod, + /* xClose */ fts5VocabCloseMethod, + /* xFilter */ fts5VocabFilterMethod, + /* xNext */ fts5VocabNextMethod, + /* xEof */ fts5VocabEofMethod, + /* xColumn */ fts5VocabColumnMethod, + /* xRowid */ fts5VocabRowidMethod, + /* xUpdate */ 0, + /* xBegin */ 0, + /* xSync */ 0, + /* xCommit */ 0, + /* xRollback */ 0, + /* xFindFunction */ 0, + /* xRename */ 0, + /* xSavepoint */ 0, + /* xRelease */ 0, + /* xRollbackTo */ 0, + }; + void *p = (void*)pGlobal; + + return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0); +} + + diff --git a/ext/fts5/fts5parse.y b/ext/fts5/fts5parse.y new file mode 100644 index 0000000..4393676 --- /dev/null +++ b/ext/fts5/fts5parse.y @@ -0,0 +1,184 @@ +/* +** 2014 May 31 +** +** 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. +** +****************************************************************************** +** +*/ + + +// All token codes are small integers with #defines that begin with "TK_" +%token_prefix FTS5_ + +// The type of the data attached to each token is Token. This is also the +// default type for non-terminals. +// +%token_type {Fts5Token} +%default_type {Fts5Token} + +// The generated parser function takes a 4th argument as follows: +%extra_argument {Fts5Parse *pParse} + +// This code runs whenever there is a syntax error +// +%syntax_error { + UNUSED_PARAM(yymajor); /* Silence a compiler warning */ + sqlite3Fts5ParseError( + pParse, "fts5: syntax error near \"%.*s\"",TOKEN.n,TOKEN.p + ); +} +%stack_overflow { + UNUSED_PARAM(yypMinor); /* Silence a compiler warning */ + sqlite3Fts5ParseError(pParse, "fts5: parser stack overflow"); +} + +// The name of the generated procedure that implements the parser +// is as follows: +%name sqlite3Fts5Parser + +// The following text is included near the beginning of the C source +// code file that implements the parser. +// +%include { +#include "fts5Int.h" +#include "fts5parse.h" + +/* +** Disable all error recovery processing in the parser push-down +** automaton. +*/ +#define YYNOERRORRECOVERY 1 + +/* +** Make yytestcase() the same as testcase() +*/ +#define yytestcase(X) testcase(X) + +/* +** Indicate that sqlite3ParserFree() will never be called with a null +** pointer. +*/ +#define YYPARSEFREENOTNULL 1 + +/* +** Alternative datatype for the argument to the malloc() routine passed +** into sqlite3ParserAlloc(). The default is size_t. +*/ +#define YYMALLOCARGTYPE u64 + +} // end %include + +%left OR. +%left AND. +%left NOT. +%left TERM. +%left COLON. + +input ::= expr(X). { sqlite3Fts5ParseFinished(pParse, X); } +%destructor input { (void)pParse; } + +%type cnearset {Fts5ExprNode*} +%type expr {Fts5ExprNode*} +%type exprlist {Fts5ExprNode*} +%destructor cnearset { sqlite3Fts5ParseNodeFree($$); } +%destructor expr { sqlite3Fts5ParseNodeFree($$); } +%destructor exprlist { sqlite3Fts5ParseNodeFree($$); } + +expr(A) ::= expr(X) AND expr(Y). { + A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0); +} +expr(A) ::= expr(X) OR expr(Y). { + A = sqlite3Fts5ParseNode(pParse, FTS5_OR, X, Y, 0); +} +expr(A) ::= expr(X) NOT expr(Y). { + A = sqlite3Fts5ParseNode(pParse, FTS5_NOT, X, Y, 0); +} + +expr(A) ::= LP expr(X) RP. {A = X;} +expr(A) ::= exprlist(X). {A = X;} + +exprlist(A) ::= cnearset(X). {A = X;} +exprlist(A) ::= exprlist(X) cnearset(Y). { + A = sqlite3Fts5ParseNode(pParse, FTS5_AND, X, Y, 0); +} + +cnearset(A) ::= nearset(X). { + A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, X); +} +cnearset(A) ::= colset(X) COLON nearset(Y). { + sqlite3Fts5ParseSetColset(pParse, Y, X); + A = sqlite3Fts5ParseNode(pParse, FTS5_STRING, 0, 0, Y); +} + +%type colset {Fts5Colset*} +%destructor colset { sqlite3_free($$); } +%type colsetlist {Fts5Colset*} +%destructor colsetlist { sqlite3_free($$); } + +colset(A) ::= LCP colsetlist(X) RCP. { A = X; } +colset(A) ::= STRING(X). { + A = sqlite3Fts5ParseColset(pParse, 0, &X); +} + +colsetlist(A) ::= colsetlist(Y) STRING(X). { + A = sqlite3Fts5ParseColset(pParse, Y, &X); } +colsetlist(A) ::= STRING(X). { + A = sqlite3Fts5ParseColset(pParse, 0, &X); +} + + +%type nearset {Fts5ExprNearset*} +%type nearphrases {Fts5ExprNearset*} +%destructor nearset { sqlite3Fts5ParseNearsetFree($$); } +%destructor nearphrases { sqlite3Fts5ParseNearsetFree($$); } + +nearset(A) ::= phrase(X). { A = sqlite3Fts5ParseNearset(pParse, 0, X); } +nearset(A) ::= STRING(X) LP nearphrases(Y) neardist_opt(Z) RP. { + sqlite3Fts5ParseNear(pParse, &X); + sqlite3Fts5ParseSetDistance(pParse, Y, &Z); + A = Y; +} + +nearphrases(A) ::= phrase(X). { + A = sqlite3Fts5ParseNearset(pParse, 0, X); +} +nearphrases(A) ::= nearphrases(X) phrase(Y). { + A = sqlite3Fts5ParseNearset(pParse, X, Y); +} + +/* +** The optional ", " at the end of the NEAR() arguments. +*/ +neardist_opt(A) ::= . { A.p = 0; A.n = 0; } +neardist_opt(A) ::= COMMA STRING(X). { A = X; } + +/* +** A phrase. A set of primitives connected by "+" operators. Examples: +** +** "the" + "quick brown" + fo * +** "the quick brown fo" * +** the+quick+brown+fo* +*/ +%type phrase {Fts5ExprPhrase*} +%destructor phrase { sqlite3Fts5ParsePhraseFree($$); } + +phrase(A) ::= phrase(X) PLUS STRING(Y) star_opt(Z). { + A = sqlite3Fts5ParseTerm(pParse, X, &Y, Z); +} +phrase(A) ::= STRING(Y) star_opt(Z). { + A = sqlite3Fts5ParseTerm(pParse, 0, &Y, Z); +} + +/* +** Optional "*" character. +*/ +%type star_opt {int} + +star_opt(A) ::= STAR. { A = 1; } +star_opt(A) ::= . { A = 0; } diff --git a/ext/fts5/mkportersteps.tcl b/ext/fts5/mkportersteps.tcl new file mode 100644 index 0000000..b6214c6 --- /dev/null +++ b/ext/fts5/mkportersteps.tcl @@ -0,0 +1,222 @@ +# +# 2014 Jun 09 +# +# 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 script generates the implementations of the following C functions, +# which are part of the porter tokenizer implementation: +# +# static int fts5PorterStep1B(char *aBuf, int *pnBuf); +# static int fts5PorterStep1B2(char *aBuf, int *pnBuf); +# static int fts5PorterStep2(char *aBuf, int *pnBuf); +# static int fts5PorterStep3(char *aBuf, int *pnBuf); +# static int fts5PorterStep4(char *aBuf, int *pnBuf); +# + +set O(Step1B2) { + { at {} ate 1 } + { bl {} ble 1 } + { iz {} ize 1 } +} + +set O(Step1B) { + { "eed" fts5Porter_MGt0 "ee" 0 } + { "ed" fts5Porter_Vowel "" 1 } + { "ing" fts5Porter_Vowel "" 1 } +} + +set O(Step2) { + { "ational" fts5Porter_MGt0 "ate" } + { "tional" fts5Porter_MGt0 "tion" } + { "enci" fts5Porter_MGt0 "ence" } + { "anci" fts5Porter_MGt0 "ance" } + { "izer" fts5Porter_MGt0 "ize" } + { "logi" fts5Porter_MGt0 "log" } + { "bli" fts5Porter_MGt0 "ble" } + { "alli" fts5Porter_MGt0 "al" } + { "entli" fts5Porter_MGt0 "ent" } + { "eli" fts5Porter_MGt0 "e" } + { "ousli" fts5Porter_MGt0 "ous" } + { "ization" fts5Porter_MGt0 "ize" } + { "ation" fts5Porter_MGt0 "ate" } + { "ator" fts5Porter_MGt0 "ate" } + { "alism" fts5Porter_MGt0 "al" } + { "iveness" fts5Porter_MGt0 "ive" } + { "fulness" fts5Porter_MGt0 "ful" } + { "ousness" fts5Porter_MGt0 "ous" } + { "aliti" fts5Porter_MGt0 "al" } + { "iviti" fts5Porter_MGt0 "ive" } + { "biliti" fts5Porter_MGt0 "ble" } +} + +set O(Step3) { + { "icate" fts5Porter_MGt0 "ic" } + { "ative" fts5Porter_MGt0 "" } + { "alize" fts5Porter_MGt0 "al" } + { "iciti" fts5Porter_MGt0 "ic" } + { "ical" fts5Porter_MGt0 "ic" } + { "ful" fts5Porter_MGt0 "" } + { "ness" fts5Porter_MGt0 "" } +} + +set O(Step4) { + { "al" fts5Porter_MGt1 "" } + { "ance" fts5Porter_MGt1 "" } + { "ence" fts5Porter_MGt1 "" } + { "er" fts5Porter_MGt1 "" } + { "ic" fts5Porter_MGt1 "" } + { "able" fts5Porter_MGt1 "" } + { "ible" fts5Porter_MGt1 "" } + { "ant" fts5Porter_MGt1 "" } + { "ement" fts5Porter_MGt1 "" } + { "ment" fts5Porter_MGt1 "" } + { "ent" fts5Porter_MGt1 "" } + { "ion" fts5Porter_MGt1_and_S_or_T "" } + { "ou" fts5Porter_MGt1 "" } + { "ism" fts5Porter_MGt1 "" } + { "ate" fts5Porter_MGt1 "" } + { "iti" fts5Porter_MGt1 "" } + { "ous" fts5Porter_MGt1 "" } + { "ive" fts5Porter_MGt1 "" } + { "ize" fts5Porter_MGt1 "" } +} + +proc sort_cb {lhs rhs} { + set L [string range [lindex $lhs 0] end-1 end-1] + set R [string range [lindex $rhs 0] end-1 end-1] + string compare $L $R +} + +proc create_step_function {name data} { + + set T(function) { +static int fts5Porter${name}(char *aBuf, int *pnBuf){ + int ret = 0; + int nBuf = *pnBuf; + switch( aBuf[nBuf-2] ){ + ${switchbody} + } + return ret; +} + } + + set T(case) { + case '${k}': + ${ifstmts} + break; + } + + set T(if_0_0_0) { + if( ${match} ){ + *pnBuf = nBuf - $n; + } + } + set T(if_1_0_0) { + if( ${match} ){ + if( ${cond} ){ + *pnBuf = nBuf - $n; + } + } + } + set T(if_0_1_0) { + if( ${match} ){ + ${memcpy} + *pnBuf = nBuf - $n + $nRep; + } + } + set T(if_1_1_0) { + if( ${match} ){ + if( ${cond} ){ + ${memcpy} + *pnBuf = nBuf - $n + $nRep; + } + } + } + set T(if_1_0_1) { + if( ${match} ){ + if( ${cond} ){ + *pnBuf = nBuf - $n; + ret = 1; + } + } + } + set T(if_0_1_1) { + if( ${match} ){ + ${memcpy} + *pnBuf = nBuf - $n + $nRep; + ret = 1; + } + } + set T(if_1_1_1) { + if( ${match} ){ + if( ${cond} ){ + ${memcpy} + *pnBuf = nBuf - $n + $nRep; + ret = 1; + } + } + } + + set switchbody "" + + foreach I $data { + set k [string range [lindex $I 0] end-1 end-1] + lappend aCase($k) $I + } + foreach k [lsort [array names aCase]] { + set ifstmts "" + foreach I $aCase($k) { + set zSuffix [lindex $I 0] ;# Suffix text for this rule + set zRep [lindex $I 2] ;# Replacement text for rule + set xCond [lindex $I 1] ;# Condition callback (or "") + + set n [string length $zSuffix] + set nRep [string length $zRep] + + set match "nBuf>$n && 0==memcmp(\"$zSuffix\", &aBuf\[nBuf-$n\], $n)" + set memcpy "memcpy(&aBuf\[nBuf-$n\], \"$zRep\", $nRep);" + set cond "${xCond}(aBuf, nBuf-$n)" + + set bMemcpy [expr {$nRep>0}] + set bCond [expr {$xCond!=""}] + set bRet [expr {[llength $I]>3 && [lindex $I 3]}] + + set t $T(if_${bCond}_${bMemcpy}_${bRet}) + lappend ifstmts [string trim [subst -nocommands $t]] + } + + set ifstmts [join $ifstmts "else "] + + append switchbody [subst -nocommands $T(case)] + } + + + puts [subst -nocommands $T(function)] +} + + +puts [string trim { +/************************************************************************** +*************************************************************************** +** GENERATED CODE STARTS HERE (mkportersteps.tcl) +*/ +}] +foreach step [array names O] { + create_step_function $step $O($step) +} +puts [string trim { +/* +** GENERATED CODE ENDS HERE (mkportersteps.tcl) +*************************************************************************** +**************************************************************************/ +}] + + + diff --git a/ext/fts5/test/fts5_common.tcl b/ext/fts5/test/fts5_common.tcl new file mode 100644 index 0000000..cf688dc --- /dev/null +++ b/ext/fts5/test/fts5_common.tcl @@ -0,0 +1,642 @@ +# 2014 Dec 19 +# +# 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. +# +#*********************************************************************** +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. .. test] +} +source $testdir/tester.tcl + +ifcapable !fts5 { + finish_test + return +} + +catch { + sqlite3_fts5_may_be_corrupt 0 + reset_db +} + +# If SQLITE_ENABLE_FTS5 is not defined, skip this test. +ifcapable !fts5 { + finish_test + return +} + +proc fts5_test_poslist {cmd} { + set res [list] + for {set i 0} {$i < [$cmd xInstCount]} {incr i} { + lappend res [string map {{ } .} [$cmd xInst $i]] + } + set res +} + +proc fts5_test_poslist2 {cmd} { + set res [list] + + for {set i 0} {$i < [$cmd xPhraseCount]} {incr i} { + $cmd xPhraseForeach $i c o { + lappend res $i.$c.$o + } + } + + #set res + sort_poslist $res +} + +proc fts5_test_collist {cmd} { + set res [list] + + for {set i 0} {$i < [$cmd xPhraseCount]} {incr i} { + $cmd xPhraseColumnForeach $i c { lappend res $i.$c } + } + + set res +} + +proc fts5_test_columnsize {cmd} { + set res [list] + for {set i 0} {$i < [$cmd xColumnCount]} {incr i} { + lappend res [$cmd xColumnSize $i] + } + set res +} + +proc fts5_test_columntext {cmd} { + set res [list] + for {set i 0} {$i < [$cmd xColumnCount]} {incr i} { + lappend res [$cmd xColumnText $i] + } + set res +} + +proc fts5_test_columntotalsize {cmd} { + set res [list] + for {set i 0} {$i < [$cmd xColumnCount]} {incr i} { + lappend res [$cmd xColumnTotalSize $i] + } + set res +} + +proc test_append_token {varname token iStart iEnd} { + upvar $varname var + lappend var $token + return "SQLITE_OK" +} +proc fts5_test_tokenize {cmd} { + set res [list] + for {set i 0} {$i < [$cmd xColumnCount]} {incr i} { + set tokens [list] + $cmd xTokenize [$cmd xColumnText $i] [list test_append_token tokens] + lappend res $tokens + } + set res +} + +proc fts5_test_rowcount {cmd} { + $cmd xRowCount +} + +proc test_queryphrase_cb {cnt cmd} { + upvar $cnt L + for {set i 0} {$i < [$cmd xInstCount]} {incr i} { + foreach {ip ic io} [$cmd xInst $i] break + set A($ic) 1 + } + foreach ic [array names A] { + lset L $ic [expr {[lindex $L $ic] + 1}] + } +} +proc fts5_test_queryphrase {cmd} { + set res [list] + for {set i 0} {$i < [$cmd xPhraseCount]} {incr i} { + set cnt [list] + for {set j 0} {$j < [$cmd xColumnCount]} {incr j} { lappend cnt 0 } + $cmd xQueryPhrase $i [list test_queryphrase_cb cnt] + lappend res $cnt + } + set res +} + +proc fts5_test_phrasecount {cmd} { + $cmd xPhraseCount +} + +proc fts5_test_all {cmd} { + set res [list] + lappend res columnsize [fts5_test_columnsize $cmd] + lappend res columntext [fts5_test_columntext $cmd] + lappend res columntotalsize [fts5_test_columntotalsize $cmd] + lappend res poslist [fts5_test_poslist $cmd] + lappend res tokenize [fts5_test_tokenize $cmd] + lappend res rowcount [fts5_test_rowcount $cmd] + set res +} + +proc fts5_aux_test_functions {db} { + foreach f { + fts5_test_columnsize + fts5_test_columntext + fts5_test_columntotalsize + fts5_test_poslist + fts5_test_poslist2 + fts5_test_collist + fts5_test_tokenize + fts5_test_rowcount + fts5_test_all + + fts5_test_queryphrase + fts5_test_phrasecount + } { + sqlite3_fts5_create_function $db $f $f + } +} + +proc fts5_level_segs {tbl} { + set sql "SELECT fts5_decode(rowid,block) aS r FROM ${tbl}_data WHERE rowid=10" + set ret [list] + foreach L [lrange [db one $sql] 1 end] { + lappend ret [expr [llength $L] - 3] + } + set ret +} + +proc fts5_level_segids {tbl} { + set sql "SELECT fts5_decode(rowid,block) aS r FROM ${tbl}_data WHERE rowid=10" + set ret [list] + foreach L [lrange [db one $sql] 1 end] { + set lvl [list] + foreach S [lrange $L 3 end] { + regexp {id=([1234567890]*)} $S -> segid + lappend lvl $segid + } + lappend ret $lvl + } + set ret +} + +proc fts5_rnddoc {n} { + set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] + set doc [list] + for {set i 0} {$i < $n} {incr i} { + lappend doc "x[string map $map [format %.3d [expr int(rand()*1000)]]]" + } + set doc +} + +#------------------------------------------------------------------------- +# Usage: +# +# nearset aCol ?-pc VARNAME? ?-near N? ?-col C? -- phrase1 phrase2... +# +# This command is used to test if a document (set of column values) matches +# the logical equivalent of a single FTS5 NEAR() clump and, if so, return +# the equivalent of an FTS5 position list. +# +# Parameter $aCol is passed a list of the column values for the document +# to test. Parameters $phrase1 and so on are the phrases. +# +# The result is a list of phrase hits. Each phrase hit is formatted as +# three integers separated by "." characters, in the following format: +# +# . . +# +# Options: +# +# -near N (NEAR distance. Default 10) +# -col C (List of column indexes to match against) +# -pc VARNAME (variable in caller frame to use for phrase numbering) +# -dict VARNAME (array in caller frame to use for synonyms) +# +proc nearset {aCol args} { + + # Process the command line options. + # + set O(-near) 10 + set O(-col) {} + set O(-pc) "" + set O(-dict) "" + + set nOpt [lsearch -exact $args --] + if {$nOpt<0} { error "no -- option" } + + # Set $lPhrase to be a list of phrases. $nPhrase its length. + set lPhrase [lrange $args [expr $nOpt+1] end] + set nPhrase [llength $lPhrase] + + foreach {k v} [lrange $args 0 [expr $nOpt-1]] { + if {[info exists O($k)]==0} { error "unrecognized option $k" } + set O($k) $v + } + + if {$O(-pc) == ""} { + set counter 0 + } else { + upvar $O(-pc) counter + } + + if {$O(-dict)!=""} { upvar $O(-dict) aDict } + + for {set j 0} {$j < [llength $aCol]} {incr j} { + for {set i 0} {$i < $nPhrase} {incr i} { + set A($j,$i) [list] + } + } + + # Loop through each column of the current row. + for {set iCol 0} {$iCol < [llength $aCol]} {incr iCol} { + + # If there is a column filter, test whether this column is excluded. If + # so, skip to the next iteration of this loop. Otherwise, set zCol to the + # column value and nToken to the number of tokens that comprise it. + if {$O(-col)!="" && [lsearch $O(-col) $iCol]<0} continue + set zCol [lindex $aCol $iCol] + set nToken [llength $zCol] + + # Each iteration of the following loop searches a substring of the + # column value for phrase matches. The last token of the substring + # is token $iLast of the column value. The first token is: + # + # iFirst = ($iLast - $O(-near) - 1) + # + # where $sz is the length of the phrase being searched for. A phrase + # counts as matching the substring if its first token lies on or before + # $iLast and its last token on or after $iFirst. + # + # For example, if the query is "NEAR(a+b c, 2)" and the column value: + # + # "x x x x A B x x C x" + # 0 1 2 3 4 5 6 7 8 9" + # + # when (iLast==8 && iFirst=5) the range will contain both phrases and + # so both instances can be added to the output poslists. + # + set iLast [expr $O(-near) >= $nToken ? $nToken - 1 : $O(-near)] + for { } {$iLast < $nToken} {incr iLast} { + + catch { array unset B } + + for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} { + set p [lindex $lPhrase $iPhrase] + set nPm1 [expr {[llength $p] - 1}] + set iFirst [expr $iLast - $O(-near) - [llength $p]] + + for {set i $iFirst} {$i <= $iLast} {incr i} { + set lCand [lrange $zCol $i [expr $i+$nPm1]] + set bMatch 1 + foreach tok $p term $lCand { + if {[nearset_match aDict $tok $term]==0} { set bMatch 0 ; break } + } + if {$bMatch} { lappend B($iPhrase) $i } + } + + if {![info exists B($iPhrase)]} break + } + + if {$iPhrase==$nPhrase} { + for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} { + set A($iCol,$iPhrase) [concat $A($iCol,$iPhrase) $B($iPhrase)] + set A($iCol,$iPhrase) [lsort -integer -uniq $A($iCol,$iPhrase)] + } + } + } + } + + set res [list] + #puts [array names A] + + for {set iPhrase 0} {$iPhrase<$nPhrase} {incr iPhrase} { + for {set iCol 0} {$iCol < [llength $aCol]} {incr iCol} { + foreach a $A($iCol,$iPhrase) { + lappend res "$counter.$iCol.$a" + } + } + incr counter + } + + #puts "$aCol -> $res" + sort_poslist $res +} + +proc nearset_match {aDictVar tok term} { + if {[string match $tok $term]} { return 1 } + + upvar $aDictVar aDict + if {[info exists aDict($tok)]} { + foreach s $aDict($tok) { + if {[string match $s $term]} { return 1 } + } + } + return 0; +} + +#------------------------------------------------------------------------- +# Usage: +# +# sort_poslist LIST +# +# Sort a position list of the type returned by command [nearset] +# +proc sort_poslist {L} { + lsort -command instcompare $L +} +proc instcompare {lhs rhs} { + foreach {p1 c1 o1} [split $lhs .] {} + foreach {p2 c2 o2} [split $rhs .] {} + + set res [expr $c1 - $c2] + if {$res==0} { set res [expr $o1 - $o2] } + if {$res==0} { set res [expr $p1 - $p2] } + + return $res +} + +#------------------------------------------------------------------------- +# Logical operators used by the commands returned by fts5_tcl_expr(). +# +proc AND {args} { + foreach a $args { + if {[llength $a]==0} { return [list] } + } + sort_poslist [concat {*}$args] +} +proc OR {args} { + sort_poslist [concat {*}$args] +} +proc NOT {a b} { + if {[llength $b]>0} { return [list] } + return $a +} + +#------------------------------------------------------------------------- +# This command is similar to [split], except that it also provides the +# start and end offsets of each token. For example: +# +# [fts5_tokenize_split "abc d ef"] -> {abc 0 3 d 4 5 ef 6 8} +# + +proc gobble_whitespace {textvar} { + upvar $textvar t + regexp {([ ]*)(.*)} $t -> space t + return [string length $space] +} + +proc gobble_text {textvar wordvar} { + upvar $textvar t + upvar $wordvar w + regexp {([^ ]*)(.*)} $t -> w t + return [string length $w] +} + +proc fts5_tokenize_split {text} { + set token "" + set ret [list] + set iOff [gobble_whitespace text] + while {[set nToken [gobble_text text word]]} { + lappend ret $word $iOff [expr $iOff+$nToken] + incr iOff $nToken + incr iOff [gobble_whitespace text] + } + + set ret +} + +#------------------------------------------------------------------------- +# +proc foreach_detail_mode {prefix script} { + set saved $::testprefix + foreach d [list full col none] { + set s [string map [list %DETAIL% $d] $script] + set ::detail $d + set ::testprefix "$prefix-$d" + reset_db + uplevel $s + unset ::detail + } + set ::testprefix $saved +} + +proc detail_check {} { + if {$::detail != "none" && $::detail!="full" && $::detail!="col"} { + error "not in foreach_detail_mode {...} block" + } +} +proc detail_is_none {} { detail_check ; expr {$::detail == "none"} } +proc detail_is_col {} { detail_check ; expr {$::detail == "col" } } +proc detail_is_full {} { detail_check ; expr {$::detail == "full"} } + + +#------------------------------------------------------------------------- +# Convert a poslist of the type returned by fts5_test_poslist() to a +# collist as returned by fts5_test_collist(). +# +proc fts5_poslist2collist {poslist} { + set res [list] + foreach h $poslist { + regexp {(.*)\.[1234567890]+} $h -> cand + lappend res $cand + } + set res [lsort -command fts5_collist_elem_compare -unique $res] + return $res +} + +# Comparison function used by fts5_poslist2collist to sort collist entries. +proc fts5_collist_elem_compare {a b} { + foreach {a1 a2} [split $a .] {} + foreach {b1 b2} [split $b .] {} + + if {$a1==$b1} { return [expr $a2 - $b2] } + return [expr $a1 - $b1] +} + + +#-------------------------------------------------------------------------- +# Construct and return a tcl list equivalent to that returned by the SQL +# query executed against database handle [db]: +# +# SELECT +# rowid, +# fts5_test_poslist($tbl), +# fts5_test_collist($tbl) +# FROM $tbl('$expr') +# ORDER BY rowid $order; +# +proc fts5_query_data {expr tbl {order ASC} {aDictVar ""}} { + + # Figure out the set of columns in the FTS5 table. This routine does + # not handle tables with UNINDEXED columns, but if it did, it would + # have to be here. + db eval "PRAGMA table_info = $tbl" x { lappend lCols $x(name) } + + set d "" + if {$aDictVar != ""} { + upvar $aDictVar aDict + set d aDict + } + + set cols "" + foreach e $lCols { append cols ", '$e'" } + set tclexpr [db one [subst -novar { + SELECT fts5_expr_tcl( $expr, 'nearset $cols -dict $d -pc ::pc' [set cols] ) + }]] + + set res [list] + db eval "SELECT rowid, * FROM $tbl ORDER BY rowid $order" x { + set cols [list] + foreach col $lCols { lappend cols $x($col) } + + set ::pc 0 + set rowdata [eval $tclexpr] + if {$rowdata != ""} { + lappend res $x(rowid) $rowdata [fts5_poslist2collist $rowdata] + } + } + + set res +} + +#------------------------------------------------------------------------- +# Similar to [fts5_query_data], but omit the collist field. +# +proc fts5_poslist_data {expr tbl {order ASC} {aDictVar ""}} { + set res [list] + + if {$aDictVar!=""} { + upvar $aDictVar aDict + set dict aDict + } else { + set dict "" + } + + foreach {rowid poslist collist} [fts5_query_data $expr $tbl $order $dict] { + lappend res $rowid $poslist + } + set res +} + +proc fts5_collist_data {expr tbl {order ASC} {aDictVar ""}} { + set res [list] + + if {$aDictVar!=""} { + upvar $aDictVar aDict + set dict aDict + } else { + set dict "" + } + + foreach {rowid poslist collist} [fts5_query_data $expr $tbl $order $dict] { + lappend res $rowid $collist + } + set res +} + +#------------------------------------------------------------------------- +# + +# This command will only work inside a [foreach_detail_mode] block. It tests +# whether or not expression $expr run on FTS5 table $tbl is supported by +# the current mode. If so, 1 is returned. If not, 0. +# +# detail=full (all queries supported) +# detail=col (all but phrase queries and NEAR queries) +# detail=none (all but phrase queries, NEAR queries, and column filters) +# +proc fts5_expr_ok {expr tbl} { + + if {![detail_is_full]} { + set nearset "nearset_rc" + if {[detail_is_col]} { set nearset "nearset_rf" } + + set ::expr_not_ok 0 + db eval "PRAGMA table_info = $tbl" x { lappend lCols $x(name) } + + set cols "" + foreach e $lCols { append cols ", '$e'" } + set ::pc 0 + set tclexpr [db one [subst -novar { + SELECT fts5_expr_tcl( $expr, '[set nearset] $cols -pc ::pc' [set cols] ) + }]] + eval $tclexpr + if {$::expr_not_ok} { return 0 } + } + + return 1 +} + +# Helper for [fts5_expr_ok] +proc nearset_rf {aCol args} { + set idx [lsearch -exact $args --] + if {$idx != [llength $args]-2 || [llength [lindex $args end]]!=1} { + set ::expr_not_ok 1 + } + list +} + +# Helper for [fts5_expr_ok] +proc nearset_rc {aCol args} { + nearset_rf $aCol {*}$args + if {[lsearch $args -col]>=0} { + set ::expr_not_ok 1 + } + list +} + + +#------------------------------------------------------------------------- +# Code for a simple Tcl tokenizer that supports synonyms at query time. +# +proc tclnum_tokenize {mode tflags text} { + foreach {w iStart iEnd} [fts5_tokenize_split $text] { + sqlite3_fts5_token $w $iStart $iEnd + if {$tflags == $mode && [info exists ::tclnum_syn($w)]} { + foreach s $::tclnum_syn($w) { sqlite3_fts5_token -colo $s $iStart $iEnd } + } + } +} + +proc tclnum_create {args} { + set mode query + if {[llength $args]} { + set mode [lindex $args 0] + } + if {$mode != "query" && $mode != "document"} { error "bad mode: $mode" } + return [list tclnum_tokenize $mode] +} + +proc fts5_tclnum_register {db} { + foreach SYNDICT { + {zero 0} + {one 1 i} + {two 2 ii} + {three 3 iii} + {four 4 iv} + {five 5 v} + {six 6 vi} + {seven 7 vii} + {eight 8 viii} + {nine 9 ix} + + {a1 a2 a3 a4 a5 a6 a7 a8 a9} + {b1 b2 b3 b4 b5 b6 b7 b8 b9} + {c1 c2 c3 c4 c5 c6 c7 c8 c9} + } { + foreach s $SYNDICT { + set o [list] + foreach x $SYNDICT {if {$x!=$s} {lappend o $x}} + set ::tclnum_syn($s) $o + } + } + sqlite3_fts5_create_tokenizer db tclnum tclnum_create +} +# +# End of tokenizer code. +#------------------------------------------------------------------------- + diff --git a/ext/fts5/test/fts5aa.test b/ext/fts5/test/fts5aa.test new file mode 100644 index 0000000..fdcf083 --- /dev/null +++ b/ext/fts5/test/fts5aa.test @@ -0,0 +1,562 @@ +# 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 fts5aa + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $::testprefix { + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c); + SELECT name, sql FROM sqlite_master; +} { + t1 {CREATE VIRTUAL TABLE t1 USING fts5(a, b, c)} + t1_data {CREATE TABLE 't1_data'(id INTEGER PRIMARY KEY, block BLOB)} + t1_idx {CREATE TABLE 't1_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID} + t1_content {CREATE TABLE 't1_content'(id INTEGER PRIMARY KEY, c0, c1, c2)} + t1_docsize {CREATE TABLE 't1_docsize'(id INTEGER PRIMARY KEY, sz BLOB)} + t1_config {CREATE TABLE 't1_config'(k PRIMARY KEY, v) WITHOUT ROWID} +} + +do_execsql_test 1.1 { + DROP TABLE t1; + SELECT name, sql FROM sqlite_master; +} { +} + +#------------------------------------------------------------------------- +# + +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=%DETAIL%); +} +do_execsql_test 2.1 { + INSERT INTO t1 VALUES('a b c', 'd e f'); +} + +do_test 2.2 { + execsql { SELECT fts5_decode(id, block) FROM t1_data WHERE id==10 } +} {/{{structure} {lvl=0 nMerge=0 nSeg=1 {id=[0123456789]* leaves=1..1}}}/} + +foreach w {a b c d e f} { + do_execsql_test 2.3.$w.asc { + SELECT rowid FROM t1 WHERE t1 MATCH $w; + } {1} + do_execsql_test 2.3.$w.desc { + SELECT rowid FROM t1 WHERE t1 MATCH $w ORDER BY rowid DESC; + } {1} +} + +do_execsql_test 2.4 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%); +} +foreach {i x y} { + 1 {g f d b f} {h h e i a} + 2 {f i g j e} {i j c f f} + 3 {e e i f a} {e h f d f} + 4 {h j f j i} {h a c f j} + 5 {d b j c g} {f e i b e} + 6 {a j a e e} {j d f d e} + 7 {g i j c h} {j d h c a} + 8 {j j i d d} {e e d f b} + 9 {c j j d c} {h j i f g} + 10 {b f h i a} {c f b b j} +} { + do_execsql_test 3.$i.1 { INSERT INTO t1 VALUES($x, $y) } + do_execsql_test 3.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check') } + if {[set_test_counter errors]} break +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} +foreach {i x y} { + 1 {g f d b f} {h h e i a} + 2 {f i g j e} {i j c f f} + 3 {e e i f a} {e h f d f} + 4 {h j f j i} {h a c f j} + 5 {d b j c g} {f e i b e} + 6 {a j a e e} {j d f d e} + 7 {g i j c h} {j d h c a} + 8 {j j i d d} {e e d f b} + 9 {c j j d c} {h j i f g} + 10 {b f h i a} {c f b b j} +} { + do_execsql_test 4.$i.1 { INSERT INTO t1 VALUES($x, $y) } + do_execsql_test 4.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check') } + if {[set_test_counter errors]} break +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} +foreach {i x y} { + 1 {dd abc abc abc abcde} {aaa dd ddd ddd aab} + 2 {dd aab d aaa b} {abcde c aaa aaa aaa} + 3 {abcde dd b b dd} {abc abc d abc ddddd} + 4 {aaa abcde dddd dddd abcde} {abc b b abcde abc} + 5 {aab dddd d dddd c} {ddd abcde dddd abcde c} + 6 {ddd dd b aab abcde} {d ddddd dddd c abc} + 7 {d ddddd ddd c abcde} {c aab d abcde ddd} + 8 {abcde aaa aab c c} {ddd c dddd b aaa} + 9 {abcde aab ddddd c aab} {dddd dddd b c dd} + 10 {ddd abcde dddd dd c} {dddd c c d abcde} +} { + do_execsql_test 5.$i.1 { INSERT INTO t1 VALUES($x, $y) } + do_execsql_test 5.$i.2 { INSERT INTO t1(t1) VALUES('integrity-check') } + if {[set_test_counter errors]} break +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} + +do_execsql_test 6.1 { + INSERT INTO t1(rowid, x, y) VALUES(22, 'a b c', 'c b a'); + REPLACE INTO t1(rowid, x, y) VALUES(22, 'd e f', 'f e d'); +} + +do_execsql_test 6.2 { + INSERT INTO t1(t1) VALUES('integrity-check') +} + +do_execsql_test 6.3 { + REPLACE INTO t1(rowid, x, y) VALUES('22', 'l l l', 'l l l'); +} + +do_execsql_test 6.4 { + REPLACE INTO t1(x, y) VALUES('x y z', 'x y z'); +} + +do_execsql_test 6.5 { + INSERT INTO t1(t1) VALUES('integrity-check') +} + +do_execsql_test 6.6 { + SELECT rowid, * FROM t1; +} { + 22 {l l l} {l l l} + 23 {x y z} {x y z} +} + +#------------------------------------------------------------------------- +# +reset_db +expr srand(0) +do_execsql_test 7.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x,y,z); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} + +proc doc {} { + set v [list aaa aab abc abcde b c d dd ddd dddd ddddd] + set ret [list] + for {set j 0} {$j < 20} {incr j} { + lappend ret [lindex $v [expr int(rand()*[llength $v])]] + } + return $ret +} + +proc dump_structure {} { + db eval {SELECT fts5_decode(id, block) AS t FROM t1_data WHERE id=10} { + foreach lvl [lrange $t 1 end] { + set seg [string repeat . [expr [llength $lvl]-2]] + puts "[lrange $lvl 0 1] $seg" + } + } +} + +for {set i 1} {$i <= 10} {incr i} { + do_test 7.$i { + for {set j 0} {$j < 10} {incr j} { + set x [doc] + set y [doc] + set z [doc] + set rowid [expr int(rand() * 100)] + execsql { REPLACE INTO t1(rowid,x,y,z) VALUES($rowid, $x, $y, $z) } + } + execsql { INSERT INTO t1(t1) VALUES('integrity-check'); } + } {} + if {[set_test_counter errors]} break +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, prefix="1,2,3"); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} + +do_execsql_test 8.1 { + INSERT INTO t1 VALUES('the quick brown fox'); + INSERT INTO t1(t1) VALUES('integrity-check'); +} + + +#------------------------------------------------------------------------- +# +reset_db + +expr srand(0) + +do_execsql_test 9.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x,y,z, prefix="1,2,3"); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} + +proc doc {} { + set v [list aaa aab abc abcde b c d dd ddd dddd ddddd] + set ret [list] + for {set j 0} {$j < 20} {incr j} { + lappend ret [lindex $v [expr int(rand()*[llength $v])]] + } + return $ret +} + +proc dump_structure {} { + db eval {SELECT fts5_decode(id, block) AS t FROM t1_data WHERE id=10} { + foreach lvl [lrange $t 1 end] { + set seg [string repeat . [expr [llength $lvl]-2]] + puts "[lrange $lvl 0 1] $seg" + } + } +} + +for {set i 1} {$i <= 10} {incr i} { + do_test 9.$i { + for {set j 0} {$j < 100} {incr j} { + set x [doc] + set y [doc] + set z [doc] + set rowid [expr int(rand() * 100)] + execsql { REPLACE INTO t1(rowid,x,y,z) VALUES($rowid, $x, $y, $z) } + } + execsql { INSERT INTO t1(t1) VALUES('integrity-check'); } + } {} + if {[set_test_counter errors]} break +} + + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 10.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x,y, detail=%DETAIL%); +} +set d10 { + 1 {g f d b f} {h h e i a} + 2 {f i g j e} {i j c f f} + 3 {e e i f a} {e h f d f} + 4 {h j f j i} {h a c f j} + 5 {d b j c g} {f e i b e} + 6 {a j a e e} {j d f d e} + 7 {g i j c h} {j d h c a} + 8 {j j i d d} {e e d f b} + 9 {c j j d c} {h j i f g} + 10 {b f h i a} {c f b b j} +} +foreach {rowid x y} $d10 { + do_execsql_test 10.1.$rowid.1 { INSERT INTO t1 VALUES($x, $y) } + do_execsql_test 10.1.$rowid.2 { INSERT INTO t1(t1) VALUES('integrity-check') } +} +foreach rowid {5 9 8 1 2 4 10 7 3 5 6} { + do_execsql_test 10.2.$rowid.1 { DELETE FROM t1 WHERE rowid = $rowid } + do_execsql_test 10.2.$rowid.2 { INSERT INTO t1(t1) VALUES('integrity-check') } +} +foreach {rowid x y} $d10 { + do_execsql_test 10.3.$rowid.1 { INSERT INTO t1 VALUES($x, $y) } + do_execsql_test 10.3.$rowid.2 { INSERT INTO t1(t1) VALUES('integrity-check') } +} + +do_execsql_test 10.4.1 { DELETE FROM t1 } +do_execsql_test 10.4.2 { INSERT INTO t1(t1) VALUES('integrity-check') } + +#------------------------------------------------------------------------- +# +do_catchsql_test 11.1 { + CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, rank, detail=%DETAIL%); +} {1 {reserved fts5 column name: rank}} +do_catchsql_test 11.2 { + CREATE VIRTUAL TABLE rank USING fts5(a, b, c, detail=%DETAIL%); +} {1 {reserved fts5 table name: rank}} +do_catchsql_test 11.3 { + CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, rowid, detail=%DETAIL%); +} {1 {reserved fts5 column name: rowid}} + +#------------------------------------------------------------------------- +# +do_execsql_test 12.1 { + CREATE VIRTUAL TABLE t2 USING fts5(x,y, detail=%DETAIL%); +} {} + +do_catchsql_test 12.2 { + SELECT t2 FROM t2 WHERE t2 MATCH '*stuff' +} {1 {unknown special query: stuff}} + +do_test 12.3 { + set res [db eval { SELECT t2 FROM t2 WHERE t2 MATCH '* reads ' }] + string is integer $res +} {1} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 13.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); + INSERT INTO t1(rowid, x) VALUES(1, 'o n e'), (2, 't w o'); +} {} + +do_execsql_test 13.2 { + SELECT rowid FROM t1 WHERE t1 MATCH 'o'; +} {1 2} + +do_execsql_test 13.4 { + DELETE FROM t1 WHERE rowid=2; +} {} + +do_execsql_test 13.5 { + SELECT rowid FROM t1 WHERE t1 MATCH 'o'; +} {1} + +do_execsql_test 13.6 { + SELECT rowid FROM t1 WHERE t1 MATCH '""'; +} {} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 14.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + WITH d(x,y) AS ( + SELECT NULL, 'xyz xyz xyz xyz xyz xyz' + UNION ALL + SELECT NULL, 'xyz xyz xyz xyz xyz xyz' FROM d + ) + INSERT INTO t1 SELECT * FROM d LIMIT 200; +} + +do_execsql_test 15.x { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +do_test 14.2 { + set nRow 0 + db eval { SELECT * FROM t1 WHERE t1 MATCH 'xyz' } { + db eval { + BEGIN; + CREATE TABLE t2(a, b); + ROLLBACK; + } + incr nRow + } + set nRow +} {200} + +do_test 14.3 { + set nRow 0 + db eval { BEGIN; } + db eval { SELECT * FROM t1 WHERE t1 MATCH 'xyz' } { + db eval { + SAVEPOINT aaa; + CREATE TABLE t2(a, b); + ROLLBACK TO aaa; + RELEASE aaa; + } + incr nRow + } + set nRow +} {200} + +do_execsql_test 15.0 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} +do_execsql_test 15.1 { + UPDATE t1_content SET c1 = 'xyz xyz xyz xyz xyz abc' WHERE rowid = 1; +} +do_catchsql_test 15.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +#------------------------------------------------------------------------- +# +do_execsql_test 16.1 { + CREATE VIRTUAL TABLE n1 USING fts5(a); + INSERT INTO n1 VALUES('a b c d'); +} + +proc funk {} { + db eval { UPDATE n1_config SET v=50 WHERE k='version' } + set fd [db incrblob main n1_data block 10] + fconfigure $fd -encoding binary -translation binary + puts -nonewline $fd "\x44\x45" + close $fd +} +db func funk funk + +do_catchsql_test 16.2 { + SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d' +} {1 {SQL logic error or missing database}} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 17.1 { + CREATE VIRTUAL TABLE b2 USING fts5(x, detail=%DETAIL%); + INSERT INTO b2 VALUES('a'); + INSERT INTO b2 VALUES('b'); + INSERT INTO b2 VALUES('c'); +} + +do_test 17.2 { + set res [list] + db eval { SELECT * FROM b2 ORDER BY rowid ASC } { + lappend res [execsql { SELECT * FROM b2 ORDER BY rowid ASC }] + } + set res +} {{a b c} {a b c} {a b c}} + +if {[string match n* %DETAIL%]==0} { + reset_db + do_execsql_test 17.3 { + CREATE VIRTUAL TABLE c2 USING fts5(x, y, detail=%DETAIL%); + INSERT INTO c2 VALUES('x x x', 'x x x'); + SELECT rowid FROM c2 WHERE c2 MATCH 'y:x'; + } {1} +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 17.1 { + CREATE VIRTUAL TABLE uio USING fts5(ttt, detail=%DETAIL%); + INSERT INTO uio VALUES(NULL); + INSERT INTO uio SELECT NULL FROM uio; + INSERT INTO uio SELECT NULL FROM uio; + INSERT INTO uio SELECT NULL FROM uio; + INSERT INTO uio SELECT NULL FROM uio; + INSERT INTO uio SELECT NULL FROM uio; + INSERT INTO uio SELECT NULL FROM uio; + INSERT INTO uio SELECT NULL FROM uio; + INSERT INTO uio SELECT NULL FROM uio; + SELECT count(*) FROM uio; +} {256} + +do_execsql_test 17.2 { + SELECT count(*) FROM uio WHERE rowid BETWEEN 8 AND 17 +} {10} +do_execsql_test 17.3 { + SELECT rowid FROM uio WHERE rowid BETWEEN 8 AND 17 +} {8 9 10 11 12 13 14 15 16 17} +do_execsql_test 17.4 { + SELECT rowid FROM uio WHERE rowid BETWEEN 8 AND 17 ORDER BY rowid DESC +} {17 16 15 14 13 12 11 10 9 8} +do_execsql_test 17.5 { + SELECT count(*) FROM uio +} {256} + +do_execsql_test 17.6 { + INSERT INTO uio(rowid) VALUES(9223372036854775807); + INSERT INTO uio(rowid) VALUES(-9223372036854775808); + SELECT count(*) FROM uio; +} {258} +do_execsql_test 17.7 { + SELECT min(rowid), max(rowid) FROM uio; +} {-9223372036854775808 9223372036854775807} + +do_execsql_test 17.8 { + INSERT INTO uio DEFAULT VALUES; + SELECT min(rowid), max(rowid), count(*) FROM uio; +} {-9223372036854775808 9223372036854775807 259} + +do_execsql_test 17.9 { + SELECT min(rowid), max(rowid), count(*) FROM uio WHERE rowid < 10; +} {-9223372036854775808 9 10} + +#-------------------------------------------------------------------- +# +do_execsql_test 18.1 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); + CREATE VIRTUAL TABLE t2 USING fts5(c, d, detail=%DETAIL%); + INSERT INTO t1 VALUES('abc*', NULL); + INSERT INTO t2 VALUES(1, 'abcdefg'); +} +do_execsql_test 18.2 { + SELECT t1.rowid, t2.rowid FROM t1, t2 WHERE t2 MATCH t1.a AND t1.rowid = t2.c +} {1 1} +do_execsql_test 18.3 { + SELECT t1.rowid, t2.rowid FROM t2, t1 WHERE t2 MATCH t1.a AND t1.rowid = t2.c +} {1 1} + +#-------------------------------------------------------------------- +# fts5 table in the temp schema. +# +reset_db +do_execsql_test 19.0 { + CREATE VIRTUAL TABLE temp.t1 USING fts5(x, detail=%DETAIL%); + INSERT INTO t1 VALUES('x y z'); + INSERT INTO t1 VALUES('w x 1'); + SELECT rowid FROM t1 WHERE t1 MATCH 'x'; +} {1 2} + +#-------------------------------------------------------------------- +# Test that 6 and 7 byte varints can be read. +# +reset_db +do_execsql_test 20.0 { + CREATE VIRTUAL TABLE temp.tmp USING fts5(x, detail=%DETAIL%); +} +set ::ids [list \ + 0 [expr 1<<36] [expr 2<<36] [expr 1<<43] [expr 2<<43] +] +do_test 20.1 { + foreach id $::ids { + execsql { INSERT INTO tmp(rowid, x) VALUES($id, 'x y z') } + } + execsql { SELECT rowid FROM tmp WHERE tmp MATCH 'y' } +} $::ids + +} + + +finish_test + + diff --git a/ext/fts5/test/fts5ab.test b/ext/fts5/test/fts5ab.test new file mode 100644 index 0000000..95da2cd --- /dev/null +++ b/ext/fts5/test/fts5ab.test @@ -0,0 +1,297 @@ +# 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 fts5ab + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t1 VALUES('hello', 'world'); + INSERT INTO t1 VALUES('one two', 'three four'); + INSERT INTO t1(rowid, a, b) VALUES(45, 'forty', 'five'); +} + +do_execsql_test 1.1 { + SELECT * FROM t1 ORDER BY rowid DESC; +} { forty five {one two} {three four} hello world } + +do_execsql_test 1.2 { + SELECT rowid FROM t1 ORDER BY rowid DESC; +} {45 2 1} + +do_execsql_test 1.3 { + SELECT rowid FROM t1 ORDER BY rowid ASC; +} {1 2 45} + +do_execsql_test 1.4 { + SELECT * FROM t1 WHERE rowid=2; +} {{one two} {three four}} + +do_execsql_test 1.5 { + SELECT * FROM t1 WHERE rowid=2.01; +} {} + +do_execsql_test 1.6 { + SELECT * FROM t1 WHERE rowid=1.99; +} {} + +#------------------------------------------------------------------------- + +reset_db +do_execsql_test 2.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + INSERT INTO t1 VALUES('one'); + INSERT INTO t1 VALUES('two'); + INSERT INTO t1 VALUES('three'); +} + +do_catchsql_test 2.2 { + SELECT rowid, * FROM t1 WHERE t1 MATCH 'AND AND' +} {1 {fts5: syntax error near "AND"}} + +do_execsql_test 2.3 { SELECT rowid, * FROM t1 WHERE t1 MATCH 'two' } {2 two} +do_execsql_test 2.4 { SELECT rowid, * FROM t1 WHERE t1 MATCH 'three' } {3 three} +do_execsql_test 2.5 { SELECT rowid, * FROM t1 WHERE t1 MATCH 'one' } {1 one} + +do_execsql_test 2.6 { + INSERT INTO t1 VALUES('a b c d e f g'); + INSERT INTO t1 VALUES('b d e a a a i'); + INSERT INTO t1 VALUES('x y z b c c c'); +} + +foreach {tn expr res} { + 1 a {5 4} + 2 b {6 5 4} + 3 c {6 4} + 4 d {5 4} + 5 e {5 4} + 6 f {4} + 7 g {4} + 8 x {6} + 9 y {6} + 10 z {6} +} { + do_execsql_test 2.7.$tn.1 { + SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid DESC + } $res + do_execsql_test 2.7.$tn.2 { + SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid ASC + } [lsort -integer $res] +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a,b); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} + +foreach {tn a b} { + 1 {abashed abandons abase abash abaft} {abases abased} + 2 {abasing abases abaft abated abandons} {abases abandoned} + 3 {abatement abash abash abated abase} {abasements abashing} + 4 {abaft abasements abase abasement abasing} {abasement abases} + 5 {abaft abashing abatement abash abasements} {abandons abandoning} + 6 {aback abate abasements abashes abandoned} {abasement abased} + 7 {abandons abated abased aback abandoning} {abases abandoned} + 8 {abashing abases abasement abaft abashing} {abashed abate} + 9 {abash abase abate abashing abashed} {abandon abandoned} + 10 {abate abandoning abandons abasement aback} {abandon abandoning} +} { + do_execsql_test 3.1.$tn.1 { INSERT INTO t1 VALUES($a, $b) } + do_execsql_test 3.1.$tn.2 { INSERT INTO t1(t1) VALUES('integrity-check') } +} + +foreach {tn expr res} { + 1 {abash} {9 5 3 1} + 2 {abase} {9 4 3 1} + 3 {abase + abash} {1} + 4 {abash + abase} {9} + 5 {abaft + abashing} {8 5} + 6 {abandon + abandoning} {10} + 7 {"abashing abases abasement abaft abashing"} {8} +} { + do_execsql_test 3.2.$tn { + SELECT rowid FROM t1 WHERE t1 MATCH $expr ORDER BY rowid DESC + } $res +} + +do_execsql_test 3.3 { + SELECT rowid FROM t1 WHERE t1 MATCH 'NEAR(aback abate, 2)' +} {6} + +foreach {tn expr res} { + 1 {abash} {1 3 5 9} + 2 {abase} {1 3 4 9} + 3 {abase + abash} {1} + 4 {abash + abase} {9} + 5 {abaft + abashing} {5 8} + 6 {abandon + abandoning} {10} + 7 {"abashing abases abasement abaft abashing"} {8} +} { + do_execsql_test 3.4.$tn { + SELECT rowid FROM t1 WHERE t1 MATCH $expr + } $res +} + +#------------------------------------------------------------------------- +# Documents with more than 2M tokens. +# + +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE s1 USING fts5(x, detail=%DETAIL%); +} +foreach {tn doc} [list \ + 1 [string repeat {a x } 1500000] \ + 2 "[string repeat {a a } 1500000] x" \ +] { + do_execsql_test 4.$tn { INSERT INTO s1 VALUES($doc) } +} + +do_execsql_test 4.3 { + SELECT rowid FROM s1 WHERE s1 MATCH 'x' +} {1 2} + +if {[detail_is_full]} { + do_execsql_test 4.4 { + SELECT rowid FROM s1 WHERE s1 MATCH '"a x"' + } {1 2} +} + +do_execsql_test 4.5 { + SELECT rowid FROM s1 WHERE s1 MATCH 'a x' +} {1 2} + +#------------------------------------------------------------------------- +# Check that a special case of segment promotion works. The case is where +# a new segment is written to level L, but the oldest segment within level +# (L-2) is larger than it. +# +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE s2 USING fts5(x, detail=%DETAIL%); + INSERT INTO s2(s2, rank) VALUES('pgsz', 32); + INSERT INTO s2(s2, rank) VALUES('automerge', 0); +} + +proc rnddoc {n} { + set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] + set doc [list] + for {set i 0} {$i < $n} {incr i} { + lappend doc [string map $map [format %.3d [expr int(rand()*1000)]]] + } + set doc +} +db func rnddoc rnddoc + +do_test 5.1 { + for {set i 1} {$i <= 65} {incr i} { + execsql { INSERT INTO s2 VALUES(rnddoc(10)) } + } + for {set i 1} {$i <= 63} {incr i} { + execsql { DELETE FROM s2 WHERE rowid = $i } + } + fts5_level_segs s2 +} {0 8} + +do_test 5.2 { + execsql { + INSERT INTO s2(s2, rank) VALUES('automerge', 8); + } + for {set i 0} {$i < 7} {incr i} { + execsql { INSERT INTO s2 VALUES(rnddoc(50)) } + } + fts5_level_segs s2 +} {8 0 0} + +# Test also the other type of segment promotion - when a new segment is written +# that is larger than segments immediately following it. +do_test 5.3 { + execsql { + DROP TABLE s2; + CREATE VIRTUAL TABLE s2 USING fts5(x, detail=%DETAIL%); + INSERT INTO s2(s2, rank) VALUES('pgsz', 32); + INSERT INTO s2(s2, rank) VALUES('automerge', 0); + } + + for {set i 1} {$i <= 16} {incr i} { + execsql { INSERT INTO s2 VALUES(rnddoc(5)) } + } + fts5_level_segs s2 +} {0 1} + +do_test 5.4 { + execsql { INSERT INTO s2 VALUES(rnddoc(160)) } + fts5_level_segs s2 +} {2 0} + +#------------------------------------------------------------------------- +# +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE s3 USING fts5(x, detail=%DETAIL%); + BEGIN; + INSERT INTO s3 VALUES('a b c'); + INSERT INTO s3 VALUES('A B C'); +} + +do_execsql_test 6.1.1 { + SELECT rowid FROM s3 WHERE s3 MATCH 'a' +} {1 2} + +do_execsql_test 6.1.2 { + SELECT rowid FROM s3 WHERE s3 MATCH 'a' ORDER BY rowid DESC +} {2 1} + +do_execsql_test 6.2 { + COMMIT; +} + +do_execsql_test 6.3 { + SELECT rowid FROM s3 WHERE s3 MATCH 'a' +} {1 2} + +do_test 6.4 { + db close + sqlite3 db test.db + execsql { + BEGIN; + INSERT INTO s3(s3) VALUES('optimize'); + ROLLBACK; + } +} {} + +#------------------------------------------------------------------------- +# +set doc [string repeat "a b c " 500] +do_execsql_test 7.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x, detail=%DETAIL%); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + INSERT INTO x1 VALUES($doc); +} + +} ;# foreach_detail_mode... + + +finish_test + diff --git a/ext/fts5/test/fts5ac.test b/ext/fts5/test/fts5ac.test new file mode 100644 index 0000000..61b3230 --- /dev/null +++ b/ext/fts5/test/fts5ac.test @@ -0,0 +1,279 @@ +# 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 fts5ac + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +set data { + 0 {p o q e z k z p n f y u z y n y} {l o o l v v k} + 1 {p k h h p y l l h i p v n} {p p l u r i f a j g e r r x w} + 2 {l s z j k i m p s} {l w e j t j e e i t w r o p o} + 3 {x g y m y m h p} {k j j b r e y y a k y} + 4 {q m a i y i z} {o w a g k x g j m w e u k} + 5 {k o a w y b s z} {s g l m m l m g p} + 6 {d a q i z h b l c p k j g k} {p x u j x t v c z} + 7 {f d a g o c t i} {w f c x l d r k i j} + 8 {y g w u b q p o m j y b p a e k} {r i d k y w o z q m a t p} + 9 {r k o m c c j s x m x m x m q r} {y r c a q d z k n x n} + 10 {k j q m g q a j d} {d d e z g w h c d o o g x d} + 11 {j z u m o y q j f w e e w t r j w} {g m o r x n t n w i f g l z f} + 12 {s y w a w d o h x m k} {c w k z b p o r a} + 13 {u t h x e g s k n g i} {f j w g c s r} + 14 {b f i c s u z t k} {c k q s j u i z o} + 15 {n a f n u s w h y n s i q e w} {x g e g a s s h n} + 16 {k s q e j n p} {t r j f t o e k k l m i} + 17 {g d t u w r o p m n m n p h b o u} {h s w o s l j e} + 18 {f l q y q q g e e x j r} {n b r r g e i r t x q k} + 19 {f i r g o a w e p i l o a w} {e k r z t d g h g i b d i e m} + 20 {l d u u f p y} {g o m m u x m g l j t t x x u} + 21 {m c d k x i c z l} {m i a i e u h} + 22 {w b f o c g x y j} {z d w x d f h i p} + 23 {w u i u x t c h k i b} {b y k h b v r t g j} + 24 {h f d j s w s b a p k} {a q y u z e y m m j q r} + 25 {d i x y x x k i y f s d j h z p n} {l l q m e t c w g y h t s v g} + 26 {g s q w t d k x g f m j p k y} {r m b x e l t d} + 27 {j l s q u g y v e c l o} {m f l m m m h g x x l n c} + 28 {c t j g v r s b z j} {l c f y d t q n} + 29 {e x z y w i h l} {b n b x e y q e n u m} + 30 {g y y h j b w r} {q b q f u s k c k g r} + 31 {g u l x l b r c m z b u c} {k g t b x k x n t e z d h o} + 32 {w g v l z f b z h p s c v h} {g e w v m h k r g w a r f q} + 33 {c g n f u d o y o b} {e y o h x x y y i z s b h a j} + 34 {v y h c q u u s q y x x k s q} {d n r m y k n t i r n w e} + 35 {o u c x l e b t a} {y b a x y f z x r} + 36 {x p h l j a a u u j h} {x o f s z m b c q p} + 37 {k q t i c a q n m v v} {v r z e f m y o} + 38 {r w t t t t r v v o e p g h} {l w x a g a u h y} + 39 {o p v g v b a g o} {j t q c r b b g y z} + 40 {f s o r o d t h q f x l} {r d b m k i f s t d l m y x j w} + 41 {t m o t m f m f} {i p i q j v n v m b q} + 42 {t x w a r l w d t b c o d o} {a h f h w z d n s} + 43 {t u q c d g p q x j o l c x c} {m n t o z z j a y} + 44 {v d i i k b f s z r v r z y} {g n q y s x x m b x c l w} + 45 {p v v a c s z y e o l} {m v t u d k m k q b d c v z r} + 46 {f y k l d r q w r s t r e} {h m v r r l r r t f q e x y} + 47 {w l n l t y x} {n h s l a f c h u f l x x m v n o} + 48 {t n v i k e b p z p d j j l i o} {i v z p g u e j s i k n h w d c} + 49 {z v x p n l t a j c} {e j l e n c e t a d} + 50 {w u b x u i v h a i y m m r p m s} {s r h d o g z y f f x e} + 51 {d c c x b c a x g} {p r a j v u y} + 52 {f w g r c o d l t u e z h i} {j l l s s b j m} + 53 {p m t f k i x} {u v y a z g w v v m x h i} + 54 {l c z g l o j i c d e b} {b f v y w u i b e i y} + 55 {r h c x f x a d s} {z x y k f l r b q c v} + 56 {v x x c y h z x b g m o q n c} {h n b i t g h a q b c o r u} + 57 {d g l o h t b s b r} {n u e p t i m u} + 58 {t d y e t d c w u o s w x f c h} {i o s v y b r d r} + 59 {l b a p q n d r} {k d c c d n y q h g a o p e x} + 60 {f r z v m p k r} {x x r i s b a g f c} + 61 {s a z i e r f i w c n y v z t k s} {y y i r y n l s b w i e k n} + 62 {n x p r e x q r m v i b y} {f o o z n b s r q j} + 63 {y j s u j x o n r q t f} {f v k n v x u s o a d e f e} + 64 {u s i l y c x q} {r k c h p c h b o s s u s p b} + 65 {m p i o s h o} {s w h u n d m n q t y k b w c} + 66 {l d f g m x x x o} {s w d d f b y j j h h t i y p j o} + 67 {c b m h f n v w n h} {i r w i e x r w l z p x u g u l s} + 68 {y a h u h i m a y q} {d d r x h e v q n z y c j} + 69 {c x f d x o n p o b r t b l p l} {m i t k b x v f p t m l l y r o} + 70 {u t l w w m s} {m f m o l t k o p e} + 71 {f g q e l n d m z x q} {z s i i i m f w w f n g p e q} + 72 {n l h a v u o d f j d e x} {v v s l f g d g r a j x i f z x} + 73 {x v m v f i g q e w} {r y s j i k m j j e d g r n o i f} + 74 {g d y n o h p s y q z j d w n h w} {x o d l t j i b r d o r y} + 75 {p g b i u r b e q d v o a g w m k} {q y z s f q o h} + 76 {u z a q u f i f f b} {b s p b a a d x r r i q f} + 77 {w h h z t h p o a h h e e} {h w r p h k z v y f r x} + 78 {c a r k i a p u x} {f w l p t e m l} + 79 {q q u k o t r k z} {f b m c w p s s o z} + 80 {t i g v y q s r x m r x z e f} {x o j w a u e y s j c b u p p r o} + 81 {n j n h r l a r e o z w e} {v o r r j a v b} + 82 {i f i d k w d n h} {o i d z i z l m w s b q v u} + 83 {m d g q q b k b w f q q p p} {j m q f b y c i z k y q p l e a} + 84 {m x o n y f g} {y c n x n q j i y c l h b r q z} + 85 {v o z l n p c} {g n j n t b b x n c l d a g j v} + 86 {z n a y f b t k k t d b z a v} {r p c n r u k u} + 87 {b q t x z e c w} {q a o a l o a h i m j r} + 88 {j f h o x x a z g b a f a m i b} {j z c z y x e x w t} + 89 {t c t p r s u c q n} {z x l i k n f q l n t} + 90 {w t d q j g m r f k n} {l e w f w w a l y q k i q t p c t} + 91 {c b o k l i c b s j n m b l} {y f p q o w g} + 92 {f y d j o q t c c q m f j s t} {f h e d y m o k} + 93 {k x j r m a d o i z j} {r t t t f e b r x i v j v g o} + 94 {s f e a e t i h h d q p z t q} {b k m k w h c} + 95 {h b n j t k i h o q u} {w n g i t o k c a m y p f l x c p} + 96 {f c x p y r b m o l m o a} {p c a q s u n n x d c f a o} + 97 {u h h k m n k} {u b v n u a o c} + 98 {s p e t c z d f n w f} {l s f j b l c e s h} + 99 {r c v w i v h a t a c v c r e} {h h u m g o f b a e o} +} + +foreach {tn2 sql} { + 1 {} + 2 {BEGIN} +} { + reset_db + fts5_aux_test_functions db + + do_execsql_test 1.$tn2.0 { + CREATE VIRTUAL TABLE xx USING fts5(x,y, detail=%DETAIL%); + INSERT INTO xx(xx, rank) VALUES('pgsz', 32); + } + + execsql $sql + + do_test 1.$tn2.1.1 { + foreach {id x y} $data { + execsql { INSERT INTO xx(rowid, x, y) VALUES($id, $x, $y) } + } + execsql { INSERT INTO xx(xx) VALUES('integrity-check') } + } {} + + + #------------------------------------------------------------------------- + # + do_execsql_test 1.$tn2.integrity { + INSERT INTO xx(xx) VALUES('integrity-check'); + } + + #------------------------------------------------------------------------- + # + foreach {tn expr} { + 1.1 "a AND b" + 1.2 "a OR b" + 1.3 "o" + 1.4 "b q" + 1.5 "e a e" + 1.6 "m d g q q b k b w f q q p p" + 1.7 "l o o l v v k" + 1.8 "a" + 1.9 "b" + 1.10 "c" + 1.11 "no" + 1.12 "L O O L V V K" + 1.13 "a AND b AND c" + 1.14 "x:a" + + 2.1 "x:a" + 2.2 "y:a" + 2.3 "x:b" + 2.4 "y:b" + + 3.1 "{x}:a" + 3.2 "{y}:a" + 3.3 "{x}:b" + 3.4 "{y}:b" + + 4.1 "{x y}:a" + 4.2 "{y x}:a" + 4.3 "{x x}:b" + 4.4 "{y y}:b" + + 5.1 {{"x" "y"}:a} + 5.2 {{"y" x}:a} + 5.3 {{x "x"}:b} + 5.4 {{"y" y}:b} + + 6.1 "b + q" + 6.2 "e + a + e" + 6.3 "m + d + g + q + q + b + k + b + w + f + q + q + p + p" + 6.4 "l + o + o + l + v + v + k" + 6.5 "L + O + O + L + V + V + K" + + 7.1 "a+b AND c" + 7.2 "d+c AND u" + 7.3 "d+c AND u+d" + 7.4 "a+b OR c" + 7.5 "d+c OR u" + 7.6 "d+c OR u+d" + + 8.1 "NEAR(a b)" + 8.2 "NEAR(r c)" + 8.2 { NEAR(r c, 5) } + 8.3 { NEAR(r c, 3) } + 8.4 { NEAR(r c, 2) } + 8.5 { NEAR(r c, 0) } + 8.6 { NEAR(a b c) } + 8.7 { NEAR(a b c, 8) } + 8.8 { x : NEAR(r c) } + 8.9 { y : NEAR(r c) } + + 9.1 { NEAR(r c) } + 9.2 { NEAR(r c, 5) } + 9.3 { NEAR(r c, 3) } + 9.4 { NEAR(r c, 2) } + 9.5 { NEAR(r c, 0) } + 9.6 { NEAR(a b c) } + 9.7 { NEAR(a b c, 8) } + 9.8 { x : NEAR(r c) } + 9.9 { y : NEAR(r c) } + 9.10 { x : "r c" } + 9.11 { y : "r c" } + 9.12 { a AND b } + 9.13 { a AND b AND c } + 9.14a { a } + 9.14b { a OR b } + 9.15 { a OR b AND c } + 9.16 { c AND b OR a } + 9.17 { c AND (b OR a) } + 9.18 { c NOT (b OR a) } + 9.19 { (c NOT b) OR (a AND d) } + } { + + if {[fts5_expr_ok $expr xx]==0} { + do_test 1.$tn2.$tn.OMITTED { list } [list] + continue + } + + set res [fts5_query_data $expr xx] + do_execsql_test 1.$tn2.$tn.[llength $res].asc { + SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx) + FROM xx WHERE xx match $expr + } $res + + set res [fts5_query_data $expr xx DESC] + do_execsql_test 1.$tn2.$tn.[llength $res].desc { + SELECT rowid, fts5_test_poslist(xx), fts5_test_collist(xx) + FROM xx WHERE xx match $expr ORDER BY 1 DESC + } $res + } +} + +} + +do_execsql_test 2.1 { + SELECT fts5_expr_tcl('a AND b'); +} {{AND [nearset -- {a}] [nearset -- {b}]}} + +do_test 2.2.1 { nearset {{a b c}} -- a } {0.0.0} +do_test 2.2.2 { nearset {{a b c}} -- c } {0.0.2} + +foreach {tn expr tclexpr} { + 1 {a b} {AND [N $x -- {a}] [N $x -- {b}]} +} { + do_execsql_test 2.3.$tn { + SELECT fts5_expr_tcl($expr, 'N $x') + } [list $tclexpr] +} + +finish_test + diff --git a/ext/fts5/test/fts5ad.test b/ext/fts5/test/fts5ad.test new file mode 100644 index 0000000..974aa78 --- /dev/null +++ b/ext/fts5/test/fts5ad.test @@ -0,0 +1,245 @@ +# 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. +# +# More specifically, the focus is on testing prefix queries, both with and +# without prefix indexes. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5ad + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE yy USING fts5(x, y, detail=%DETAIL%); + INSERT INTO yy VALUES('Changes the result to be', 'the list of all matching'); + INSERT INTO yy VALUES('indices (or all matching', 'values if -inline is'); + INSERT INTO yy VALUES('specified as well.) If', 'indices are returned, the'); +} {} + +foreach {tn match res} { + 1 {c*} {1} + 2 {i*} {3 2} + 3 {t*} {3 1} + 4 {r*} {3 1} +} { + do_execsql_test 1.$tn { + SELECT rowid FROM yy WHERE yy MATCH $match ORDER BY rowid DESC + } $res +} + +foreach {tn match res} { + 5 {c*} {1} + 6 {i*} {2 3} + 7 {t*} {1 3} + 8 {r*} {1 3} +} { + do_execsql_test 1.$tn { + SELECT rowid FROM yy WHERE yy MATCH $match + } $res +} + +foreach {T create} { + 2 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + } + + 3 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix="1,2,3,4", detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + } + + 4 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + BEGIN; + } + + 5 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix="1,2,3,4", detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + BEGIN; + } + +} { + + do_test $T.1 { + execsql { DROP TABLE IF EXISTS t1 } + execsql $create + } {} + + do_test $T.1 { + foreach {rowid a b} { + 0 {fghij uvwxyz klmn pq uvwx} {klmn f fgh uv fghij klmno} + 1 {uv f abcd abcd fghi} {pq klm uv uv fgh uv a} + 2 {klmn klm pqrs fghij uv} {f k uvw ab abcd pqr uv} + 3 {ab pqrst a fghi ab pqr fg} {k klmno a fg abcd} + 4 {abcd pqrst uvwx a fgh} {f klmno fghij kl pqrst} + 5 {uvwxyz k abcde u a} {uv k k kl klmn} + 6 {uvwxyz k klmn pqrst uv} {fghi pqrs abcde u k} + 7 {uvwxy klmn u p pqrst fgh} {p f fghi abcd uvw kl uv} + 8 {f klmno pqrst uvwxy pqrst} {uv abcde klm pq pqr} + 9 {f abcde a uvwxyz pqrst} {fghij abc k uvwx pqr fghij uvwxy} + 10 {ab uv f fg pqrst uvwxy} {fgh p uv k abc klm uvw} + 11 {pq klmno a uvw abcde uvwxyz} {fghij pq uvwxyz pqr fghi} + 12 {fgh u pq fgh uvw} {uvw pqr f uvwxy uvwx} + 13 {uvwx klmn f fgh abcd pqr} {uvw k fg uv klm abcd} + 14 {ab uvwx pqrst pqr uvwxyz pqrs} {uvwxyz abcde ab ab uvw abcde} + 15 {abc abcde uvwxyz abc kl k pqr} {klm k k klmno u fgh} + 16 {fghi abcd fghij uv uvwxyz ab uv} {klmn pqr a uvw fghi} + 17 {abc pqrst fghi uvwx uvw klmn fghi} {ab fg pqr pqrs p} + 18 {pqr kl a fghij fgh fg kl} {pqr uvwxyz uvw abcd uvwxyz} + 19 {fghi fghi pqr kl fghi f} {klmn u u klmno klmno} + 20 {abc pqrst klmno kl pq uvwxy} {abc k fghi pqrs klm} + 21 {a pqr uvwxyz uv fghi a fgh} {abc pqrs pqrst pq klm} + 22 {klm abc uvwxyz klm pqrst} {fghij k pq pqr u klm fghij} + 23 {p klm uv p a a} {uvwxy klmn uvw abcde pq} + 24 {uv fgh fg pq uvwxy u uvwxy} {pqrs a uvw p uvwx uvwxyz fg} + 25 {fghij fghi klmn abcd pq kl} {fghi abcde pqrs abcd fgh uvwxy} + 26 {pq fgh a abc klmno klmn} {fgh p k p fg fghij} + 27 {fg pq kl uvwx fghij pqrst klmn} {abcd uvw abcd fghij f fghij} + 28 {uvw fghi p fghij pq fgh uvwx} {k fghij abcd uvwx pqr fghi} + 29 {klm pq abcd pq f uvwxy} {pqrst p fghij pqr p} + 30 {ab uvwx fg uvwx klmn klm} {klmn klmno fghij klmn klm} + 31 {pq k pqr abcd a pqrs} {abcd abcd uvw a abcd klmno ab} + 32 {pqrst u abc pq klm} {abc kl uvwxyz fghij u fghi p} + 33 {f uvwxy u k f uvw uvwx} {pqrs uvw fghi fg pqrst klm} + 34 {pqrs pq fghij uvwxyz pqr} {ab abc abc uvw f pq f} + 35 {uvwxy ab uvwxy klmno kl pqrs} {abcde uvw pqrs uvwx k k} + 36 {uvwxyz k ab abcde abc uvw} {uvw abcde uvw klmn uv klmn} + 37 {k kl uv abcde uvwx fg u} {u abc uvwxy k fg abcd} + 38 {fghi pqrst fghi pqr pqrst uvwx} {u uv uvwx fghi abcde} + 39 {k pqrst k uvw fg pqrst fghij} {uvwxy ab kl klmn uvwxyz abcde} + 40 {fg uvwxy pqrs klmn uvwxyz klm p} {k uv ab fghij fgh k pqrs} + 41 {uvwx abc f pq uvwxy k} {ab uvwxyz abc f fghij} + 42 {uvwxy klmno uvwxyz uvwxyz pqrst} {uv kl kl klmno k f abcde} + 43 {abcde ab pqrs fg f fgh} {abc fghij fghi k k} + 44 {uvw abcd a ab pqrst klmn fg} {pqrst u uvwx pqrst fghij f pqrst} + 45 {uvwxy p kl uvwxyz ab pqrst fghi} {abc f pqr fg a k} + 46 {u p f a fgh} {a kl pq uv f} + 47 {pqrs abc fghij fg abcde ab a} {p ab uv pqrs kl fghi abcd} + 48 {abcde uvwxy pqrst uv abc pqr uvwx} {uvwxy klm uvwxy uvwx k} + 49 {fgh klm abcde klmno u} {a f fghij f uvwxyz abc u} + 50 {uv uvw uvwxyz uvwxyz uv ab} {uvwx pq fg u k uvwxy} + 51 {uvwxy pq p kl fghi} {pqrs fghi pqrs abcde uvwxyz ab} + 52 {pqr p uvwxy kl pqrs klmno fghij} {ab abcde abc pqrst pqrs uv} + 53 {fgh pqrst p a klmno} {ab ab pqrst pqr kl pqrst} + 54 {abcd klm ab uvw a fg u} {f pqr f abcd uv} + 55 {u fg uvwxyz k uvw} {abc pqrs f fghij fg pqrs uvwxy} + 56 {klm fg p fghi fg a} {uv a fghi uvwxyz a fghi} + 57 {uvwxy k abcde fgh f fghi} {f kl klmn f fghi klm} + 58 {klm k fgh uvw fgh fghi} {klmno uvwx u pqrst u} + 59 {fghi pqr pqrst p uvw fghij} {uv pqrst pqrs pq fghij klm} + 60 {uvwx klm uvwxy uv klmn} {p a a abc klmn ab k} + 61 {uvwxy uvwx klm uvwx klm} {pqrs ab ab uvwxyz fg} + 62 {kl uv uv uvw fg kl k} {abcde uvw fgh uvwxy klm} + 63 {a abc fgh u klm abcd} {fgh pqr uv klmn fghij} + 64 {klmn k klmn klmno pqrs pqr} {fg kl abcde klmno uvwxy kl pq} + 65 {uvwxyz klm fghi abc abcde kl} {uvwxy uvw uvwxyz uvwxyz pq pqrst} + 66 {pq klm abc pqrst fgh f} {u abcde pqrst abcde fg} + 67 {u pqrst kl u uvw klmno} {u pqr pqrs fgh u p} + 68 {abc fghi uvwxy fgh k pq} {uv p uvwx uvwxyz ab} + 69 {klmno f uvwxyz uvwxy klmn fg ab} {fgh kl a pqr abcd pqr} + 70 {fghi pqrst pqrst uv a} {uvwxy k p uvw uvwx a} + 71 {a fghij f p uvw} {klm fg abcd abcde klmno pqrs} + 72 {uv uvwx uvwx uvw klm} {uv fghi klmno uvwxy uvw} + 73 {kl uvwxy ab f pq klm u} {uvwxy klmn klm abcd pq fg k} + 74 {uvw pqrst abcd uvwxyz ab} {fgh fgh klmn abc pq} + 75 {uvwxyz klm pq abcd klmno pqr uvwxyz} {kl f a fg pqr klmn} + 76 {uvw uvwxy pqr k pqrst kl} {uvwxy abc uvw uvw u} + 77 {fgh klm u uvwxyz f uvwxy abcde} {uv abcde klmno u u ab} + 78 {klmno abc pq pqr fgh} {p uv abcd fgh abc u k} + 79 {fg pqr uvw pq uvwx} {uv uvw fghij pqrs fg p} + 80 {abcd pqrs uvwx uvwxy uvwx} {u uvw pqrst pqr abcde pqrs kl} + 81 {uvwxyz klm pq uvwxy fghij} {p pq klm fghij u a a} + 82 {uvwx k uvwxyz klmno pqrst kl} {abcde p f pqrst abcd uvwxyz p} + 83 {abcd abcde klm pqrst uvwxyz} {uvw pqrst u p uvwxyz a pqrs} + 84 {k klm abc uv uvwxy klm klmn} {k abc pqr a abc p kl} + 85 {klmn abcd pqrs p pq klm a} {klmn kl ab uvw pq} + 86 {klmn a pqrs abc uvw pqrst} {a pqr kl klm a k f} + 87 {pqrs ab uvwx uvwxy a pqr f} {fg klm uvwx pqr pqr} + 88 {klmno ab k kl u uvwxyz} {uv kl uvw fghi uv uvw} + 89 {pq fghi pqrst klmn uvwxy abc pqrs} {fg f f fg abc abcde klm} + 90 {kl a k fghi uvwx fghi u} {ab uvw pqr fg a p abc} + 91 {uvwx pqrs klmno ab fgh uvwx} {pqr uvwx abc kl f klmno kl} + 92 {fghij pq pqrs fghij f pqrst} {u abcde fg pq pqr fgh k} + 93 {fgh u pqrs abcde klmno abc} {abc fg pqrst pqr abcde} + 94 {uvwx p abc f pqr p} {k pqrs kl klm abc fghi klm} + 95 {kl p klmno uvwxyz klmn} {fghi ab a fghi pqrs kl} + 96 {pqr fgh pq uvwx a} {uvw klm klmno fg uvwxy uvwx} + 97 {fg abc uvwxyz fghi pqrst pq} {abc k a ab abcde f} + 98 {uvwxy fghi uvwxy u abcde abcde uvw} {klmn uvwx pqrs uvw uvwxy abcde} + 99 {pq fg fghi uvwx uvwx fghij uvwxy} {klmn klmn f abc fg a} + } { + execsql { + INSERT INTO t1(rowid, a, b) VALUES($rowid, $a, $b); + } + } + } {} + + proc prefix_query {prefixlist} { + set ret [list] + db eval {SELECT rowid, a, b FROM t1 ORDER BY rowid DESC} { + set bMatch 1 + foreach pref $prefixlist { + if { [lsearch -glob $a $pref]<0 && [lsearch -glob $b $pref]<0 } { + set bMatch 0 + break + } + } + if {$bMatch} { lappend ret $rowid } + } + return $ret + } + + do_execsql_test $T.integrity { + INSERT INTO t1(t1) VALUES('integrity-check'); + } + + foreach {bAsc sql} { + 1 {SELECT rowid FROM t1 WHERE t1 MATCH $prefix} + 0 {SELECT rowid FROM t1 WHERE t1 MATCH $prefix ORDER BY rowid DESC} + } { + foreach {tn prefix} { + 1 {a*} 2 {ab*} 3 {abc*} 4 {abcd*} 5 {abcde*} + 6 {f*} 7 {fg*} 8 {fgh*} 9 {fghi*} 10 {fghij*} + 11 {k*} 12 {kl*} 13 {klm*} 14 {klmn*} 15 {klmno*} + 16 {p*} 17 {pq*} 18 {pqr*} 19 {pqrs*} 20 {pqrst*} + 21 {u*} 22 {uv*} 23 {uvw*} 24 {uvwx*} 25 {uvwxy*} 26 {uvwxyz*} + 27 {x*} + 28 {a f*} 29 {a* f*} 30 {a* fghij*} + } { + set res [prefix_query $prefix] + if {$bAsc} { + set res [lsort -integer -increasing $res] + } + set n [llength $res] + if {$T==5} breakpoint + do_execsql_test $T.$bAsc.$tn.$n $sql $res + } + } + + catchsql COMMIT +} + +} + +finish_test + diff --git a/ext/fts5/test/fts5ae.test b/ext/fts5/test/fts5ae.test new file mode 100644 index 0000000..5153306 --- /dev/null +++ b/ext/fts5/test/fts5ae.test @@ -0,0 +1,312 @@ +# 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 fts5ae + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} + +do_execsql_test 1.1 { + INSERT INTO t1 VALUES('hello', 'world'); + SELECT rowid FROM t1 WHERE t1 MATCH 'hello' ORDER BY rowid ASC; +} {1} + +do_execsql_test 1.2 { + INSERT INTO t1 VALUES('world', 'hello'); + SELECT rowid FROM t1 WHERE t1 MATCH 'hello' ORDER BY rowid ASC; +} {1 2} + +do_execsql_test 1.3 { + INSERT INTO t1 VALUES('world', 'world'); + SELECT rowid FROM t1 WHERE t1 MATCH 'hello' ORDER BY rowid ASC; +} {1 2} + +do_execsql_test 1.4.1 { + INSERT INTO t1 VALUES('hello', 'hello'); +} + +do_execsql_test 1.4.2 { + SELECT rowid FROM t1 WHERE t1 MATCH 'hello' ORDER BY rowid ASC; +} {1 2 4} + +fts5_aux_test_functions db + +#------------------------------------------------------------------------- +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t2 USING fts5(x, y, detail=%DETAIL%); + INSERT INTO t2 VALUES('u t l w w m s', 'm f m o l t k o p e'); + INSERT INTO t2 VALUES('f g q e l n d m z x q', 'z s i i i m f w w f n g p'); +} + +do_execsql_test 2.1 { + SELECT rowid, fts5_test_poslist(t2) FROM t2 + WHERE t2 MATCH 'm' ORDER BY rowid; +} { + 1 {0.0.5 0.1.0 0.1.2} + 2 {0.0.7 0.1.5} +} + +do_execsql_test 2.2 { + SELECT rowid, fts5_test_poslist(t2) FROM t2 + WHERE t2 MATCH 'u OR q' ORDER BY rowid; +} { + 1 {0.0.0} + 2 {1.0.2 1.0.10} +} + +if {[detail_is_full]} { + do_execsql_test 2.3 { + SELECT rowid, fts5_test_poslist(t2) FROM t2 + WHERE t2 MATCH 'y:o' ORDER BY rowid; + } { + 1 {0.1.3 0.1.7} + } +} + +#------------------------------------------------------------------------- +# +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t3 USING fts5(x, y, detail=%DETAIL%); + INSERT INTO t3 VALUES( 'j f h o x x a z g b a f a m i b', 'j z c z y x w t'); + INSERT INTO t3 VALUES( 'r c', ''); +} + +if {[detail_is_full]} { + do_execsql_test 3.1 { + SELECT rowid, fts5_test_poslist(t3) FROM t3 WHERE t3 MATCH 'NEAR(a b)'; + } { + 1 {0.0.6 1.0.9 0.0.10 0.0.12 1.0.15} + } + + do_execsql_test 3.2 { + SELECT rowid, fts5_test_poslist(t3) FROM t3 WHERE t3 MATCH 'NEAR(r c)'; + } { + 2 {0.0.0 1.0.1} + } +} + +do_execsql_test 3.3 { + INSERT INTO t3 + VALUES('k x j r m a d o i z j', 'r t t t f e b r x i v j v g o'); + SELECT rowid, fts5_test_poslist(t3) + FROM t3 WHERE t3 MATCH 'a OR b AND c'; +} { + 1 {0.0.6 1.0.9 0.0.10 0.0.12 1.0.15 2.1.2} + 3 0.0.5 +} + +#------------------------------------------------------------------------- +# +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE t4 USING fts5(x, y, detail=%DETAIL%); + INSERT INTO t4 + VALUES('k x j r m a d o i z j', 'r t t t f e b r x i v j v g o'); +} + +do_execsql_test 4.1 { + SELECT rowid, fts5_test_poslist(t4) FROM t4 WHERE t4 MATCH 'a OR b AND c'; +} { + 1 0.0.5 +} + +#------------------------------------------------------------------------- +# Test that the xColumnSize() and xColumnAvgsize() APIs work. +# +reset_db +fts5_aux_test_functions db + +do_execsql_test 5.1 { + CREATE VIRTUAL TABLE t5 USING fts5(x, y, detail=%DETAIL%); + INSERT INTO t5 VALUES('a b c d', 'e f g h i j'); + INSERT INTO t5 VALUES('', 'a'); + INSERT INTO t5 VALUES('a', ''); +} +do_execsql_test 5.2 { + SELECT rowid, fts5_test_columnsize(t5) FROM t5 WHERE t5 MATCH 'a' + ORDER BY rowid DESC; +} { + 3 {1 0} + 2 {0 1} + 1 {4 6} +} + +do_execsql_test 5.3 { + SELECT rowid, fts5_test_columntext(t5) FROM t5 WHERE t5 MATCH 'a' + ORDER BY rowid DESC; +} { + 3 {a {}} + 2 {{} a} + 1 {{a b c d} {e f g h i j}} +} + +do_execsql_test 5.4 { + SELECT rowid, fts5_test_columntotalsize(t5) FROM t5 WHERE t5 MATCH 'a' + ORDER BY rowid DESC; +} { + 3 {5 7} + 2 {5 7} + 1 {5 7} +} + +do_execsql_test 5.5 { + INSERT INTO t5 VALUES('x y z', 'v w x y z'); + SELECT rowid, fts5_test_columntotalsize(t5) FROM t5 WHERE t5 MATCH 'a' + ORDER BY rowid DESC; +} { + 3 {8 12} + 2 {8 12} + 1 {8 12} +} + +#------------------------------------------------------------------------- +# Test the xTokenize() API +# +reset_db +fts5_aux_test_functions db +do_execsql_test 6.1 { + CREATE VIRTUAL TABLE t6 USING fts5(x, y, detail=%DETAIL%); + INSERT INTO t6 VALUES('There are more', 'things in heaven and earth'); + INSERT INTO t6 VALUES(', Horatio, Than are', 'dreamt of in your philosophy.'); +} + +do_execsql_test 6.2 { + SELECT rowid, fts5_test_tokenize(t6) FROM t6 WHERE t6 MATCH 't*' +} { + 1 {{there are more} {things in heaven and earth}} + 2 {{horatio than are} {dreamt of in your philosophy}} +} + +#------------------------------------------------------------------------- +# Test the xQueryPhrase() API +# +reset_db +fts5_aux_test_functions db +do_execsql_test 7.1 { + CREATE VIRTUAL TABLE t7 USING fts5(x, y, detail=%DETAIL%); +} +do_test 7.2 { + foreach {x y} { + {q i b w s a a e l o} {i b z a l f p t e u} + {b a z t a l o x d i} {b p a d b f h d w y} + {z m h n p p u i e g} {v h d v b x j j c z} + {a g i m v a u c b i} {p k s o t l r t b m} + {v v c j o d a s c p} {f f v o k p o f o g} + } { + execsql {INSERT INTO t7 VALUES($x, $y)} + } + execsql { SELECT count(*) FROM t7 } +} {5} + +foreach {tn q res} { + 1 a {{4 2}} + 2 b {{3 4}} + 3 c {{2 1}} + 4 d {{2 2}} + 5 {a AND b} {{4 2} {3 4}} + 6 {a OR b OR c OR d} {{4 2} {3 4} {2 1} {2 2}} +} { + do_execsql_test 7.3.$tn { + SELECT fts5_test_queryphrase(t7) FROM t7 WHERE t7 MATCH $q LIMIT 1 + } [list $res] +} + +do_execsql_test 7.4 { + SELECT fts5_test_rowcount(t7) FROM t7 WHERE t7 MATCH 'a'; +} {5 5 5 5} + +#do_execsql_test 7.4 { +# SELECT rowid, bm25debug(t7) FROM t7 WHERE t7 MATCH 'a'; +#} {5 5 5 5} +# + +#------------------------------------------------------------------------- +# +do_test 8.1 { + execsql { CREATE VIRTUAL TABLE t8 USING fts5(x, y, detail=%DETAIL%) } + foreach {rowid x y} { + 0 {A o} {o o o C o o o o o o o o} + 1 {o o B} {o o o C C o o o o o o o} + 2 {A o o} {o o o o D D o o o o o o} + 3 {o B} {o o o o o D o o o o o o} + 4 {E o G} {H o o o o o o o o o o o} + 5 {F o G} {I o J o o o o o o o o o} + 6 {E o o} {H o J o o o o o o o o o} + 7 {o o o} {o o o o o o o o o o o o} + 9 {o o o} {o o o o o o o o o o o o} + } { + execsql { INSERT INTO t8(rowid, x, y) VALUES($rowid, $x, $y) } + } +} {} + +foreach {tn q res} { + 1 {a} {0 2} + 2 {b} {3 1} + 3 {c} {1 0} + 4 {d} {2 3} + 5 {g AND (e OR f)} {5 4} + 6 {j AND (h OR i)} {5 6} +} { + do_execsql_test 8.2.$tn.1 { + SELECT rowid FROM t8 WHERE t8 MATCH $q ORDER BY bm25(t8); + } $res + + do_execsql_test 8.2.$tn.2 { + SELECT rowid FROM t8 WHERE t8 MATCH $q ORDER BY +rank; + } $res + + do_execsql_test 8.2.$tn.3 { + SELECT rowid FROM t8 WHERE t8 MATCH $q ORDER BY rank; + } $res +} + +#------------------------------------------------------------------------- +# Test xPhraseCount() for some different queries. +# +do_test 9.1 { + execsql { CREATE VIRTUAL TABLE t9 USING fts5(x) } + foreach x { + "a b c" "d e f" + } { + execsql { INSERT INTO t9 VALUES($x) } + } +} {} + +foreach {tn q cnt} { + 1 {a AND b} 2 + 2 {a OR b} 2 + 3 {a OR b OR c} 3 + 4 {NEAR(a b)} 2 +} { + do_execsql_test 9.2.$tn { + SELECT fts5_test_phrasecount(t9) FROM t9 WHERE t9 MATCH $q LIMIT 1 + } $cnt +} + +} + +finish_test + diff --git a/ext/fts5/test/fts5af.test b/ext/fts5/test/fts5af.test new file mode 100644 index 0000000..d6b2241 --- /dev/null +++ b/ext/fts5/test/fts5af.test @@ -0,0 +1,148 @@ +# 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. +# +# More specifically, the tests in this file focus on the built-in +# snippet() function. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5af + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=%DETAIL%); +} + +proc do_snippet_test {tn doc match res} { + + uplevel #0 [list set v1 $doc] + uplevel #0 [list set v2 $match] + + do_execsql_test $tn.1 { + DELETE FROM t1; + INSERT INTO t1 VALUES($v1, NULL); + SELECT snippet(t1, -1, '[', ']', '...', 7) FROM t1 WHERE t1 MATCH $v2; + } [list $res] + + do_execsql_test $tn.2 { + DELETE FROM t1; + INSERT INTO t1 VALUES(NULL, $v1); + SELECT snippet(t1, -1, '[', ']', '...', 7) FROM t1 WHERE t1 MATCH $v2; + } [list $res] + + do_execsql_test $tn.3 { + DELETE FROM t1; + INSERT INTO t1 VALUES($v1, NULL); + SELECT snippet(t1, -1, '[', ']', '...', 7) FROM t1 WHERE t1 MATCH $v2 + ORDER BY rank DESC; + } [list $res] + + +} + + +foreach {tn doc res} { + + 1.1 {X o o o o o o} {[X] o o o o o o} + 1.2 {o X o o o o o} {o [X] o o o o o} + 1.3 {o o X o o o o} {o o [X] o o o o} + 1.4 {o o o X o o o} {o o o [X] o o o} + 1.5 {o o o o X o o} {o o o o [X] o o} + 1.6 {o o o o o X o} {o o o o o [X] o} + 1.7 {o o o o o o X} {o o o o o o [X]} + + 2.1 {X o o o o o o o} {[X] o o o o o o...} + 2.2 {o X o o o o o o} {o [X] o o o o o...} + 2.3 {o o X o o o o o} {o o [X] o o o o...} + 2.4 {o o o X o o o o} {o o o [X] o o o...} + 2.5 {o o o o X o o o} {...o o o [X] o o o} + 2.6 {o o o o o X o o} {...o o o o [X] o o} + 2.7 {o o o o o o X o} {...o o o o o [X] o} + 2.8 {o o o o o o o X} {...o o o o o o [X]} + + 3.1 {X o o o o o o o o} {[X] o o o o o o...} + 3.2 {o X o o o o o o o} {o [X] o o o o o...} + 3.3 {o o X o o o o o o} {o o [X] o o o o...} + 3.4 {o o o X o o o o o} {o o o [X] o o o...} + 3.5 {o o o o X o o o o} {...o o o [X] o o o...} + 3.6 {o o o o o X o o o} {...o o o [X] o o o} + 3.7 {o o o o o o X o o} {...o o o o [X] o o} + 3.8 {o o o o o o o X o} {...o o o o o [X] o} + 3.9 {o o o o o o o o X} {...o o o o o o [X]} + + 4.1 {X o o o o o X o o} {[X] o o o o o [X]...} + 4.2 {o X o o o o o X o} {...[X] o o o o o [X]...} + 4.3 {o o X o o o o o X} {...[X] o o o o o [X]} + + 5.1 {X o o o o X o o o} {[X] o o o o [X] o...} + 5.2 {o X o o o o X o o} {...[X] o o o o [X] o...} + 5.3 {o o X o o o o X o} {...[X] o o o o [X] o} + 5.4 {o o o X o o o o X} {...o [X] o o o o [X]} + + 6.1 {X o o o X o o o} {[X] o o o [X] o o...} + 6.2 {o X o o o X o o o} {o [X] o o o [X] o...} + 6.3 {o o X o o o X o o} {...o [X] o o o [X] o...} + 6.4 {o o o X o o o X o} {...o [X] o o o [X] o} + 6.5 {o o o o X o o o X} {...o o [X] o o o [X]} + + 7.1 {X o o X o o o o o} {[X] o o [X] o o o...} + 7.2 {o X o o X o o o o} {o [X] o o [X] o o...} + 7.3 {o o X o o X o o o} {...o [X] o o [X] o o...} + 7.4 {o o o X o o X o o} {...o [X] o o [X] o o} + 7.5 {o o o o X o o X o} {...o o [X] o o [X] o} + 7.6 {o o o o o X o o X} {...o o o [X] o o [X]} +} { + do_snippet_test 1.$tn $doc X $res +} + +if {[detail_is_full]} { + foreach {tn doc res} { + 1.1 {X Y o o o o o} {[X Y] o o o o o} + 1.2 {o X Y o o o o} {o [X Y] o o o o} + 1.3 {o o X Y o o o} {o o [X Y] o o o} + 1.4 {o o o X Y o o} {o o o [X Y] o o} + 1.5 {o o o o X Y o} {o o o o [X Y] o} + 1.6 {o o o o o X Y} {o o o o o [X Y]} + + 2.1 {X Y o o o o o o} {[X Y] o o o o o...} + 2.2 {o X Y o o o o o} {o [X Y] o o o o...} + 2.3 {o o X Y o o o o} {o o [X Y] o o o...} + 2.4 {o o o X Y o o o} {...o o [X Y] o o o} + 2.5 {o o o o X Y o o} {...o o o [X Y] o o} + 2.6 {o o o o o X Y o} {...o o o o [X Y] o} + 2.7 {o o o o o o X Y} {...o o o o o [X Y]} + + 3.1 {X Y o o o o o o o} {[X Y] o o o o o...} + 3.2 {o X Y o o o o o o} {o [X Y] o o o o...} + 3.3 {o o X Y o o o o o} {o o [X Y] o o o...} + 3.4 {o o o X Y o o o o} {...o o [X Y] o o o...} + 3.5 {o o o o X Y o o o} {...o o [X Y] o o o} + 3.6 {o o o o o X Y o o} {...o o o [X Y] o o} + 3.7 {o o o o o o X Y o} {...o o o o [X Y] o} + 3.8 {o o o o o o o X Y} {...o o o o o [X Y]} + } { + do_snippet_test 2.$tn $doc "X + Y" $res + } +} + +} ;# foreach_detail_mode + +finish_test + diff --git a/ext/fts5/test/fts5ag.test b/ext/fts5/test/fts5ag.test new file mode 100644 index 0000000..de126a2 --- /dev/null +++ b/ext/fts5/test/fts5ag.test @@ -0,0 +1,145 @@ +# 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 fts5ag + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# This file attempts to verify that the extension APIs work with +# "ORDER BY rank" queries. This is done by comparing the results of +# the fts5_test() function when run with queries of the form: +# +# ... WHERE fts MATCH ? ORDER BY bm25(fts) [ASC|DESC] +# +# and +# +# ... WHERE fts MATCH ? ORDER BY rank [ASC|DESC] +# + +foreach_detail_mode $testprefix { + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y, z, detail=%DETAIL%); +} + +do_test 1.1 { + foreach {x y z} { + {j s m y m r n l u k} {z k f u z g h s w g} {r n o s s b v n w w} + {m v g n d x q r r s} {q t d a q a v l h j} {s k l f s i n v q v} + {m f f d h h s o h a} {y e v r q i u m h d} {b c k q m z l z h n} + {j e m v k p e c j m} {m p v z d x l n i a} {v p u p m t p q i f} + {v r w l e e t d z p} {c s b w k m n k o u} {w g y f v w v w v p} + {k d g o u j p z n o} {t g e q l z i g b j} {f i q q j y h b g h} + {j s w x o t j b t m} {v a v v r t x c q a} {r t k x w u l h a g} + {j y b i u d e m d w} {y s o j h i n a u p} {n a g b u c w e b m} + {b c k s c w j p w b} {m o c o w o b d q q} {n t y o y z y r z e} + {p n q l e l h z q c} {n s e i h c v b b u} {m p d i t a o o f f} + {k c o n v e z l b m} {s m n i n s d e s u} {t a u e q d a o u c} + {h d t o i a g b b p} {k x c i g f g b b k} {x f i v n a n n j i} + {f z k r b u s k z e} {n z v z w l e r h t} {t i s v v a v p n s} + {k f e c t z r e f d} {f m g r c w q k b v} {v y s y f r b f e f} + {z r c t d q q h x b} {u c g z n z u v s s} {y t n f f x b f d x} + {u n p n u t i m e j} {p j j d m f k p m z} {d o l v c o e a h w} + {h o q w t f v i c y} {c q u n r z s l l q} {z x a q w s b w s y} + {y m s x k i m n x c} {b i a n v h z n k a} {w l q p b h h g d y} + {z v s j f p v l f w} {c s b i z e k i g c} {x b v d w j f e d z} + {r k k j e o m k g b} {h b d c h m y b t u} {u j s h k z c u d y} + {v h i v s y z i k l} {d t m w q w c a z p} {r s e s x v d w k b} + {u r e q j y h o o s} {x x z r x y t f j s} {k n h x i i u e c v} + {q l f d a p w l q o} {y z q w j o p b o v} {s u h z h f d f n l} + {q o e o x x l g q i} {j g m h q q w c d b} {o m d h w a g b f n} + {m x k t s s y l v a} {j x t c a u w b w g} {n f j b v x y p u t} + {u w k a q b u w k w} {a h j u o w f s k p} {j o f s h y t j h g} + {x v b l m t l m h l} {t p y i y i q b q a} {k o o z w a c h c f} + {j g c d k w b d t v} {a k v c m a v h v p} {i c a i j g h l j h} + {l m v l c z j b p b} {z p z f l n k i b a} {j v q k g i x g i b} + {m c i w u z m i s z} {i z r f n l q z k w} {x n b p b q r g i z} + {d g i o o x l f x d} {r t m f b n q y c b} {i u g k w x n m p o} + {t o s i q d z x d t} {v a k s q z j c o o} {z f n n r l y w v v} + {w k h d t l j g n n} {r z m v y b l n c u} {v b v s c l n k g v} + {m a g r a b u u n z} {u y l h v w v k b f} {x l p g i s j f x v} + {v s g x k z a k a r} {l t g v j q l k p l} {f h n a x t v s t y} + {z u v u x p s j y t} {g b q e e g l n w g} {e n p j i g j f u r} + {q z l t w o l m p e} {t s g h r p r o t z} {y b f a o n u m z g} + {d t w n y b o g f o} {d a j e r l g g s h} {d z e l w q l t h f} + {f l u w q v x j a h} {f n u l l d m h h w} {d x c c e r o d q j} + {b y f q s q f u l g} {u z w l f d b i a g} {m v q b g u o z e z} + {h z p t s e x i v m} {l h q m e o x x x j} {e e d n p r m g j f} + {k h s g o n s d a x} {u d t t s j o v h a} {z r b a e u v o e s} + {m b b g a f c p a t} {w c m j o d b l g e} {f p j p m o s y v j} + {c r n h d w c a b l} {s g e u s d n j b g} {b o n a x a b x y l} + {r h u x f c d z n o} {x y l g u m i i w d} {t f h b z v r s r g} + {t i o r b v g g p a} {d x l u q k m o s u} {j f h t u n z u k m} + {g j t y d c n j y g} {w e s k v c w i g t} {g a h r g v g h r o} + {e j l a q j g i n h} {d z k c u p n u p p} {t u e e v z v r r g} + {l j s g k j k h z l} {p v d a t x d e q u} {r l u z b m g k s j} + {i e y d u x d i n l} {p f z k m m w p u l} {z l p m r q w n d a} + } { + execsql { INSERT INTO t1 VALUES($x, $y, $z) } + } + set {} {} +} {} + +fts5_aux_test_functions db + +proc do_fts5ag_test {tn E} { + set q1 {SELECT fts5_test_all(t1) FROM t1 WHERE t1 MATCH $E ORDER BY rank} + set q2 {SELECT fts5_test_all(t1) FROM t1 WHERE t1 MATCH $E ORDER BY bm25(t1)} + + set res [execsql $q1] + set expected [execsql $q2] + uplevel [list do_test $tn.1 [list set {} $res] $expected] + + append q1 " DESC" + append q2 " DESC" + + set res [execsql $q1] + set expected [execsql $q2] + uplevel [list do_test $tn.2 [list set {} $res] $expected] +} + +foreach {tn expr} { + 2.1 a + 2.2 b + 2.3 c + 2.4 d + + 3.0 {a AND b} + 3.1 {a OR b} + 3.2 {b OR c AND d} +} { + do_fts5ag_test $tn $expr +} + +if {[detail_is_full]} { + foreach {tn expr} { + 4.1 {"m m"} + 4.2 {e + s} + 4.3 {NEAR(c d)} + } { + do_fts5ag_test $tn $expr + } +} + +} ;# foreach_detail_mode + + +finish_test + diff --git a/ext/fts5/test/fts5ah.test b/ext/fts5/test/fts5ah.test new file mode 100644 index 0000000..b7beb56 --- /dev/null +++ b/ext/fts5/test/fts5ah.test @@ -0,0 +1,170 @@ +# 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 fts5ah + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +#------------------------------------------------------------------------- +# This file contains tests for very large doclists. +# + +set Y [list] +set W [list] +do_test 1.0 { + execsql { CREATE VIRTUAL TABLE t1 USING fts5(a, detail=%DETAIL%) } + execsql { INSERT INTO t1(t1, rank) VALUES('pgsz', 128) } + set v {w w w w w w w w w w w w w w w w w w w w} + execsql { INSERT INTO t1(rowid, a) VALUES(0, $v) } + for {set i 1} {$i <= 10000} {incr i} { + set v {x x x x x x x x x x x x x x x x x x x x} + if {($i % 2139)==0} {lset v 3 Y ; lappend Y $i} + if {($i % 1577)==0} {lset v 5 W ; lappend W $i} + execsql { INSERT INTO t1 VALUES($v) } + } + set v {w w w w w w w w w w w w w w w w w w w w} + execsql { INSERT INTO t1 VALUES($v) } +} {} + +do_execsql_test 1.1.1 { + SELECT rowid FROM t1 WHERE t1 MATCH 'x AND w' +} [lsort -integer -incr $W] + +do_execsql_test 1.1.2 { + SELECT rowid FROM t1 WHERE t1 MATCH 'x* AND w*' +} [lsort -integer -incr $W] + +do_execsql_test 1.2 { + SELECT rowid FROM t1 WHERE t1 MATCH 'y AND x' +} [lsort -integer -incr $Y] + +do_execsql_test 1.3 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +proc reads {} { + db one {SELECT t1 FROM t1 WHERE t1 MATCH '*reads'} +} + +proc execsql_reads {sql} { + set nRead [reads] + execsql $sql + expr [reads] - $nRead +} + +do_test 1.4 { + set nRead [reads] + execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'x' } + set nReadX [expr [reads] - $nRead] + #puts -nonewline "(nReadX=$nReadX)" + if {[detail_is_full]} { set expect 1000 } + if {[detail_is_col]} { set expect 250 } + if {[detail_is_none]} { set expect 80 } + + expr $nReadX>$expect +} {1} + +do_test 1.5 { + set fwd [execsql_reads {SELECT rowid FROM t1 WHERE t1 MATCH 'x' }] + set bwd [execsql_reads { + SELECT rowid FROM t1 WHERE t1 MATCH 'x' ORDER BY 1 ASC + }] + expr {$bwd < $fwd + 12} +} {1} + +foreach {tn q res} " + 1 { SELECT rowid FROM t1 WHERE t1 MATCH 'w + x' } [list $W] + 2 { SELECT rowid FROM t1 WHERE t1 MATCH 'x + w' } [list $W] + 3 { SELECT rowid FROM t1 WHERE t1 MATCH 'x AND w' } [list $W] + 4 { SELECT rowid FROM t1 WHERE t1 MATCH 'y AND x' } [list $Y] +" { + if {[detail_is_full]==0 && ($tn==1 || $tn==2)} continue + + if {[detail_is_full]} { set ratio 8 } + if {[detail_is_col]} { set ratio 4 } + if {[detail_is_none]} { set ratio 2 } + + do_test 1.6.$tn.1 { + set n [execsql_reads $q] + #puts -nonewline "(n=$n nReadX=$nReadX)" + expr {$n < ($nReadX / $ratio)} + } {1} + + do_test 1.6.$tn.2 { + set n [execsql_reads "$q ORDER BY rowid DESC"] + #puts -nonewline "(n=$n nReadX=$nReadX)" + expr {$n < ($nReadX / $ratio)} + } {1} + + do_execsql_test 1.6.$tn.3 $q [lsort -int -incr $res] + do_execsql_test 1.6.$tn.4 "$q ORDER BY rowid DESC" [lsort -int -decr $res] +} + +#------------------------------------------------------------------------- +# Now test that adding range constraints on the rowid field reduces the +# number of pages loaded from disk. +# +foreach {tn fraction tail cnt} { + 1 0.6 {rowid > 5000} 5000 + 2 0.2 {rowid > 9000} 1000 + 3 0.2 {rowid < 1000} 999 + 4 0.2 {rowid BETWEEN 4000 AND 5000} 1001 + 5 0.6 {rowid >= 5000} 5001 + 6 0.2 {rowid >= 9000} 1001 + 7 0.2 {rowid <= 1000} 1000 + 8 0.6 {rowid > '5000'} 5000 + 9 0.2 {rowid > '9000'} 1000 + 10 0.1 {rowid = 444} 1 +} { + set q "SELECT rowid FROM t1 WHERE t1 MATCH 'x' AND $tail" + set n [execsql_reads $q] + set ret [llength [execsql $q]] + + # Because the position lists for 'x' are quite long in this db, the + # advantage is a bit smaller in detail=none mode. Update $fraction to + # reflect this. + if {[detail_is_none] && $fraction<0.5} { set fraction [expr $fraction*2] } + + do_test "1.7.$tn.asc.(n=$n ret=$ret)" { + expr {$n < ($fraction*$nReadX) && $ret==$cnt} + } {1} + + set q "SELECT rowid FROM t1 WHERE t1 MATCH 'x' AND $tail ORDER BY rowid DESC" + set n [execsql_reads $q] + set ret [llength [execsql $q]] + do_test "1.7.$tn.desc.(n=$n ret=$ret)" { + expr {$n < 2*$fraction*$nReadX && $ret==$cnt} + } {1} +} + +do_execsql_test 1.8.1 { + SELECT count(*) FROM t1 WHERE t1 MATCH 'x' AND +rowid < 'text'; +} {10000} +do_execsql_test 1.8.2 { + SELECT count(*) FROM t1 WHERE t1 MATCH 'x' AND rowid < 'text'; +} {10000} + +} ;# foreach_detail_mode + +#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r} + +finish_test + diff --git a/ext/fts5/test/fts5ai.test b/ext/fts5/test/fts5ai.test new file mode 100644 index 0000000..e32c806 --- /dev/null +++ b/ext/fts5/test/fts5ai.test @@ -0,0 +1,58 @@ +# 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. +# +# Specifically, it tests transactions and savepoints +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5ai + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=%DETAIL%); +} {} + +do_execsql_test 1.1 { + BEGIN; + INSERT INTO t1 VALUES('a b c'); + INSERT INTO t1 VALUES('d e f'); + SAVEPOINT one; + INSERT INTO t1 VALUES('g h i'); + SAVEPOINT two; + INSERT INTO t1 VALUES('j k l'); + ROLLBACK TO one; + INSERT INTO t1 VALUES('m n o'); + SAVEPOINT two; + INSERT INTO t1 VALUES('p q r'); + RELEASE one; + SAVEPOINT one; + INSERT INTO t1 VALUES('s t u'); + ROLLBACK TO one; + COMMIT; +} + +do_execsql_test 1.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} +} + + +finish_test + diff --git a/ext/fts5/test/fts5aj.test b/ext/fts5/test/fts5aj.test new file mode 100644 index 0000000..6b9dddd --- /dev/null +++ b/ext/fts5/test/fts5aj.test @@ -0,0 +1,69 @@ +# 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. +# +# Specifically, this tests that, provided the amount of data remains +# constant, the FTS index does not grow indefinitely as rows are inserted +# and deleted, +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5aj + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc doc {} { + set dict [list a b c d e f g h i j k l m n o p q r s t u v w x y z] + set res [list] + for {set i 0} {$i < 20} {incr i} { + lappend res [lindex $dict [expr int(rand() * 26)]] + } + set res +} + +proc structure {} { + set val [db one {SELECT fts5_decode(rowid,block) FROM t1_data WHERE rowid=10}] + foreach lvl [lrange $val 1 end] { + lappend res [expr [llength $lvl]-2] + } + set res +} + +expr srand(0) +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', 64); +} + +for {set iTest 0} {$iTest < 50000} {incr iTest} { + if {$iTest > 1000} { execsql { DELETE FROM t1 WHERE rowid=($iTest-1000) } } + set new [doc] + execsql { INSERT INTO t1 VALUES($new) } + if {$iTest==10000} { set sz1 [db one {SELECT count(*) FROM t1_data}] } + if {0==($iTest % 1000)} { + set sz [db one {SELECT count(*) FROM t1_data}] + set s [structure] + do_execsql_test 1.$iTest.$sz.{$s} { + INSERT INTO t1(t1) VALUES('integrity-check') + } + } +} + +do_execsql_test 2.0 { INSERT INTO t1(t1) VALUES('integrity-check') } + + +finish_test + diff --git a/ext/fts5/test/fts5ak.test b/ext/fts5/test/fts5ak.test new file mode 100644 index 0000000..0f699a6 --- /dev/null +++ b/ext/fts5/test/fts5ak.test @@ -0,0 +1,150 @@ +# 2014 November 24 +# +# 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. +# +# Specifically, the auxiliary function "highlight". +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5ak + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +do_execsql_test 1.1 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, detail=%DETAIL%); + INSERT INTO ft1 VALUES('i d d a g i b g d d'); + INSERT INTO ft1 VALUES('h d b j c c g a c a'); + INSERT INTO ft1 VALUES('e j a e f h b f h h'); + INSERT INTO ft1 VALUES('j f h d g h i b d f'); + INSERT INTO ft1 VALUES('d c j d c j b c g e'); + INSERT INTO ft1 VALUES('i a d e g j g d a a'); + INSERT INTO ft1 VALUES('j f c e d a h j d b'); + INSERT INTO ft1 VALUES('i c c f a d g h j e'); + INSERT INTO ft1 VALUES('i d i g c d c h b f'); + INSERT INTO ft1 VALUES('g d a e h a b c f j'); + + CREATE VIRTUAL TABLE ft2 USING fts5(x, detail=%DETAIL%); + INSERT INTO ft2 VALUES('a b c d e f g h i j'); +} + +do_execsql_test 1.2 { + SELECT highlight(ft1, 0, '[', ']') FROM ft1 WHERE ft1 MATCH 'e'; +} { + {[e] j a [e] f h b f h h} + {d c j d c j b c g [e]} + {i a d [e] g j g d a a} + {j f c [e] d a h j d b} + {i c c f a d g h j [e]} + {g d a [e] h a b c f j} +} + +do_execsql_test 1.3 { + SELECT highlight(ft1, 0, '[', ']') FROM ft1 WHERE ft1 MATCH 'e e e' +} { + {[e] j a [e] f h b f h h} + {d c j d c j b c g [e]} + {i a d [e] g j g d a a} + {j f c [e] d a h j d b} + {i c c f a d g h j [e]} + {g d a [e] h a b c f j} +} + +do_execsql_test 1.4 { + SELECT highlight(ft2, 0, '[', ']') FROM ft2 WHERE ft2 MATCH 'f d' +} { + {a b c [d] e [f] g h i j} +} + +do_execsql_test 1.5 { + SELECT highlight(ft2, 0, '[', ']') FROM ft2 WHERE ft2 MATCH 'd f' +} { + {a b c [d] e [f] g h i j} +} + +#------------------------------------------------------------------------- +# Tests below this point require detail=full. +#------------------------------------------------------------------------- +if {[detail_is_full]==0} continue + + +do_execsql_test 2.1 { + SELECT highlight(ft1, 0, '[', ']') FROM ft1 WHERE ft1 MATCH 'h + d'; +} { + {[h d] b j c c g a c a} + {j f [h d] g h i b d f} +} + +do_execsql_test 2.2 { + SELECT highlight(ft1, 0, '[', ']') FROM ft1 WHERE ft1 MATCH 'd + d'; +} { + {i [d d] a g i b g [d d]} +} + +do_execsql_test 2.3 { + SELECT highlight(ft1, 0, '[', ']') FROM ft1 WHERE ft1 MATCH 'd + d d + d'; +} { + {i [d d] a g i b g [d d]} +} + +do_execsql_test 2.4 { + SELECT highlight(ft2, 0, '[', ']') FROM ft2 WHERE ft2 MATCH 'b+c+d c+d+e' +} {{a [b c d e] f g h i j}} + +do_execsql_test 2.5 { + SELECT highlight(ft2, 0, '[', ']') FROM ft2 WHERE ft2 MATCH 'b+c+d e+f+g' +} { + {a [b c d] [e f g] h i j} +} + +do_execsql_test 2.6 { + SELECT highlight(ft2, 0, '[', ']') FROM ft2 WHERE ft2 MATCH 'b+c+d c' +} { + {a [b c d] e f g h i j} +} + +do_execsql_test 2.7 { + SELECT highlight(ft2, 0, '[', ']') FROM ft2 WHERE ft2 MATCH 'b+c c+d+e' +} { + {a [b c d e] f g h i j} +} + +#------------------------------------------------------------------------- +# The example from the docs. +# +do_execsql_test 3.1 { + -- Assuming this: + CREATE VIRTUAL TABLE ft USING fts5(a, detail=%DETAIL%); + INSERT INTO ft VALUES('a b c x c d e'); + INSERT INTO ft VALUES('a b c c d e'); + INSERT INTO ft VALUES('a b c d e'); + + -- The following SELECT statement returns these three rows: + -- '[a b c] x [c d e]' + -- '[a b c] [c d e]' + -- '[a b c d e]' + SELECT highlight(ft, 0, '[', ']') FROM ft WHERE ft MATCH 'a+b+c AND c+d+e'; +} { + {[a b c] x [c d e]} + {[a b c] [c d e]} + {[a b c d e]} +} + +} + +finish_test + diff --git a/ext/fts5/test/fts5al.test b/ext/fts5/test/fts5al.test new file mode 100644 index 0000000..c0dd211 --- /dev/null +++ b/ext/fts5/test/fts5al.test @@ -0,0 +1,300 @@ +# 2014 November 24 +# +# 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. +# +# Specifically, this function tests the %_config table. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5al + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +do_execsql_test 1.1 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, detail=%DETAIL%); + SELECT * FROM ft1_config; +} {version 4} + +do_execsql_test 1.2 { + INSERT INTO ft1(ft1, rank) VALUES('pgsz', 32); + SELECT * FROM ft1_config; +} {pgsz 32 version 4} + +do_execsql_test 1.3 { + INSERT INTO ft1(ft1, rank) VALUES('pgsz', 64); + SELECT * FROM ft1_config; +} {pgsz 64 version 4} + +#-------------------------------------------------------------------------- +# Test the logic for parsing the rank() function definition. +# +foreach {tn defn} { + 1 "fname()" + 2 "fname(1)" + 3 "fname(1,2)" + 4 "fname(null,NULL,nUlL)" + 5 " fname ( null , NULL , nUlL ) " + 6 "fname('abc')" + 7 "fname('a''bc')" + 8 "fname('''abc')" + 9 "fname('abc''')" + + 7 "fname( 'a''bc' )" + 8 "fname('''abc' )" + 9 "fname( 'abc''' )" + + 10 "fname(X'1234ab')" + + 11 "myfunc(1.2)" + 12 "myfunc(-1.0)" + 13 "myfunc(.01,'abc')" +} { + do_execsql_test 2.1.$tn { + INSERT INTO ft1(ft1, rank) VALUES('rank', $defn); + } +} + +foreach {tn defn} { + 1 "" + 2 "fname" + 3 "fname(X'234ab')" + 4 "myfunc(-1.,'abc')" +} { + do_test 2.2.$tn { + catchsql { INSERT INTO ft1(ft1, rank) VALUES('rank', $defn) } + } {1 {SQL logic error or missing database}} +} + +#------------------------------------------------------------------------- +# Assorted tests of the tcl interface for creating extension functions. +# + +do_execsql_test 3.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); + INSERT INTO t1 VALUES('q w e r t y'); + INSERT INTO t1 VALUES('y t r e w q'); +} + +proc argtest {cmd args} { return $args } +sqlite3_fts5_create_function db argtest argtest + +do_execsql_test 3.2.1 { + SELECT argtest(t1, 123) FROM t1 WHERE t1 MATCH 'q' +} {123 123} + +do_execsql_test 3.2.2 { + SELECT argtest(t1, 123, 456) FROM t1 WHERE t1 MATCH 'q' +} {{123 456} {123 456}} + +proc rowidtest {cmd} { $cmd xRowid } +sqlite3_fts5_create_function db rowidtest rowidtest + +do_execsql_test 3.3.1 { + SELECT rowidtest(t1) FROM t1 WHERE t1 MATCH 'q' +} {1 2} + +proc insttest {cmd} { + set res [list] + for {set i 0} {$i < [$cmd xInstCount]} {incr i} { + lappend res [$cmd xInst $i] + } + set res +} +sqlite3_fts5_create_function db insttest insttest + +do_execsql_test 3.4.1 { + SELECT insttest(t1) FROM t1 WHERE t1 MATCH 'q' +} { + {{0 0 0}} + {{0 0 5}} +} + +if {[detail_is_full]} { + do_execsql_test 3.4.2 { + SELECT insttest(t1) FROM t1 WHERE t1 MATCH 'r+e OR w' + } { + {{1 0 1}} + {{0 0 2} {1 0 4}} + } +} + +proc coltest {cmd} { + list [$cmd xColumnSize 0] [$cmd xColumnText 0] +} +sqlite3_fts5_create_function db coltest coltest + +do_execsql_test 3.5.1 { + SELECT coltest(t1) FROM t1 WHERE t1 MATCH 'q' +} { + {6 {q w e r t y}} + {6 {y t r e w q}} +} + +#------------------------------------------------------------------------- +# Tests for remapping the "rank" column. +# +# 4.1.*: Mapped to a function with no arguments. +# 4.2.*: Mapped to a function with one or more arguments. +# + +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE t2 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t2 VALUES('a s h g s b j m r h', 's b p a d b b a o e'); + INSERT INTO t2 VALUES('r h n t a g r d d i', 'l d n j r c f t o q'); + INSERT INTO t2 VALUES('q k n i k c a a e m', 'c h n j p g s c i t'); + INSERT INTO t2 VALUES('h j g t r e l s g s', 'k q k c i i c k n s'); + INSERT INTO t2 VALUES('b l k h d n n n m i', 'p t i a r b t q o l'); + INSERT INTO t2 VALUES('k r i l j b g i p a', 't q c h a i m g n l'); + INSERT INTO t2 VALUES('a e c q n m o m d g', 'l c t g i s q g q e'); + INSERT INTO t2 VALUES('b o j h f o g b p e', 'r t l h s b g i c p'); + INSERT INTO t2 VALUES('s q k f q b j g h f', 'n m a o p e i e k t'); + INSERT INTO t2 VALUES('o q g g q c o k a b', 'r t k p t f t h p c'); +} + +proc firstinst {cmd} { + foreach {p c o} [$cmd xInst 0] {} + expr $c*100 + $o +} +sqlite3_fts5_create_function db firstinst firstinst + +do_execsql_test 4.1.1 { + SELECT rowid, firstinst(t2) FROM t2 WHERE t2 MATCH 'a' ORDER BY rowid ASC +} { + 1 0 2 4 3 6 5 103 + 6 9 7 0 9 102 10 8 +} + +do_execsql_test 4.1.2 { + SELECT rowid, rank FROM t2 + WHERE t2 MATCH 'a' AND rank MATCH 'firstinst()' + ORDER BY rowid ASC +} { + 1 0 2 4 3 6 5 103 + 6 9 7 0 9 102 10 8 +} + +do_execsql_test 4.1.3 { + SELECT rowid, rank FROM t2 + WHERE t2 MATCH 'a' AND rank MATCH 'firstinst()' + ORDER BY rank DESC +} { + 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0 +} + +do_execsql_test 4.1.4 { + INSERT INTO t2(t2, rank) VALUES('rank', 'firstinst()'); + SELECT rowid, rank FROM t2 WHERE t2 MATCH 'a' ORDER BY rowid ASC +} { + 1 0 2 4 3 6 5 103 + 6 9 7 0 9 102 10 8 +} + +do_execsql_test 4.1.5 { + SELECT rowid, rank FROM t2 WHERE t2 MATCH 'a' ORDER BY rank DESC +} { + 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0 +} + +do_execsql_test 4.1.6 { + INSERT INTO t2(t2, rank) VALUES('rank', 'firstinst ( ) '); + SELECT rowid, rank FROM t2 WHERE t2 MATCH 'a' ORDER BY rank DESC +} { + 5 103 9 102 6 9 10 8 3 6 2 4 1 0 7 0 +} + +proc rowidplus {cmd ival} { + expr [$cmd xRowid] + $ival +} +sqlite3_fts5_create_function db rowidplus rowidplus + +if {[detail_is_full]} { + do_execsql_test 4.2.1 { + INSERT INTO t2(t2, rank) VALUES('rank', 'rowidplus(100) '); + SELECT rowid, rank FROM t2 WHERE t2 MATCH 'o + q + g' + } { + 10 110 + } + do_execsql_test 4.2.2 { + INSERT INTO t2(t2, rank) VALUES('rank', 'rowidplus(111) '); + SELECT rowid, rank FROM t2 WHERE t2 MATCH 'o + q + g' + } { + 10 121 + } + + do_execsql_test 4.2.3 { + SELECT rowid, rank FROM t2 + WHERE t2 MATCH 'o + q + g' AND rank MATCH 'rowidplus(112)' + } { + 10 122 + } +} + +proc rowidmod {cmd imod} { + expr [$cmd xRowid] % $imod +} +sqlite3_fts5_create_function db rowidmod rowidmod +do_execsql_test 4.3.1 { + CREATE VIRTUAL TABLE t3 USING fts5(x, detail=%DETAIL%); + INSERT INTO t3 VALUES('a one'); + INSERT INTO t3 VALUES('a two'); + INSERT INTO t3 VALUES('a three'); + INSERT INTO t3 VALUES('a four'); + INSERT INTO t3 VALUES('a five'); + INSERT INTO t3(t3, rank) VALUES('rank', 'bm25()'); +} + +do_execsql_test 4.3.2 { + SELECT * FROM t3 + WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(4)' + ORDER BY rank ASC +} { + {a four} {a one} {a five} {a two} {a three} +} + +do_execsql_test 4.3.3 { + SELECT *, rank FROM t3 + WHERE t3 MATCH 'a' AND rank MATCH 'rowidmod(3)' + ORDER BY rank ASC +} { + {a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2 +} + +do_execsql_test 4.3.4 { + SELECT * FROM t3('a', 'rowidmod(4)') ORDER BY rank ASC; +} { + {a four} {a one} {a five} {a two} {a three} +} + +do_execsql_test 4.3.5 { + SELECT *, rank FROM t3('a', 'rowidmod(3)') ORDER BY rank ASC +} { + {a three} 0 {a one} 1 {a four} 1 {a two} 2 {a five} 2 +} + +do_catchsql_test 4.4.3 { + SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH 'xyz(3)' +} {1 {no such function: xyz}} +do_catchsql_test 4.4.4 { + SELECT *, rank FROM t3 WHERE t3 MATCH 'a' AND rank MATCH NULL +} {1 {parse error in rank function: }} + +} ;# foreach_detail_mode + + +finish_test + diff --git a/ext/fts5/test/fts5alter.test b/ext/fts5/test/fts5alter.test new file mode 100644 index 0000000..eae01b7 --- /dev/null +++ b/ext/fts5/test/fts5alter.test @@ -0,0 +1,103 @@ +# 2015 Jun 10 +# +# 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 tests in this file focus on renaming FTS5 tables using the +# "ALTER TABLE ... RENAME TO ..." command +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5alter + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# Test renaming regular, contentless and columnsize=0 FTS5 tables. +# +do_execsql_test 1.1.0 { + CREATE VIRTUAL TABLE "a x" USING fts5(a, x); + INSERT INTO "a x" VALUES('a a a', 'x x x'); + ALTER TABLE "a x" RENAME TO "x y"; +} +do_execsql_test 1.1.1 { + SELECT * FROM "x y"; + SELECT rowid FROM "x y" WHERE "x y" MATCH 'a' +} {{a a a} {x x x} 1} + +do_execsql_test 1.2.0 { + CREATE VIRTUAL TABLE "one/two" USING fts5(one, columnsize=0); + INSERT INTO "one/two"(rowid, one) VALUES(456, 'd d d'); + ALTER TABLE "one/two" RENAME TO "three/four"; +} +do_execsql_test 1.2.1 { + SELECT * FROM "three/four"; + SELECT rowid FROM "three/four" WHERE "three/four" MATCH 'd' +} {{d d d} 456} + +do_execsql_test 1.3.0 { + CREATE VIRTUAL TABLE t1 USING fts5(val, content=''); + INSERT INTO t1(rowid, val) VALUES(-1, 'drop table'); + INSERT INTO t1(rowid, val) VALUES(-2, 'drop view'); + ALTER TABLE t1 RENAME TO t2; +} +do_execsql_test 1.3.1 { + SELECT rowid, * FROM t2; + SELECT rowid FROM t2 WHERE t2 MATCH 'table' +} {-2 {} -1 {} -1} + +#------------------------------------------------------------------------- +# Test renaming an FTS5 table within a transaction. +# +do_execsql_test 2.1 { + CREATE VIRTUAL TABLE zz USING fts5(a); + INSERT INTO zz(rowid, a) VALUES(-56, 'a b c'); + BEGIN; + INSERT INTO zz(rowid, a) VALUES(-22, 'a b c'); + ALTER TABLE zz RENAME TO yy; + SELECT rowid FROM yy WHERE yy MATCH 'a + b + c'; + COMMIT; +} {-56 -22} + +do_execsql_test 2.2 { + BEGIN; + ALTER TABLE yy RENAME TO ww; + INSERT INTO ww(rowid, a) VALUES(-11, 'a b c'); + SELECT rowid FROM ww WHERE ww MATCH 'a + b + c'; +} {-56 -22 -11} + +do_execsql_test 2.3 { + ROLLBACK; + SELECT rowid FROM yy WHERE yy MATCH 'a + b + c'; +} {-56 -22} + +#------------------------------------------------------------------------- + +do_execsql_test 3.1 { + CREATE VIRTUAL TABLE abc USING fts5(a); + INSERT INTO abc(rowid, a) VALUES(1, 'a'); + BEGIN; + INSERT INTO abc(rowid, a) VALUES(2, 'a'); +} +breakpoint +do_execsql_test 3.2 { + SELECT rowid FROM abc WHERE abc MATCH 'a'; +} {1 2} + +do_execsql_test 3.3 { + COMMIT; + SELECT rowid FROM abc WHERE abc MATCH 'a'; +} {1 2} + +finish_test + diff --git a/ext/fts5/test/fts5auto.test b/ext/fts5/test/fts5auto.test new file mode 100644 index 0000000..218b3f4 --- /dev/null +++ b/ext/fts5/test/fts5auto.test @@ -0,0 +1,345 @@ +# 2015 May 30 +# +# 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 contains automatically generated tests for various types +# of MATCH expressions. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5auto + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +set data { + -4026076 + {n x w k b p x b n t t d s} {f j j s p j o} + {w v i y r} {i p y s} + {a o q v e n q r} {q v g u c y a z y} + 3995120 + {c} {e e w d t} + {x c p f w r s m l r b f d} {g g u e} + {s n u t d v p d} {b k v p m f} + -2913881 + {k m} {a} + {w r j z n s l} {m j i w d t w e l} + {z n c} {v f b m} + 174082 + {j} {q l w u k e q v r i} + {j l} {u v w r s p e l} + {p i k j k q c t g u s} {g u y s m h q k g t e s o r} + 3207399 + {e t} {} + {p} {y v r b e k h d e v} + {t m w z b g q t s d d h} {o n v u i t o y k j} + 182399 + {} {m o s o x d y f a x j z} + {x n z r c d} {n r x i r} + {s v s} {a u} + 768994 + {e u t q v z q k j p u f j p} {y c b} + {p s d} {k n w p m p p} + {u o x s d} {f s g r d b d r m m m z y} + 3931037 + {c j p x e} {c n k t h z o i} + {} {r r p j k x w q} + {o r d z d} {x} + 3105748 + {p x r u} {x i s w o t o g x m z i w} + {q x m z} {h c j w b l y w x c o} + {m b k v} {t v q i s a d x} + -2501642 + {o u d n w o m o o s n t r h} {k p e u y p e z d j r y g} + {v b b h d d q y j q j} {a m w d t} + {y e f n} {a k x i x} + -1745680 + {z u w j f d b f} {j w i c g u d w e} + {m f p v m a s p v c o s} {s c r z o t w l b e a q} + {m k q} {k b a v o} + -932328 + {r v i u m q d r} {f z u v h c m r f g} + {r x r} {k p i d h h w h z u a x} + {k m j p} {h l j a e u c i q x x f x g} + -3923818 + {t t p b n u i h e c k} {m z} + {v u d c} {v y y j s g} + {o a f k k q p h g x e n z x} {h d w c o l} + -2145922 + {z z l f a l g e d c d h} {j b j p k o o u b q} + {d i g q t f d r h k} {n w g j c x r p t y f l c t} + {d o c u k f o} {r y s x z s p p h g t p y c} + 4552917 + {j w j y h l k u} {n a} + {y h w c n k} {b} + {w} {z l r t s i m v c y} + 2292008 + {q v q j w y y x u t} {r q z n h a b o} + {d q y} {y v o e j} + {} {a b h c d l p d x} + 1407892 + {n j j u q d o a u c f} {r d b w o q n g} + {d e v w s} {v d v o u o x s l s j z y} + {j y w h i f g i h m} {v n z b n y} + -4412544 + {g h h r s} {h e r e} + {n q s} {o p z r m l l t} + {p} {f s u o b j} + 1209110 + {o a a z t t u h j} {z z i r k r} + {i c x q w g v o x z i z p} {q o g k i n z x e d v w v} + {p f v b g f e d n p u c y k} {q z z a i p a a s r e z} + 3448977 + {i v} {l u x t b o k} + {f h u v p} {k a o y j} + {d m k c j} {v c e r u e f i t} + -4703774 + {d h v w u z r e h x o l t} {p s f y w y r q d a m w} + {c h g c g j j f t b i c q} {s e} + {c t q j g f} {v n r w y r a g e j d} + 2414151 + {s o o s d s k q b f q v p e} {j r o b t o p d l o o x} + {d d k t v e} {} + {t v o d w} {w e q w h y c y y i j b a m} + -3342407 + {m c h n e p d o c r w n t} {j d k s p q l} + {t g s r w x j l r z r} {h} + {r q v x i r a n h s} {m y p b v w r a u o g q r} + -993951 + {l n p u o j d x t u u c o j} {k r n a r e k v i t o e} + {q f t t a a c z v f} {o n m p v f o e n} + {h z h i p s b j z h} {i t w m k c u g n i} + 1575251 + {} {z s i j d o x j a r t} + {h g j u j n v e n z} {p z j n n f} + {s q q f d w r l y i z d o m} {b a n d h t b y g h d} + 4263668 + {q g t h f s} {s g x p f q z i s o f l i} + {q k} {w v h a x n a r b} + {m j a h o b i x k r w z q u} {m t r g j o e q t m p u l} + 2487819 + {m w g x r n e u t s r} {b x a t u u j c r n} + {j} {w f j r e e y l p} + {o u h b} {o c a c a b v} + 167966 + {o d b s d o a u m o x y} {c} + {r w d o b v} {z e b} + {i n z a f g z o} {m u b a g} + 1948599 + {n r g q d j s} {n k} + {l b p d v t k h y y} {u m k e c} + {t b n y o t b} {j w c i r x x} + 2941631 + {l d p l b g f} {e k e} + {p j} {m c s w t b k n l d x} + {f o v y v l} {c w p s w j w c u t y} + 3561104 + {d r j j r j i g p} {u} + {g r j q} {z l p d s n f c h t d c v z} + {w r c f s x z y} {g f o k g g} + -2223281 + {y e t j j z f p o m m z} {h k o g o} + {m x a t} {l q x l} + {r w k d l s y b} {q g k b} + -4502874 + {k k b x k l f} {r} + {} {q m z b k h k u n e z} + {z q g y m y u} {} + 1757599 + {d p z j y u r} {z p l q w j t j} + {n i r x r y j} {} + {h} {w t d q c x z z x e e} + -4809589 + {} {z p x u h i i n g} + {w q s u d b f x n} {l y k b b r x t i} + {n d v j q o t o d p z e} {u r y u v u c} + 1068408 + {y e} {e g s k e w t p v o b k} + {z c m s} {r u r u h n h b p q g b} + {j k b l} {m c d t s r s q a d b o f} + -1972554 + {m s w} {d k v s a r k p a r i v} + {g j z k p} {y k c v r e u o q f i b a} + {i p i} {c z w c y b n z i v} + -2052385 + {} {x e u f f g n c i x n e i e} + {} {p s w d x p g} + {} {s j a h n} + 2805981 + {m x g c w o e} {k g u y r y i u e g g} + {f k j v t x p h x k u} {w i} + {b l f z f v t n} {i u d o d p h s m u} + 2507621 + {} {u b n l x f n j t} + {u r x l h} {h r l m r} + {d y e n b s q v t k n q q} {x l t v w h a s k} + -3138375 + {e o f j y x u w v e w z} {r d q g k n n v r c z n e w} + {l y i q z k j p u f q s k} {c i l l i m a a g a z r x f} + {a v k h m q z b y n z} {q g w c y r r o a} + -457971 + {j x a w e c s h f l f} {q} + {j f v j u m d q r v v} {x n v a w} + {i e h d h f u w t t z} {v s u l s v o v i k n e} + 2265221 + {z t c y w n y r t} {n b a x s} + {q w a v} {a b s d x i g w t e z h} + {t l} {j k r w f f y j o k u} + -3941280 + {r x t o z} {f j n z k} + {t x e b t d b k w i s} {j t y h i h} + {y q g n g s u v c z j z n g} {n n g t l p h} + 2084745 + {z d z d} {j} + {o e k t b k a z l w} {o p i h k c x} + {c r b t i j f} {z e n m} + 1265843 + {} {j s g j j x u y} + {u q t f} {g o g} + {w o j e d} {w q n a c t q x j} + -2941116 + {i n c u o} {f b} + {o m s q d o z a q} {f s v o b b} + {o a z c h r} {j e w h b f z} + -1265441 + {p g z q v a o a x a} {s t h} + {w i p o c} {s n d g f z w q o d v v l j} + {y f b i a s v} {u m o z k k s t s d p b l p} + -1989158 + {r i c n} {r e w w i n z} + {q u s y b w u g y g f o} {y} + {d} {j x i b x u y d c p v a h} + 2391989 + {b n w x w f q h p i} {e u b b i n a i o c d g} + {v a z o i e n l x l r} {r u f o r k w m d w} + {k s} {r f e j q p w} +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE tt USING fts5(a, b, c, d, e, f); +} {} + +fts5_aux_test_functions db + +proc do_auto_test {tn tbl expr} { + foreach order {asc desc} { + set res [fts5_poslist_data $expr $tbl $order] + set testname "$tn.[string range $order 0 0].rows=[expr [llength $res]/2]" + + set ::autotest_expr $expr + do_execsql_test $testname [subst -novar { + SELECT rowid, fts5_test_poslist([set tbl]) FROM [set tbl] + WHERE [set tbl] MATCH $::autotest_expr ORDER BY rowid [set order] + }] $res + } +} + +#------------------------------------------------------------------------- +# + +for {set fold 0} {$fold < 3} {incr fold} { + switch $fold { + 0 { set map {} } + 1 { set map { + a a b a c b d b e c f c g d h d + i e j e k f l f m g g g o h p h + q i r i s j t j u k v k w l x l + y m z m + }} + + 2 { set map { + a a b a c a d a e a f a g a h a + i b j b k b l b m b g b o b p b + q c r c s c t c u c v c w c x c + }} + } + + execsql { + BEGIN; + DELETE FROM tt; + } + foreach {rowid a b c d e f} [string map $map $data] { + if {$rowid==-4703774} { + execsql { + INSERT INTO tt(rowid, a, b, c, d, e, f) + VALUES($rowid, $a, $b, $c, $d, $e, $f) + } + } + } + execsql COMMIT + + + foreach {tn expr} { + A.1 { {a} : x } + A.2 { {a b} : x } + A.3 { {a b f} : x } + A.4 { {f a b} : x } + A.5 { {f a b} : x y } + A.6 { {f a b} : x + y } + A.7 { {c a b} : x + c } + A.8 { {c d} : "l m" } + A.9 { {c e} : "l m" } + A.10 { {a b c a b c a b c f f e} : "l m" } + + B.1 { a NOT b } + B.2 { a NOT a:b } + B.3 { a OR (b AND c) } + B.4 { a OR (b AND {a b c}:c) } + B.5 { a OR "b c" } + B.6 { a OR b OR c } + + C.1 { a OR (b AND "b c") } + C.2 { a OR (b AND "z c") } + } { + do_auto_test 3.$fold.$tn tt $expr + } +} + +proc replace_elems {list args} { + set ret $list + foreach {idx elem} $args { + set ret [lreplace $ret $idx $idx $elem] + } + set ret +} + +#------------------------------------------------------------------------- +# +set bigdoc [string trim [string repeat "a " 1000]] +do_test 4.0 { + set a [replace_elems $bigdoc 50 x 950 x] + set b [replace_elems $bigdoc 20 y 21 x 887 x 888 y] + set c [replace_elems $bigdoc 1 z 444 z 789 z] + execsql { + CREATE VIRTUAL TABLE yy USING fts5(c1, c2, c3); + INSERT INTO yy(rowid, c1, c2, c3) VALUES(-56789, $a, $b, $c); + INSERT INTO yy(rowid, c1, c2, c3) VALUES(250, $a, $b, $c); + } +} {} + +foreach {tn expr} { + 1 x + 2 y + 3 z + + 4 {c1 : x} 5 {c2 : x} 6 {c3 : x} + 7 {c1 : y} 8 {c2 : y} 9 {c3 : y} + 10 {c1 : z} 11 {c2 : z} 12 {c3 : z} +} { + do_auto_test 4.$tn yy $expr +} + + + +finish_test + diff --git a/ext/fts5/test/fts5aux.test b/ext/fts5/test/fts5aux.test new file mode 100644 index 0000000..995fe85 --- /dev/null +++ b/ext/fts5/test/fts5aux.test @@ -0,0 +1,250 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on the auxiliary function APIs. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5aux + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc inst {cmd i} { + $cmd xInst $i +} +sqlite3_fts5_create_function db inst inst + +proc colsize {cmd i} { + $cmd xColumnSize $i +} +sqlite3_fts5_create_function db colsize colsize + +proc totalsize {cmd i} { + $cmd xColumnTotalSize $i +} +sqlite3_fts5_create_function db totalsize totalsize + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE f1 USING fts5(a, b); + INSERT INTO f1 VALUES('one two', 'two one zero'); + INSERT INTO f1 VALUES('one one', 'one one one'); +} + +do_catchsql_test 1.1 { + SELECT inst(f1, -1) FROM f1 WHERE f1 MATCH 'two'; +} {1 SQLITE_RANGE} +do_catchsql_test 1.2 { + SELECT inst(f1, 0) FROM f1 WHERE f1 MATCH 'two'; +} {0 {{0 0 1}}} +do_catchsql_test 1.3 { + SELECT inst(f1, 1) FROM f1 WHERE f1 MATCH 'two'; +} {0 {{0 1 0}}} +do_catchsql_test 1.4 { + SELECT inst(f1, 2) FROM f1 WHERE f1 MATCH 'two'; +} {1 SQLITE_RANGE} + +do_catchsql_test 2.1 { + SELECT colsize(f1, 2) FROM f1 WHERE f1 MATCH 'two'; +} {1 SQLITE_RANGE} +do_execsql_test 2.2 { + SELECT colsize(f1, 0), colsize(f1, 1) FROM f1 WHERE f1 MATCH 'zero'; +} {2 3} +do_execsql_test 2.3 { + SELECT colsize(f1, -1) FROM f1 WHERE f1 MATCH 'zero'; +} {5} + +do_execsql_test 2.4.1 { + SELECT totalsize(f1, -1) FROM f1 WHERE f1 MATCH 'zero'; +} {10} +do_execsql_test 2.4.2 { + SELECT totalsize(f1, 0) FROM f1 WHERE f1 MATCH 'zero'; +} {4} +do_execsql_test 2.4.3 { + SELECT totalsize(f1, 1) FROM f1 WHERE f1 MATCH 'zero'; +} {6} +do_catchsql_test 2.4.4 { + SELECT totalsize(f1, 2) FROM f1 WHERE f1 MATCH 'zero'; +} {1 SQLITE_RANGE} + +#------------------------------------------------------------------------- +# Test the xSet and xGetAuxdata APIs with a NULL destructor. +# +proc prevrowid {add cmd} { + set res [$cmd xGetAuxdataInt 0] + set r [$cmd xRowid] + $cmd xSetAuxdataInt $r + return [expr $res + $add] +} +sqlite3_fts5_create_function db prevrowid [list prevrowid 0] +sqlite3_fts5_create_function db prevrowid1 [list prevrowid 1] + +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE e5 USING fts5(x); + INSERT INTO e5 VALUES('a b c'); + INSERT INTO e5 VALUES('d e f'); + INSERT INTO e5 VALUES('a b c'); + INSERT INTO e5 VALUES('d e f'); + INSERT INTO e5 VALUES('a b c'); +} + +do_execsql_test 3.1 { + SELECT prevrowid(e5) || '+' || rowid FROM e5 WHERE e5 MATCH 'c' +} {0+1 1+3 3+5} + +do_execsql_test 3.2 { + SELECT prevrowid(e5) || '+' || prevrowid1(e5) || '+' || rowid + FROM e5 WHERE e5 MATCH 'e' +} {0+1+2 2+3+4} + +#------------------------------------------------------------------------- +# Test that if the xQueryPhrase callback returns other than SQLITE_OK, +# the query is abandoned. And that if it returns an error code other than +# SQLITE_DONE, the error is propagated back to the caller. +# +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE e7 USING fts5(x); + INSERT INTO e7 VALUES('a x a'); + INSERT INTO e7 VALUES('b x b'); + INSERT INTO e7 VALUES('c x c'); + INSERT INTO e7 VALUES('d x d'); + INSERT INTO e7 VALUES('e x e'); +} + +proc xCallback {rowid code cmd} { + set r [$cmd xRowid] + lappend ::cb $r + if {$r==$rowid} { return $code } + return "" +} + +proc phrasequery {cmd code} { + set ::cb [list] + $cmd xQueryPhrase 1 [list xCallback [$cmd xRowid] $code] + set ::cb +} + +sqlite3_fts5_create_function db phrasequery phrasequery + +do_execsql_test 4.1 { + SELECT phrasequery(e7, 'SQLITE_OK') FROM e7 WHERE e7 MATCH 'c x' +} {{1 2 3 4 5}} + +do_execsql_test 4.2 { + SELECT phrasequery(e7, 'SQLITE_DONE') FROM e7 WHERE e7 MATCH 'c x' +} {{1 2 3}} + +do_catchsql_test 4.3 { + SELECT phrasequery(e7, 'SQLITE_ERROR') FROM e7 WHERE e7 MATCH 'c x' +} {1 SQLITE_ERROR} + +#------------------------------------------------------------------------- +# Auxiliary function calls with many cursors in the global cursor list. +# +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE e9 USING fts5(y); + INSERT INTO e9(rowid, y) VALUES(1, 'i iii'); + INSERT INTO e9(rowid, y) VALUES(2, 'ii iv'); + INSERT INTO e9(rowid, y) VALUES(3, 'ii'); + INSERT INTO e9(rowid, y) VALUES(4, 'i iv'); + INSERT INTO e9(rowid, y) VALUES(5, 'iii'); +} + +proc my_rowid {cmd} { $cmd xRowid } +sqlite3_fts5_create_function db my_rowid my_rowid + +foreach {var q} { + s1 i + s2 ii + s3 iii + s4 iv +} { + set sql "SELECT my_rowid(e9) FROM e9 WHERE e9 MATCH '$q'" + set $var [sqlite3_prepare db $sql -1 dummy] +} + +do_test 5.1.1 { sqlite3_step $s1 ; sqlite3_column_int $s1 0 } 1 +do_test 5.1.2 { sqlite3_step $s2 ; sqlite3_column_int $s2 0 } 2 +do_test 5.1.3 { sqlite3_step $s3 ; sqlite3_column_int $s3 0 } 1 +do_test 5.1.4 { sqlite3_step $s4 ; sqlite3_column_int $s4 0 } 2 + +do_test 5.2.1 { sqlite3_step $s1 ; sqlite3_column_int $s1 0 } 4 +do_test 5.2.2 { sqlite3_step $s2 ; sqlite3_column_int $s2 0 } 3 +do_test 5.2.3 { sqlite3_step $s3 ; sqlite3_column_int $s3 0 } 5 +do_test 5.2.4 { sqlite3_step $s4 ; sqlite3_column_int $s4 0 } 4 + +sqlite3_finalize $s1 +sqlite3_finalize $s2 +sqlite3_finalize $s3 +sqlite3_finalize $s4 + +#------------------------------------------------------------------------- +# Passing an invalid first argument to an auxiliary function is detected. +# +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE e11 USING fts5(y, z); + INSERT INTO e11(rowid, y, z) VALUES(1, 'a b', 45); + INSERT INTO e11(rowid, y, z) VALUES(2, 'b c', 46); +} + +do_catchsql_test 6.1 { + SELECT my_rowid(z) FROM e11 WHERE e11 MATCH 'b' +} {1 {no such cursor: 45}} + +do_catchsql_test 6.2 { + SELECT my_rowid(y) FROM e11 WHERE e11 MATCH 'b' +} {1 {no such cursor: 0}} + +#------------------------------------------------------------------------- +# Test passing an out-of-range phrase number to xPhraseSize (should +# return 0). +# +proc my_phrasesize {cmd iPhrase} { $cmd xPhraseSize $iPhrase } +sqlite3_fts5_create_function db my_phrasesize my_phrasesize + +do_execsql_test 7.1 { + CREATE VIRTUAL TABLE t1 USING fts5(a); + INSERT INTO t1 VALUES('a b c'); +} +do_execsql_test 7.2 { + SELECT + my_phrasesize(t1, -1), + my_phrasesize(t1, 0), + my_phrasesize(t1, 1), + my_phrasesize(t1, 2) + FROM t1 WHERE t1 MATCH 'a OR b+c' +} {0 1 2 0} + +#------------------------------------------------------------------------- +# +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE x1 USING fts5(a); +} + +foreach {tn lRow res} { + 4 {"a a a" "b" "a d"} {"[a] [a] [a]" "[a] d"} + 1 {"b d" "a b"} {"[b] [d]" "[a] b"} + 2 {"d b" "a d"} {"[d] [b]" "[a] d"} + 3 {"a a d"} {"[a] [a] d"} +} { + execsql { DELETE FROM x1 } + foreach row $lRow { execsql { INSERT INTO x1 VALUES($row) } } + breakpoint + do_execsql_test 8.$tn { + SELECT highlight(x1, 0, '[', ']') FROM x1 WHERE x1 MATCH 'a OR (b AND d)'; + } $res +} + +finish_test + diff --git a/ext/fts5/test/fts5auxdata.test b/ext/fts5/test/fts5auxdata.test new file mode 100644 index 0000000..dbbb1db --- /dev/null +++ b/ext/fts5/test/fts5auxdata.test @@ -0,0 +1,115 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on the fts5 xSetAuxdata() and xGetAuxdata() APIs. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5auxdata + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE f1 USING fts5(a, b); + INSERT INTO f1(rowid, a, b) VALUES(1, 'a', 'b1'); + INSERT INTO f1(rowid, a, b) VALUES(2, 'a', 'b2'); + INSERT INTO f1(rowid, a, b) VALUES(3, 'a', 'b3'); + INSERT INTO f1(rowid, a, b) VALUES(4, 'a', 'b4'); + INSERT INTO f1(rowid, a, b) VALUES(5, 'a', 'b5'); +} + +proc aux_function_1 {cmd tn} { + switch [$cmd xRowid] { + 1 { + do_test $tn.1 [list $cmd xGetAuxdata 0 ] {} + $cmd xSetAuxdata "one" + } + + 2 { + do_test $tn.2 [list $cmd xGetAuxdata 0 ] {one} + $cmd xSetAuxdata "two" + } + + 3 { + do_test $tn.3 [list $cmd xGetAuxdata 0 ] {two} + } + + 4 { + do_test $tn.4 [list $cmd xGetAuxdata 1 ] {two} + } + + 5 { + do_test $tn.5 [list $cmd xGetAuxdata 0 ] {} + } + } +} + +sqlite3_fts5_create_function db aux_function_1 aux_function_1 +db eval { + SELECT aux_function_1(f1, 1) FROM f1 WHERE f1 MATCH 'a' + ORDER BY rowid ASC +} + +proc aux_function_2 {cmd tn inst} { + if {$inst == "A"} { + switch [$cmd xRowid] { + 1 { + do_test $tn.1.$inst [list $cmd xGetAuxdata 0 ] {} + $cmd xSetAuxdata "one $inst" + } + 2 { + do_test $tn.2.$inst [list $cmd xGetAuxdata 0 ] "one $inst" + $cmd xSetAuxdata "two $inst" + } + 3 { + do_test $tn.3.$inst [list $cmd xGetAuxdata 0 ] "two $inst" + } + 4 { + do_test $tn.4.$inst [list $cmd xGetAuxdata 1 ] "two $inst" + } + 5 { + do_test $tn.5.$inst [list $cmd xGetAuxdata 0 ] {} + } + } + } else { + switch [$cmd xRowid] { + 1 { + do_test $tn.1.$inst [list $cmd xGetAuxdata 0 ] "one A" + } + 2 { + do_test $tn.2.$inst [list $cmd xGetAuxdata 0 ] "two A" + } + 3 { + do_test $tn.3.$inst [list $cmd xGetAuxdata 0 ] "two A" + } + 4 { + do_test $tn.4.$inst [list $cmd xGetAuxdata 0 ] {} + } + 5 { + do_test $tn.5.$inst [list $cmd xGetAuxdata 0 ] {} + } + } + } +} + +sqlite3_fts5_create_function db aux_function_2 aux_function_2 +db eval { + SELECT aux_function_2(f1, 2, 'A'), aux_function_2(f1, 2, 'B') + FROM f1 WHERE f1 MATCH 'a' + ORDER BY rowid ASC +} + +finish_test + diff --git a/ext/fts5/test/fts5bigpl.test b/ext/fts5/test/fts5bigpl.test new file mode 100644 index 0000000..85f7460 --- /dev/null +++ b/ext/fts5/test/fts5bigpl.test @@ -0,0 +1,64 @@ +# 2015 April 21 +# +# 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 fts5bigpl + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +if { $tcl_platform(wordSize)<8 } { + finish_test + return +} + +do_execsql_test 1.0 { CREATE VIRTUAL TABLE t1 USING fts5(x) } + +do_test 1.1 { + foreach t {a b c d e f g h i j} { + set doc [string repeat "$t " 1200000] + execsql { INSERT INTO t1 VALUES($doc) } + } + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } +} {} + +do_test 1.2 { + execsql { DELETE FROM t1 } + foreach t {"a b" "b a" "c d" "d c"} { + set doc [string repeat "$t " 600000] + execsql { INSERT INTO t1 VALUES($doc) } + } + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } +} {} + + +# 5-byte varint. This test takes 30 seconds or so on a 2014 workstation. +# The generated database is roughly 635MiB. +# +do_test 2.1...slow { + execsql { DELETE FROM t1 } + foreach t {a} { + set doc [string repeat "$t " 150000000] + execsql { INSERT INTO t1 VALUES($doc) } + } + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } +} {} + +finish_test + diff --git a/ext/fts5/test/fts5bigtok.test b/ext/fts5/test/fts5bigtok.test new file mode 100644 index 0000000..2267be5 --- /dev/null +++ b/ext/fts5/test/fts5bigtok.test @@ -0,0 +1,67 @@ +# 2016 Jan 19 +# +# 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 fts5bigtok + +proc rndterm {} { + set L [list a b c d e f g h i j k l m n o p q r s t u v w x y z] + set l [lindex $L [expr int(rand() * [llength $L])]] + string repeat $l [expr int(rand() * 5) + 60] +} + +proc rnddoc {n} { + set res [list] + for {set i 0} {$i < $n} {incr i} { + lappend res [rndterm] + } + set res +} + +foreach_detail_mode $::testprefix { + db func rnddoc rnddoc + do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + CREATE VIRTUAL TABLE t1vocab USING fts5vocab(t1, row); + + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10 ) + INSERT INTO t1 SELECT rnddoc(3) FROM s; + + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10 ) + INSERT INTO t1 SELECT rnddoc(3) FROM s; + } + + foreach v [db eval {SELECT term FROM t1vocab}] { + set res [db eval {SELECT rowid FROM t1($v)}] + do_execsql_test 1.[string range $v 0 0] { + SELECT rowid FROM t1($v) ORDER BY rowid DESC + } [lsort -integer -decr $res] + } + + do_execsql_test 2.0 { + INSERT INTO t1(t1) VALUES('optimize'); + } + + foreach v [db eval {SELECT term FROM t1vocab}] { + set res [db eval {SELECT rowid FROM t1($v)}] + do_execsql_test 2.[string range $v 0 0] { + SELECT rowid FROM t1($v) ORDER BY rowid DESC + } [lsort -integer -decr $res] + } +} + +finish_test + + diff --git a/ext/fts5/test/fts5columnsize.test b/ext/fts5/test/fts5columnsize.test new file mode 100644 index 0000000..dec9b58 --- /dev/null +++ b/ext/fts5/test/fts5columnsize.test @@ -0,0 +1,151 @@ +# 2015 Jun 10 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on fts5 tables with the columnsize=0 option. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5columnsize + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# Check that the option can be parsed and that the %_docsize table is +# only created if it is set to true. +# +foreach {tn outcome stmt} { + 1 0 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=0) } + 2 1 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=1) } + 3 0 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize='0') } + 4 1 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize='1') } + 5 2 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize='') } + 6 2 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=2) } + 7 1 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=0, columnsize=1) } + 8 1 { CREATE VIRTUAL TABLE t1 USING fts5(x) } + 9 2 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=11) } +} { + execsql { + DROP TABLE IF EXISTS t1; + } + if {$outcome==2} { + do_catchsql_test 1.$tn.1 $stmt {1 {malformed columnsize=... directive}} + } else { + do_execsql_test 1.$tn.2 $stmt + do_execsql_test 1.$tn.3 { + SELECT count(*) FROM sqlite_master WHERE name = 't1_docsize' + } $outcome + } +} + +#------------------------------------------------------------------------- +# Run tests on a table with no %_content or %_docsize backing store. +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t2 USING fts5(x, columnsize=0, content=''); +} +do_catchsql_test 2.1 { + INSERT INTO t2 VALUES('a b c d e f'); +} {1 {datatype mismatch}} +do_execsql_test 2.2 { + INSERT INTO t2(rowid, x) VALUES(1, 'c d e f'); + INSERT INTO t2(rowid, x) VALUES(2, 'c d e f g h'); + INSERT INTO t2(rowid, x) VALUES(3, 'a b c d e f g h'); +} {} +do_execsql_test 2.3 { + SELECT rowid FROM t2 WHERE t2 MATCH 'b'; SELECT '::'; + SELECT rowid FROM t2 WHERE t2 MATCH 'e'; SELECT '::'; + SELECT rowid FROM t2 WHERE t2 MATCH 'h'; +} {3 :: 1 2 3 :: 2 3} +do_execsql_test 2.4 { + INSERT INTO t2(t2, rowid, x) VALUES('delete', 2, 'c d e f g h'); + SELECT rowid FROM t2 WHERE t2 MATCH 'b'; SELECT '::'; + SELECT rowid FROM t2 WHERE t2 MATCH 'e'; SELECT '::'; + SELECT rowid FROM t2 WHERE t2 MATCH 'h'; +} {3 :: 1 3 :: 3} +do_execsql_test 2.5 { + INSERT INTO t2(t2) VALUES('delete-all'); + SELECT rowid FROM t2 WHERE t2 MATCH 'b'; SELECT '::'; + SELECT rowid FROM t2 WHERE t2 MATCH 'e'; SELECT '::'; + SELECT rowid FROM t2 WHERE t2 MATCH 'h'; +} {:: ::} +do_execsql_test 2.6 { + INSERT INTO t2(rowid, x) VALUES(1, 'o t t f'); + INSERT INTO t2(rowid, x) VALUES(2, 'f s s e'); + INSERT INTO t2(rowid, x) VALUES(3, 'n t e t'); +} + +do_catchsql_test 2.7.1 { + SELECT rowid FROM t2 +} {1 {t2: table does not support scanning}} +do_catchsql_test 2.7.2 { + SELECT rowid FROM t2 WHERE rowid=2 +} {1 {t2: table does not support scanning}} +do_catchsql_test 2.7.3 { + SELECT rowid FROM t2 WHERE rowid BETWEEN 1 AND 3 +} {1 {t2: table does not support scanning}} + +do_execsql_test 2.X { + DROP TABLE t2 +} + +#------------------------------------------------------------------------- +# Test the xColumnSize() API +# +fts5_aux_test_functions db + +do_execsql_test 3.1.0 { + CREATE VIRTUAL TABLE t3 USING fts5(x, y UNINDEXED, z, columnsize=0); + INSERT INTO t3 VALUES('a a', 'b b b', 'c'); + INSERT INTO t3 VALUES('x a x', 'b b b y', ''); +} +do_execsql_test 3.1.1 { + SELECT rowid, fts5_test_columnsize(t3) FROM t3 WHERE t3 MATCH 'a' +} { + 1 {2 0 1} 2 {3 0 0} +} +do_execsql_test 3.1.2 { + INSERT INTO t3 VALUES(NULL, NULL, 'a a a a'); + DELETE FROM t3 WHERE rowid = 1; + SELECT rowid, fts5_test_columnsize(t3) FROM t3 WHERE t3 MATCH 'a' +} { + 2 {3 0 0} 3 {0 0 4} +} + +do_execsql_test 3.2.0 { + CREATE VIRTUAL TABLE t4 USING fts5(x, y UNINDEXED, z, columnsize=0, content=''); + INSERT INTO t4(rowid, x, y, z) VALUES(1, 'a a', 'b b b', 'c'); + INSERT INTO t4(rowid, x, y, z) VALUES(2, 'x a x', 'b b b y', ''); +} +do_execsql_test 3.2.1 { + SELECT rowid, fts5_test_columnsize(t4) FROM t4 WHERE t4 MATCH 'a' +} { + 1 {-1 0 -1} 2 {-1 0 -1} +} + +#------------------------------------------------------------------------- +# Test the integrity-check +# +do_execsql_test 4.1.1 { + CREATE VIRTUAL TABLE t5 USING fts5(x, columnsize=0); + INSERT INTO t5 VALUES('1 2 3 4'); + INSERT INTO t5 VALUES('2 4 6 8'); +} + +breakpoint +do_execsql_test 4.1.2 { + INSERT INTO t5(t5) VALUES('integrity-check'); +} + +finish_test diff --git a/ext/fts5/test/fts5config.test b/ext/fts5/test/fts5config.test new file mode 100644 index 0000000..c30a597 --- /dev/null +++ b/ext/fts5/test/fts5config.test @@ -0,0 +1,251 @@ +# 2015 Jan 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 file focuses on the code in fts5_config.c, which is largely concerned +# with parsing the various configuration and CREATE TABLE options. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5config + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# Try different types of quote characters. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5('a', "b", [c], `d`); + PRAGMA table_info = t1; +} { + 0 a {} 0 {} 0 + 1 b {} 0 {} 0 + 2 c {} 0 {} 0 + 3 d {} 0 {} 0 +} + +#------------------------------------------------------------------------- +# Syntax errors in the prefix= option. +# +foreach {tn opt} { + 1 {prefix=x} + 2 {prefix='x'} + 3 {prefix='$'} + 4 {prefix='1,2,'} + 5 {prefix=',1'} + 6 {prefix='1,2,3...'} + 7 {prefix='1,2,3xyz'} +} { + set res [list 1 {malformed prefix=... directive}] + do_catchsql_test 2.$tn "CREATE VIRTUAL TABLE f1 USING fts5(x, $opt)" $res +} + +#------------------------------------------------------------------------- +# Syntax errors in the 'rank' option. +# +foreach {tn val} { + 1 "f1(xyz)" + 2 "f1(zyx)" + 3 "f1(nzz)" + 4 "f1(x'!!')" + 5 "f1(x':;')" + 6 "f1(x'[]')" + 7 "f1(x'{}')" + 8 "f1('abc)" +} { + do_catchsql_test 3.$tn { + INSERT INTO t1(t1, rank) VALUES('rank', $val); + } {1 {SQL logic error or missing database}} +} + +#------------------------------------------------------------------------- +# The parsing of SQL literals specified as part of 'rank' options. +# +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE zzz USING fts5(one); + INSERT INTO zzz VALUES('a b c'); +} +proc first {cmd A} { return $A } +sqlite3_fts5_create_function db first first + +foreach {tn arg} { + 1 "123" + 2 "'01234567890ABCDEF'" + 3 "x'0123'" + 4 "x'ABCD'" + 5 "x'0123456789ABCDEF'" + 6 "x'0123456789abcdef'" + 7 "22.5" + 8 "-91.5" + 9 "-.5" + 10 "''''" + 11 "+.5" +} { + set func [string map {' ''} "first($arg)"] + do_execsql_test 4.1.$tn " + INSERT INTO zzz(zzz, rank) VALUES('rank', '$func'); + SELECT rank IS $arg FROM zzz WHERE zzz MATCH 'a + b + c' + " 1 +} + +do_execsql_test 4.2 { + INSERT INTO zzz(zzz, rank) VALUES('rank', 'f1()'); +} {} + +#------------------------------------------------------------------------- +# Misquoting in tokenize= and other options. +# +do_catchsql_test 5.1 { + CREATE VIRTUAL TABLE xx USING fts5(x, tokenize="porter 'ascii"); +} {1 {parse error in tokenize directive}} + +breakpoint +do_catchsql_test 5.2 { + CREATE VIRTUAL TABLE xx USING fts5(x, [y[]); +} {0 {}} + +do_catchsql_test 5.3 { + CREATE VIRTUAL TABLE yy USING fts5(x, [y]]); +} {1 {unrecognized token: "]"}} + +#------------------------------------------------------------------------- +# Errors in prefix= directives. +# +do_catchsql_test 6.2 { + CREATE VIRTUAL TABLE abc USING fts5(a, prefix='1, 2, 1001'); +} {1 {prefix length out of range (max 999)}} +do_catchsql_test 6.3 { + CREATE VIRTUAL TAbLE abc USING fts5(a, prefix='1, 2, 0000'); +} {1 {prefix length out of range (max 999)}} +do_catchsql_test 6.4 { + CREATE VIRTUAL TABLE abc USING fts5(a, prefix='1 , 1000000'); +} {1 {prefix length out of range (max 999)}} + +#------------------------------------------------------------------------- +# Duplicate tokenize= and other options. +# +do_catchsql_test 7.1 { + CREATE VIRTUAL TABLE abc USING fts5(a, tokenize=porter, tokenize=ascii); +} {1 {multiple tokenize=... directives}} +do_catchsql_test 7.2 { + CREATE VIRTUAL TABLE abc USING fts5(a, content=porter, content=ascii); +} {1 {multiple content=... directives}} +do_catchsql_test 7.3 { + CREATE VIRTUAL TABLE abc USING fts5(a, content_rowid=porter, content_rowid=a); +} {1 {multiple content_rowid=... directives}} + +#------------------------------------------------------------------------- +# Unrecognized option. +# +do_catchsql_test 8.0 { + CREATE VIRTUAL TABLE abc USING fts5(a, nosuchoption=123); +} {1 {unrecognized option: "nosuchoption"}} +do_catchsql_test 8.1 { + CREATE VIRTUAL TABLE abc USING fts5(a, "nosuchoption"=123); +} {1 {parse error in ""nosuchoption"=123"}} + +#------------------------------------------------------------------------- +# Errors in: +# +# 9.1.* 'pgsz' options. +# 9.2.* 'automerge' options. +# 9.3.* 'crisismerge' options. +# 9.4.* a non-existant option. +# 9.5.* 'hashsize' options. +# +do_execsql_test 9.0 { + CREATE VIRTUAL TABLE abc USING fts5(a, b); +} {} +do_catchsql_test 9.1.1 { + INSERT INTO abc(abc, rank) VALUES('pgsz', -5); +} {1 {SQL logic error or missing database}} +do_catchsql_test 9.1.2 { + INSERT INTO abc(abc, rank) VALUES('pgsz', 50000000); +} {1 {SQL logic error or missing database}} +do_catchsql_test 9.1.3 { + INSERT INTO abc(abc, rank) VALUES('pgsz', 66.67); +} {1 {SQL logic error or missing database}} + +do_catchsql_test 9.2.1 { + INSERT INTO abc(abc, rank) VALUES('automerge', -5); +} {1 {SQL logic error or missing database}} +do_catchsql_test 9.2.2 { + INSERT INTO abc(abc, rank) VALUES('automerge', 50000000); +} {1 {SQL logic error or missing database}} +do_catchsql_test 9.2.3 { + INSERT INTO abc(abc, rank) VALUES('automerge', 66.67); +} {1 {SQL logic error or missing database}} +do_execsql_test 9.2.4 { + INSERT INTO abc(abc, rank) VALUES('automerge', 1); +} {} + +do_catchsql_test 9.3.1 { + INSERT INTO abc(abc, rank) VALUES('crisismerge', -5); +} {1 {SQL logic error or missing database}} +do_catchsql_test 9.3.2 { + INSERT INTO abc(abc, rank) VALUES('crisismerge', 66.67); +} {1 {SQL logic error or missing database}} +do_execsql_test 9.3.3 { + INSERT INTO abc(abc, rank) VALUES('crisismerge', 1); +} {} +do_execsql_test 9.3.4 { + INSERT INTO abc(abc, rank) VALUES('crisismerge', 50000000); +} {} + +do_catchsql_test 9.4.1 { + INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1); +} {1 {SQL logic error or missing database}} + +do_catchsql_test 9.5.1 { + INSERT INTO abc(abc, rank) VALUES('hashsize', 'not an integer'); +} {1 {SQL logic error or missing database}} +do_catchsql_test 9.5.2 { + INSERT INTO abc(abc, rank) VALUES('hashsize', -500000); +} {1 {SQL logic error or missing database}} +do_catchsql_test 9.5.3 { + INSERT INTO abc(abc, rank) VALUES('hashsize', 500000); +} {0 {}} + +#------------------------------------------------------------------------- +# Too many prefix indexes. Maximum allowed is 31. +# +foreach {tn spec} { + 1 {prefix="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32"} + 2 {prefix="1 2 3 4", prefix="5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32"} +} { + set sql "CREATE VIRTUAL TABLE xyz USING fts5(x, $spec)" + do_catchsql_test 10.$tn $sql {1 {too many prefix indexes (max 31)}} +} + +#------------------------------------------------------------------------- +# errors in the detail= option. +# +foreach {tn opt} { + 1 {detail=x} + 2 {detail='x'} + 3 {detail='$'} + 4 {detail='1,2,'} + 5 {detail=',1'} + 6 {detail=''} +} { + set res [list 1 {malformed detail=... directive}] + do_catchsql_test 11.$tn "CREATE VIRTUAL TABLE f1 USING fts5(x, $opt)" $res +} + +do_catchsql_test 12.1 { + INSERT INTO t1(t1, rank) VALUES('rank', NULL);; +} {1 {SQL logic error or missing database}} + +finish_test + diff --git a/ext/fts5/test/fts5conflict.test b/ext/fts5/test/fts5conflict.test new file mode 100644 index 0000000..5c1e593 --- /dev/null +++ b/ext/fts5/test/fts5conflict.test @@ -0,0 +1,70 @@ +# 2015 October 27 +# +# 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 fts5conflict + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(x INTEGER PRIMARY KEY, a, b); + CREATE VIRTUAL TABLE ft USING fts5(a, b, content=t1, content_rowid=x); +} + +do_execsql_test 1.1 { + REPLACE INTO ft(rowid, a, b) VALUES(1, 'a b c', 'a b c'); + REPLACE INTO t1 VALUES(1, 'a b c', 'a b c'); +} + +do_execsql_test 1.2 { + INSERT INTO ft(ft) VALUES('integrity-check'); +} + +do_execsql_test 2.0 { + CREATE TABLE tbl(a INTEGER PRIMARY KEY, b, c); + CREATE VIRTUAL TABLE fts_idx USING fts5(b, c, content=tbl, content_rowid=a); + CREATE TRIGGER tbl_ai AFTER INSERT ON tbl BEGIN + INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c); + END; + CREATE TRIGGER tbl_ad AFTER DELETE ON tbl BEGIN + INSERT INTO fts_idx(fts_idx, rowid, b, c) + VALUES('delete', old.a, old.b, old.c); + END; + CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN + INSERT INTO fts_idx(fts_idx, rowid, b, c) + VALUES('delete', old.a, old.b, old.c); + INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c); + END; +} + +do_execsql_test 2.1 { + PRAGMA recursive_triggers = 1; + INSERT INTO tbl VALUES(1, 'x y z', '1 2 3'); + INSERT INTO tbl VALUES(10, 'x y z', '1 2 3'); + INSERT INTO tbl VALUES(100, 'x 1 z', '1 y 3'); + + UPDATE tbl SET b = '1 2 x' WHERE rowid=10; + REPLACE INTO tbl VALUES(1, '4 5 6', '3 2 1'); + DELETE FROM tbl WHERE a=100; + + INSERT INTO fts_idx(fts_idx) VALUES('integrity-check'); +} + +finish_test + + diff --git a/ext/fts5/test/fts5content.test b/ext/fts5/test/fts5content.test new file mode 100644 index 0000000..69e66a5 --- /dev/null +++ b/ext/fts5/test/fts5content.test @@ -0,0 +1,258 @@ +# 2014 Dec 20 +# +# 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 contains tests for the content= and content_rowid= options. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5content + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# Contentless tables +# +do_execsql_test 1.1 { + CREATE VIRTUAL TABLE f1 USING fts5(a, b, content=''); + INSERT INTO f1(rowid, a, b) VALUES(1, 'one', 'o n e'); + INSERT INTO f1(rowid, a, b) VALUES(2, 'two', 't w o'); + INSERT INTO f1(rowid, a, b) VALUES(3, 'three', 't h r e e'); +} + +do_execsql_test 1.2 { + SELECT rowid FROM f1 WHERE f1 MATCH 'o'; +} {1 2} + +do_execsql_test 1.3 { + INSERT INTO f1(a, b) VALUES('four', 'f o u r'); + SELECT rowid FROM f1 WHERE f1 MATCH 'o'; +} {1 2 4} + +do_execsql_test 1.4 { + SELECT rowid, a, b FROM f1 WHERE f1 MATCH 'o'; +} {1 {} {} 2 {} {} 4 {} {}} + +do_execsql_test 1.5 { + SELECT rowid, highlight(f1, 0, '[', ']') FROM f1 WHERE f1 MATCH 'o'; +} {1 {} 2 {} 4 {}} + +do_execsql_test 1.6 { + SELECT rowid, highlight(f1, 0, '[', ']') IS NULL FROM f1 WHERE f1 MATCH 'o'; +} {1 1 2 1 4 1} + +do_execsql_test 1.7 { + SELECT rowid, snippet(f1, -1, '[', ']', '...', 5) IS NULL + FROM f1 WHERE f1 MATCH 'o'; +} {1 1 2 1 4 1} + +do_execsql_test 1.8 { + SELECT rowid, snippet(f1, 1, '[', ']', '...', 5) IS NULL + FROM f1 WHERE f1 MATCH 'o'; +} {1 1 2 1 4 1} + +do_execsql_test 1.9 { + SELECT rowid FROM f1; +} {1 2 3 4} + +do_execsql_test 1.10 { + SELECT * FROM f1; +} {{} {} {} {} {} {} {} {}} + +do_execsql_test 1.11 { + SELECT rowid, a, b FROM f1 ORDER BY rowid ASC; +} {1 {} {} 2 {} {} 3 {} {} 4 {} {}} + +do_execsql_test 1.12 { + SELECT a IS NULL FROM f1; +} {1 1 1 1} + +do_catchsql_test 1.13 { + DELETE FROM f1 WHERE rowid = 2; +} {1 {cannot DELETE from contentless fts5 table: f1}} + +do_catchsql_test 1.14 { + UPDATE f1 SET a = 'a b c' WHERE rowid = 2; +} {1 {cannot UPDATE contentless fts5 table: f1}} + +do_execsql_test 1.15 { + INSERT INTO f1(f1, rowid, a, b) VALUES('delete', 2, 'two', 't w o'); +} {} + +do_execsql_test 1.16 { + SELECT rowid FROM f1 WHERE f1 MATCH 'o'; +} {1 4} + +do_execsql_test 1.17 { + SELECT rowid FROM f1; +} {1 3 4} + +#------------------------------------------------------------------------- +# External content tables +# +reset_db +do_execsql_test 2.1 { + -- Create a table. And an external content fts5 table to index it. + CREATE TABLE tbl(a INTEGER PRIMARY KEY, b, c); + CREATE VIRTUAL TABLE fts_idx USING fts5(b, c, content='tbl', content_rowid='a'); + + -- Triggers to keep the FTS index up to date. + CREATE TRIGGER tbl_ai AFTER INSERT ON tbl BEGIN + INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c); + END; + CREATE TRIGGER tbl_ad AFTER DELETE ON tbl BEGIN + INSERT INTO fts_idx(fts_idx, rowid, b, c) + VALUES('delete', old.a, old.b, old.c); + END; + CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN + INSERT INTO fts_idx(fts_idx, rowid, b, c) + VALUES('delete', old.a, old.b, old.c); + INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c); + END; +} + +do_execsql_test 2.2 { + INSERT INTO tbl VALUES(1, 'one', 'o n e'); + INSERT INTO tbl VALUES(NULL, 'two', 't w o'); + INSERT INTO tbl VALUES(3, 'three', 't h r e e'); +} + +do_execsql_test 2.3 { + INSERT INTO fts_idx(fts_idx) VALUES('integrity-check'); +} + +do_execsql_test 2.4 { + DELETE FROM tbl WHERE rowid=2; + INSERT INTO fts_idx(fts_idx) VALUES('integrity-check'); +} + +do_execsql_test 2.5 { + UPDATE tbl SET c = c || ' x y z'; + INSERT INTO fts_idx(fts_idx) VALUES('integrity-check'); +} + +do_execsql_test 2.6 { + SELECT * FROM fts_idx WHERE fts_idx MATCH 't AND x'; +} {three {t h r e e x y z}} + +do_execsql_test 2.7 { + SELECT highlight(fts_idx, 1, '[', ']') FROM fts_idx + WHERE fts_idx MATCH 't AND x'; +} {{[t] h r e e [x] y z}} + +#------------------------------------------------------------------------- +# Quick tests of the 'delete-all' command. +# +do_execsql_test 3.1 { + CREATE VIRTUAL TABLE t3 USING fts5(x, content=''); + INSERT INTO t3 VALUES('a b c'); + INSERT INTO t3 VALUES('d e f'); +} + +do_execsql_test 3.2 { + SELECT count(*) FROM t3_docsize; + SELECT count(*) FROM t3_data; +} {2 4} + +do_execsql_test 3.3 { + INSERT INTO t3(t3) VALUES('delete-all'); + SELECT count(*) FROM t3_docsize; + SELECT count(*) FROM t3_data; +} {0 2} + +do_execsql_test 3.4 { + INSERT INTO t3 VALUES('a b c'); + INSERT INTO t3 VALUES('d e f'); + SELECT rowid FROM t3 WHERE t3 MATCH 'e'; +} {2} + +do_execsql_test 3.5 { + SELECT rowid FROM t3 WHERE t3 MATCH 'c'; +} {1} + +do_execsql_test 3.6 { + SELECT count(*) FROM t3_docsize; + SELECT count(*) FROM t3_data; +} {2 4} + +do_execsql_test 3.7 { + CREATE VIRTUAL TABLE t4 USING fts5(x); +} {} +do_catchsql_test 3.8 { + INSERT INTO t4(t4) VALUES('delete-all'); +} {1 {'delete-all' may only be used with a contentless or external content fts5 table}} + +#------------------------------------------------------------------------- +# Test an external content table with a more interesting schema. +# +do_execsql_test 4.1 { + CREATE TABLE x2(a, "key col" PRIMARY KEY, b, c) WITHOUT ROWID; + INSERT INTO x2 VALUES('a b', 1, 'c d' , 'e f'); + INSERT INTO x2 VALUES('x y', -40, 'z z' , 'y x'); + + CREATE VIRTUAL TABLE t2 USING fts5(a, c, content=x2, content_rowid='key col'); + INSERT INTO t2(t2) VALUES('rebuild'); +} + +do_execsql_test 4.2 { SELECT rowid FROM t2 } {-40 1} +do_execsql_test 4.3 { SELECT rowid FROM t2 WHERE t2 MATCH 'c'} {} +do_execsql_test 4.4 { SELECT rowid FROM t2 WHERE t2 MATCH 'a'} {1} +do_execsql_test 4.5 { SELECT rowid FROM t2 WHERE t2 MATCH 'x'} {-40} + +do_execsql_test 4.6 { INSERT INTO t2(t2) VALUES('integrity-check') } {} + +do_execsql_test 4.7 { + DELETE FROM x2 WHERE "key col" = 1; + INSERT INTO t2(t2, rowid, a, c) VALUES('delete', 1, 'a b', 'e f'); + INSERT INTO t2(t2) VALUES('integrity-check'); +} + +do_execsql_test 4.8 { SELECT rowid FROM t2 WHERE t2 MATCH 'b'} {} +do_execsql_test 4.9 { SELECT rowid FROM t2 WHERE t2 MATCH 'y'} {-40} + +#------------------------------------------------------------------------- +# Test that if the 'rowid' field of a 'delete' is not an integer, no +# changes are made to the FTS index. +# +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE t5 USING fts5(a, b, content=); + INSERT INTO t5(rowid, a, b) VALUES(-1, 'one', 'two'); + INSERT INTO t5(rowid, a, b) VALUES( 0, 'three', 'four'); + INSERT INTO t5(rowid, a, b) VALUES( 1, 'five', 'six'); +} + +set ::checksum [execsql {SELECT md5sum(id, block) FROM t5_data}] + +do_execsql_test 5.1 { + INSERT INTO t5(t5, rowid, a, b) VALUES('delete', NULL, 'three', 'four'); + SELECT md5sum(id, block) FROM t5_data; +} $::checksum + + +#------------------------------------------------------------------------- +# Check that a contentless table can be dropped. +# +reset_db +do_execsql_test 6.1 { + CREATE VIRTUAL TABLE xx USING fts5(x, y, content=""); + SELECT name FROM sqlite_master; +} {xx xx_data xx_idx xx_docsize xx_config} +do_execsql_test 6.2 { + DROP TABLE xx; + SELECT name FROM sqlite_master; +} {} + + +finish_test + diff --git a/ext/fts5/test/fts5corrupt.test b/ext/fts5/test/fts5corrupt.test new file mode 100644 index 0000000..edaafb2 --- /dev/null +++ b/ext/fts5/test/fts5corrupt.test @@ -0,0 +1,99 @@ +# 2014 Dec 20 +# +# 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 tests that the FTS5 'integrity-check' command detects +# inconsistencies (corruption) in the on-disk backing tables. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5corrupt + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); +} + +do_test 1.1 { + db transaction { + for {set i 1} {$i < 200} {incr i} { + set doc [list [string repeat x $i] [string repeat y $i]] + execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) } + } + } + fts5_level_segs t1 +} {1} +db_save + +do_execsql_test 1.2 { INSERT INTO t1(t1) VALUES('integrity-check') } +set segid [lindex [fts5_level_segids t1] 0] + +do_test 1.3 { + execsql { + DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4); + } + catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } +} {1 {database disk image is malformed}} + +do_test 1.4 { + db_restore_and_reopen + execsql { + UPDATE t1_data set block = X'00000000' || substr(block, 5) WHERE + rowid = fts5_rowid('segment', $segid, 4); + } + catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } +} {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} + + +#-------------------------------------------------------------------- +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t2 USING fts5(x); + INSERT INTO t2(t2, rank) VALUES('pgsz', 64); +} +db func rnddoc fts5_rnddoc +do_test 2.1 { + for {set i 0} {$i < 500} {incr i} { + execsql { INSERT INTO t2 VALUES(rnddoc(50)) } + } + execsql { INSERT INTO t2(t2) VALUES('integrity-check') } +} {} + +#-------------------------------------------------------------------- +# A mundane test - missing row in the %_content table. +# +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t3 USING fts5(x); + INSERT INTO t3 VALUES('one o'); + INSERT INTO t3 VALUES('two e'); + INSERT INTO t3 VALUES('three o'); + INSERT INTO t3 VALUES('four e'); + INSERT INTO t3 VALUES('five o'); +} +do_execsql_test 3.1 { + SELECT * FROM t3 WHERE t3 MATCH 'o' +} {{one o} {three o} {five o}} + +do_catchsql_test 3.1 { + DELETE FROM t3_content WHERE rowid = 3; + SELECT * FROM t3 WHERE t3 MATCH 'o'; +} {1 {database disk image is malformed}} + +finish_test + diff --git a/ext/fts5/test/fts5corrupt2.test b/ext/fts5/test/fts5corrupt2.test new file mode 100644 index 0000000..3a4fcfa --- /dev/null +++ b/ext/fts5/test/fts5corrupt2.test @@ -0,0 +1,272 @@ +# 2015 Apr 24 +# +# 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 tests that FTS5 handles corrupt databases (i.e. internal +# inconsistencies in the backing tables) correctly. In this case +# "correctly" means without crashing. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5corrupt2 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} +sqlite3_fts5_may_be_corrupt 1 + +# Create a simple FTS5 table containing 100 documents. Each document +# contains 10 terms, each of which start with the character "x". +# +expr srand(0) +db func rnddoc fts5_rnddoc +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<100) + INSERT INTO t1 SELECT rnddoc(10) FROM ii; +} +set mask [expr 31 << 31] + +if 1 { + +# Test 1: +# +# For each page in the t1_data table, open a transaction and DELETE +# the t1_data entry. Then run: +# +# * an integrity-check, and +# * unless the deleted block was a b-tree node, a query for "t1 MATCH 'x*'" +# +# and check that the corruption is detected in both cases. The +# rollback the transaction. +# +# Test 2: +# +# Same thing, except instead of deleting a row from t1_data, replace its +# blob content with integer value 14. +# +foreach {tno stmt} { + 1 { DELETE FROM t1_data WHERE rowid=$rowid } + 2 { UPDATE t1_data SET block=14 WHERE rowid=$rowid } +} { + set tn 0 + foreach rowid [db eval {SELECT rowid FROM t1_data WHERE rowid>10}] { + incr tn + #if {$tn!=224} continue + + do_test 1.$tno.$tn.1.$rowid { + execsql { BEGIN } + execsql $stmt + catchsql { INSERT INTO t1(t1) VALUES('integrity-check') } + } {1 {database disk image is malformed}} + + if {($rowid & $mask)==0} { + # Node is a leaf node, not a b-tree node. + do_catchsql_test 1.$tno.$tn.2.$rowid { + SELECT rowid FROM t1 WHERE t1 MATCH 'x*' + } {1 {database disk image is malformed}} + } + + do_execsql_test 1.$tno.$tn.3.$rowid { + ROLLBACK; + INSERT INTO t1(t1) VALUES('integrity-check'); + } {} + } +} + +# Using the same database as the 1.* tests. +# +# Run N-1 tests, where N is the number of bytes in the rightmost leaf page +# of the fts index. For test $i, truncate the rightmost leafpage to $i +# bytes. Then test both the integrity-check detects the corruption. +# +# Also tested is that "MATCH 'x*'" does not crash and sometimes reports +# corruption. It may not report the db as corrupt because truncating the +# final leaf to some sizes may create a valid leaf page. +# +set lrowid [db one {SELECT max(rowid) FROM t1_data WHERE (rowid & $mask)=0}] +set nbyte [db one {SELECT length(block) FROM t1_data WHERE rowid=$lrowid}] +set all [db eval {SELECT rowid FROM t1}] +for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} { + do_execsql_test 2.$i.1 { + BEGIN; + UPDATE t1_data SET block = substr(block, 1, $i) WHERE rowid=$lrowid; + } + + do_catchsql_test 2.$i.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); + } {1 {database disk image is malformed}} + + do_test 2.$i.3 { + set res [catchsql {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'}] + expr { + $res=="1 {database disk image is malformed}" + || $res=="0 {$all}" + } + } 1 + + do_execsql_test 2.$i.4 { + ROLLBACK; + INSERT INTO t1(t1) VALUES('integrity-check'); + } {} +} + +#------------------------------------------------------------------------- +# Test that corruption in leaf page headers is detected by queries that use +# doclist-indexes. +# +set doc "A B C D E F G H I J " +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE x3 USING fts5(tt); + INSERT INTO x3(x3, rank) VALUES('pgsz', 32); + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<1000) + INSERT INTO x3 + SELECT ($doc || CASE WHEN (i%50)==0 THEN 'X' ELSE 'Y' END) FROM ii; +} + +foreach {tn hdr} { + 1 "\x00\x00\x00\x00" + 2 "\xFF\xFF\xFF\xFF" + 3 "\x44\x45" +} { + set tn2 0 + set nCorrupt 0 + set nCorrupt2 0 + foreach rowid [db eval {SELECT rowid FROM x3_data WHERE rowid>10}] { + if {$rowid & $mask} continue + incr tn2 + do_test 3.$tn.$tn2.1 { + execsql BEGIN + + set fd [db incrblob main x3_data block $rowid] + fconfigure $fd -encoding binary -translation binary + set existing [read $fd [string length $hdr]] + seek $fd 0 + puts -nonewline $fd $hdr + close $fd + + set res [catchsql {SELECT rowid FROM x3 WHERE x3 MATCH 'x AND a'}] + 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') } + } {1 {database disk image is malformed}} + } + + execsql ROLLBACK + } + + do_test 3.$tn.x { expr $nCorrupt>0 } 1 +} + +#-------------------------------------------------------------------- +# +set doc "A B C D E F G H I J " +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE x4 USING fts5(tt); + INSERT INTO x4(x4, rank) VALUES('pgsz', 32); + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10) + INSERT INTO x4 + SELECT ($doc || CASE WHEN (i%50)==0 THEN 'X' ELSE 'Y' END) FROM ii; +} + +foreach {tn nCut} { + 1 1 + 2 10 +} { + set tn2 0 + set nCorrupt 0 + foreach rowid [db eval {SELECT rowid FROM x4_data WHERE rowid>10}] { + if {$rowid & $mask} continue + incr tn2 + do_test 4.$tn.$tn2 { + execsql { + BEGIN; + UPDATE x4_data SET block = substr(block, 1, length(block)-$nCut) + WHERE id = $rowid; + } + + set res [catchsql { + SELECT rowid FROM x4 WHERE x4 MATCH 'a' ORDER BY 1 DESC + }] + if {$res == "1 {database disk image is malformed}"} {incr nCorrupt} + set {} 1 + } {1} + + execsql ROLLBACK + } + + # do_test 4.$tn.x { expr $nCorrupt>0 } 1 +} + +} + +set doc [string repeat "A B C " 1000] +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE x5 USING fts5(tt); + INSERT INTO x5(x5, rank) VALUES('pgsz', 32); + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10) + INSERT INTO x5 SELECT $doc FROM ii; +} + +foreach {tn hdr} { + 1 "\x00\x01" +} { + set tn2 0 + set nCorrupt 0 + foreach rowid [db eval {SELECT rowid FROM x5_data WHERE rowid>10}] { + if {$rowid & $mask} continue + incr tn2 + do_test 5.$tn.$tn2 { + execsql BEGIN + + set fd [db incrblob main x5_data block $rowid] + fconfigure $fd -encoding binary -translation binary + puts -nonewline $fd $hdr + close $fd + + catchsql { INSERT INTO x5(x5) VALUES('integrity-check') } + set {} {} + } {} + + execsql ROLLBACK + } +} + +#-------------------------------------------------------------------- +reset_db +do_execsql_test 6.1 { + CREATE VIRTUAL TABLE x5 USING fts5(tt); + INSERT INTO x5 VALUES('a'); + INSERT INTO x5 VALUES('a a'); + INSERT INTO x5 VALUES('a a a'); + INSERT INTO x5 VALUES('a a a a'); + + UPDATE x5_docsize SET sz = X'' WHERE id=3; +} +proc colsize {cmd i} { + $cmd xColumnSize $i +} +sqlite3_fts5_create_function db colsize colsize + +do_catchsql_test 6.2 { + SELECT colsize(x5, 0) FROM x5 WHERE x5 MATCH 'a' +} {1 SQLITE_CORRUPT_VTAB} + + +sqlite3_fts5_may_be_corrupt 0 +finish_test + diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test new file mode 100644 index 0000000..7a8cb5c --- /dev/null +++ b/ext/fts5/test/fts5corrupt3.test @@ -0,0 +1,408 @@ +# 2015 Apr 24 +# +# 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 tests that FTS5 handles corrupt databases (i.e. internal +# inconsistencies in the backing tables) correctly. In this case +# "correctly" means without crashing. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5corrupt3 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} +sqlite3_fts5_may_be_corrupt 1 + +proc create_t1 {} { + expr srand(0) + db func rnddoc fts5_rnddoc + db eval { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', 64); + WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<100) + INSERT INTO t1 SELECT rnddoc(10) FROM ii; + } +} + +if 1 { + +# Create a simple FTS5 table containing 100 documents. Each document +# contains 10 terms, each of which start with the character "x". +# +do_test 1.0 { create_t1 } {} + +do_test 1.1 { + # Pick out the rowid of the right-most b-tree leaf in the new segment. + set rowid [db one { + SELECT max(rowid) FROM t1_data WHERE ((rowid>>31) & 0x0F)==1 + }] + set L [db one {SELECT length(block) FROM t1_data WHERE rowid = $rowid}] + set {} {} +} {} + +for {set i 0} {$i < $L} {incr i} { + do_test 1.2.$i { + catchsql { + BEGIN; + UPDATE t1_data SET block = substr(block, 1, $i) WHERE id = $rowid; + INSERT INTO t1(t1) VALUES('integrity-check'); + } + } {1 {database disk image is malformed}} + catchsql ROLLBACK +} + +#------------------------------------------------------------------------- +# Test that trailing bytes appended to the averages record are ignored. +# +do_execsql_test 2.1 { + CREATE VIRTUAL TABLE t2 USING fts5(x); + INSERT INTO t2 VALUES(rnddoc(10)); + INSERT INTO t2 VALUES(rnddoc(10)); + SELECT length(block) FROM t2_data WHERE id=1; +} {2} +do_execsql_test 2.2 { + UPDATE t2_data SET block = block || 'abcd' WHERE id=1; + SELECT length(block) FROM t2_data WHERE id=1; +} {6} +do_execsql_test 2.2 { + INSERT INTO t2 VALUES(rnddoc(10)); + SELECT length(block) FROM t2_data WHERE id=1; +} {2} + + +#------------------------------------------------------------------------- +# Test that missing leaf pages are recognized as corruption. +# +reset_db +do_test 3.0 { create_t1 } {} + +do_execsql_test 3.1 { + SELECT count(*) FROM t1_data; +} {105} + +proc do_3_test {tn} { + set i 0 + foreach ::rowid [db eval "SELECT rowid FROM t1_data WHERE rowid>100"] { + incr i + do_test $tn.$i { + db eval BEGIN + db eval {DELETE FROM t1_data WHERE rowid = $::rowid} + list [ + catch { db eval {SELECT rowid FROM t1 WHERE t1 MATCH 'x*'} } msg + ] $msg + } {1 {database disk image is malformed}} + catch { db eval ROLLBACK } + } +} + +do_3_test 3.2 + +do_execsql_test 3.3 { + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + INSERT INTO t1 SELECT x FROM t1; + INSERT INTO t1(t1) VALUES('optimize'); +} {} + +do_3_test 3.4 + +do_test 3.5 { + execsql { + DELETE FROM t1; + INSERT INTO t1(t1, rank) VALUES('pgsz', 40); + } + for {set i 0} {$i < 1000} {incr i} { + set rnd [expr int(rand() * 1000)] + set doc [string repeat "x$rnd " [expr int(rand() * 3) + 1]] + execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) } + } +} {} + +do_3_test 3.6 + +do_test 3.7 { + execsql { + INSERT INTO t1(t1, rank) VALUES('pgsz', 40); + INSERT INTO t1 SELECT x FROM t1; + INSERT INTO t1(t1) VALUES('optimize'); + } +} {} + +do_3_test 3.8 + +do_test 3.9 { + execsql { + DELETE FROM t1; + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + } + for {set i 0} {$i < 100} {incr i} { + set rnd [expr int(rand() * 100)] + set doc "x[string repeat $rnd 20]" + execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) } + } +} {} + +do_3_test 3.10 + +#------------------------------------------------------------------------- +# Test that segments that end unexpectedly are identified as corruption. +# +reset_db +do_test 4.0 { + execsql { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + } + for {set i 0} {$i < 100} {incr i} { + set rnd [expr int(rand() * 100)] + set doc "x[string repeat $rnd 20]" + execsql { INSERT INTO t1(rowid, x) VALUES($i, $doc) } + } + execsql { INSERT INTO t1(t1) VALUES('optimize') } +} {} + +set nErr 0 +for {set i 1} {1} {incr i} { + set struct [db one {SELECT block FROM t1_data WHERE id=10}] + binary scan $struct c* var + set end [lindex $var end] + if {$end<=$i} break + lset var end [expr $end - $i] + set struct [binary format c* $var] + db eval { + BEGIN; + UPDATE t1_data SET block = $struct WHERE id=10; + } + do_test 4.1.$i { + incr nErr [catch { db eval { SELECT rowid FROM t1 WHERE t1 MATCH 'x*' } }] + set {} {} + } {} + catch { db eval ROLLBACK } +} +do_test 4.1.x { expr $nErr>45 } 1 + +#------------------------------------------------------------------------- +# + +# The first argument passed to this command must be a binary blob +# containing an FTS5 leaf page. This command returns a copy of this +# blob, with the pgidx of the leaf page replaced by a single varint +# containing value $iVal. +# +proc rewrite_pgidx {blob iVal} { + binary scan $blob SS off1 szLeaf + if {$iVal<0 || $iVal>=128} { + error "$iVal out of range!" + } else { + set pgidx [binary format c $iVal] + } + + binary format a${szLeaf}a* $blob $pgidx +} + +reset_db +do_execsql_test 5.1 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 40); + BEGIN; + INSERT INTO x1 VALUES('xaaa xabb xccc xcdd xeee xeff xggg xghh xiii xijj'); + INSERT INTO x1 SELECT x FROM x1; + INSERT INTO x1 SELECT x FROM x1; + INSERT INTO x1 SELECT x FROM x1; + INSERT INTO x1 SELECT x FROM x1; + INSERT INTO x1(x1) VALUES('optimize'); + COMMIT; +} + +#db eval { SELECT fts5_decode(id, block) b from x1_data } { puts $b } +# +db func rewrite_pgidx rewrite_pgidx +set i 0 +foreach rowid [db eval {SELECT rowid FROM x1_data WHERE rowid>100}] { + foreach val {2 100} { + do_test 5.2.$val.[incr i] { + catchsql { + BEGIN; + UPDATE x1_data SET block=rewrite_pgidx(block, $val) WHERE id=$rowid; + SELECT rowid FROM x1 WHERE x1 MATCH 'xa*'; + SELECT rowid FROM x1 WHERE x1 MATCH 'xb*'; + SELECT rowid FROM x1 WHERE x1 MATCH 'xc*'; + SELECT rowid FROM x1 WHERE x1 MATCH 'xd*'; + SELECT rowid FROM x1 WHERE x1 MATCH 'xe*'; + SELECT rowid FROM x1 WHERE x1 MATCH 'xf*'; + SELECT rowid FROM x1 WHERE x1 MATCH 'xg*'; + SELECT rowid FROM x1 WHERE x1 MATCH 'xh*'; + SELECT rowid FROM x1 WHERE x1 MATCH 'xi*'; + } + set {} {} + } {} + catch { db eval ROLLBACK } + } +} + +#------------------------------------------------------------------------ +# +reset_db +do_execsql_test 6.1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a); + INSERT INTO t1 VALUES('bbbbb ccccc'); + SELECT quote(block) FROM t1_data WHERE rowid>100; +} {X'000000180630626262626201020201056363636363010203040A'} +do_execsql_test 6.1.1 { + UPDATE t1_data SET block = + X'000000180630626262626201020201056161616161010203040A' + WHERE rowid>100; +} +do_catchsql_test 6.1.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +#------- +reset_db +do_execsql_test 6.2.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + INSERT INTO t1 VALUES('aa bb cc dd ee'); + SELECT pgno, quote(term) FROM t1_idx; +} {2 X'' 4 X'3064'} +do_execsql_test 6.2.1 { + UPDATE t1_idx SET term = X'3065' WHERE pgno=4; +} +do_catchsql_test 6.2.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +#------- +reset_db +do_execsql_test 6.3.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a); + INSERT INTO t1 VALUES('abc abcdef abcdefghi'); + SELECT quote(block) FROM t1_data WHERE id>100; +} {X'0000001C043061626301020204036465660102030703676869010204040808'} +do_execsql_test 6.3.1 { + BEGIN; + UPDATE t1_data SET block = + X'0000001C043061626301020204036465660102035003676869010204040808' + ------------------------------------------^^--------------------- + WHERE id>100; +} +do_catchsql_test 6.3.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} +do_execsql_test 6.3.3 { + ROLLBACK; + BEGIN; + UPDATE t1_data SET block = + X'0000001C043061626301020204036465660102030750676869010204040808' + --------------------------------------------^^------------------- + WHERE id>100; +} +do_catchsql_test 6.3.3 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} +do_execsql_test 6.3.4 { + ROLLBACK; + BEGIN; + UPDATE t1_data SET block = + X'0000001C043061626301020204036465660102030707676869010204040850' + --------------------------------------------------------------^^- + WHERE id>100; +} +do_catchsql_test 6.3.5 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} +do_execsql_test 6.3.6 { + ROLLBACK; + BEGIN; + UPDATE t1_data SET block = + X'0000001C503061626301020204036465660102030707676869010204040808' + ----------^^----------------------------------------------------- + WHERE id>100; +} +do_catchsql_test 6.3.5 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + + +#------------------------------------------------------------------------ +# +reset_db +proc rnddoc {n} { + set map [list a b c d] + set doc [list] + for {set i 0} {$i < $n} {incr i} { + lappend doc "x[lindex $map [expr int(rand()*4)]]" + } + set doc +} + +db func rnddoc rnddoc +do_test 7.0 { + execsql { + CREATE VIRTUAL TABLE t5 USING fts5(x); + INSERT INTO t5 VALUES( rnddoc(10000) ); + INSERT INTO t5 VALUES( rnddoc(10000) ); + INSERT INTO t5 VALUES( rnddoc(10000) ); + INSERT INTO t5 VALUES( rnddoc(10000) ); + INSERT INTO t5(t5) VALUES('optimize'); + } +} {} + +do_test 7.1 { + foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] { + db eval BEGIN + db eval {DELETE FROM t5_data WHERE rowid = $i} + set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ] + if {$r != "1 {database disk image is malformed}"} { error $r } + db eval ROLLBACK + } +} {} + +} + +#------------------------------------------------------------------------ +# Corruption within the structure record. +# +reset_db +do_execsql_test 8.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y); + INSERT INTO t1 VALUES('one', 'two'); +} + +do_test 9.1.1 { + set blob "12345678" ;# cookie + append blob "0105" ;# 1 level, total of 5 segments + append blob "06" ;# write counter + append blob "0002" ;# first level has 0 segments merging, 2 other. + append blob "450108" ;# first segment + execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" +} {} +do_catchsql_test 9.1.2 { + SELECT * FROM t1('one AND two'); +} {1 {database disk image is malformed}} + +do_test 9.2.1 { + set blob "12345678" ;# cookie + append blob "0205" ;# 2 levels, total of 5 segments + append blob "06" ;# write counter + append blob "0001" ;# first level has 0 segments merging, 1 other. + append blob "450108" ;# first segment + execsql "REPLACE INTO t1_data VALUES(10, X'$blob')" +} {} +do_catchsql_test 9.2.2 { + SELECT * FROM t1('one AND two'); +} {1 {database disk image is malformed}} + +sqlite3_fts5_may_be_corrupt 0 +finish_test + diff --git a/ext/fts5/test/fts5detail.test b/ext/fts5/test/fts5detail.test new file mode 100644 index 0000000..58fda3e --- /dev/null +++ b/ext/fts5/test/fts5detail.test @@ -0,0 +1,244 @@ +# 2015 December 18 +# +# 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 fts5detail + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +fts5_aux_test_functions db + +#-------------------------------------------------------------------------- +# Simple tests. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, detail=col); + INSERT INTO t1 VALUES('h d g', 'j b b g b', 'i e i d h g g'); -- 1 + INSERT INTO t1 VALUES('h j d', 'j h d a h', 'f d d g g f b'); -- 2 + INSERT INTO t1 VALUES('j c i', 'f f h e f', 'c j i j c h f'); -- 3 + INSERT INTO t1 VALUES('e g g', 'g e d h i', 'e d b e g d c'); -- 4 + INSERT INTO t1 VALUES('b c c', 'd i h a f', 'd i j f a b c'); -- 5 + INSERT INTO t1 VALUES('e d e', 'b c j g d', 'a i f d h b d'); -- 6 + INSERT INTO t1 VALUES('g h e', 'b c d i d', 'e f c i f i c'); -- 7 + INSERT INTO t1 VALUES('c f j', 'j j i e a', 'h a c f d h e'); -- 8 + INSERT INTO t1 VALUES('a h i', 'c i a f a', 'c f d h g d g'); -- 9 + INSERT INTO t1 VALUES('j g g', 'e f e f f', 'h j b i c g e'); -- 10 +} + +do_execsql_test 1.1 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +foreach {tn match res} { + 1 "a:a" {9} + 2 "b:g" {1 4 6} + 3 "c:h" {1 3 6 8 9 10} +} { + do_execsql_test 1.2.$tn.1 { + SELECT rowid FROM t1($match); + } $res + + do_execsql_test 1.2.$tn.2 { + SELECT rowid FROM t1($match || '*'); + } $res +} + +do_catchsql_test 1.3.1 { + SELECT rowid FROM t1('h + d'); +} {1 {fts5: phrase queries are not supported (detail!=full)}} + +do_catchsql_test 1.3.2 { + SELECT rowid FROM t1('NEAR(h d)'); +} {1 {fts5: NEAR queries are not supported (detail!=full)}} + + +#------------------------------------------------------------------------- +# integrity-check with both detail= and prefix= options. +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t2 USING fts5(a, detail=col, prefix="1"); + INSERT INTO t2(a) VALUES('aa ab'); +} + +#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t2_data} {puts $r} + +do_execsql_test 2.1 { + INSERT INTO t2(t2) VALUES('integrity-check'); +} + +do_execsql_test 2.2 { + SELECT fts5_test_poslist(t2) FROM t2('aa'); +} {0.0.0} + +do_execsql_test 2.3 { + SELECT fts5_test_collist(t2) FROM t2('aa'); +} {0.0} + +set ::pc 0 +#puts [nearset {{ax bx cx}} -pc ::pc -near 10 -- b*] +#exit + +#------------------------------------------------------------------------- +# Check that the xInstCount, xInst, xPhraseFirst and xPhraseNext APIs +# work with detail=col tables. +# +set data { + 1 {abb aca aca} {aba bab aab aac caa} {abc cbc ccb bcc bab ccb aca} + 2 {bca aca acb} {ccb bcc bca aab bcc} {bab aaa aac cbb bba aca abc} + 3 {cca abc cab} {aab aba bcc cac baa} {bab cbb acb aba aab ccc cca} + 4 {ccb bcb aba} {aba bbb bcc cac bbb} {cbb aaa bca bcc aab cac aca} + 5 {bca bbc cac} {aba cbb cac cca aca} {cab acb cbc ccb cac bbb bcb} + 6 {acc bba cba} {bab bbc bbb bcb aca} {bca ccc cbb aca bac ccc ccb} + 7 {aba bab aaa} {abb bca aac bcb bcc} {bcb bbc aba aaa cba abc acc} + 8 {cab aba aaa} {ccb aca caa bbc bcc} {aaa abc ccb bbb cac cca abb} + 9 {bcb bab bac} {bcb cba cac bbb abc} {aba aca cbb acb abb ccc ccb} + 10 {aba aab ccc} {abc ccc bcc cab bbb} {aab bcc cbb ccc aaa bac baa} + 11 {bab acb cba} {aac cab cab bca cbc} {aab cbc aac baa ccb acc cac} + 12 {ccc cbb cbc} {aaa aab bcc aac bbc} {cbc cbc bac bac ccc bbc acc} + 13 {cab bbc abc} {bbb bab bba aca bab} {baa bbb aab bbb ccb bbb ccc} + 14 {bbc cab caa} {acb aac abb cba acc} {cba bba bba acb abc abb baa} + 15 {aba cca bcc} {aaa acb abc aab ccb} {cca bcb acc aaa caa cca cbc} + 16 {bcb bba aba} {cbc acb cab caa ccb} {aac aaa bbc cab cca cba abc} + 17 {caa cbb acc} {ccb bcb bca aaa bcc} {bbb aca bcb bca cbc cbc cca} + 18 {cbb bbc aac} {ccc bbc aaa aab baa} {cab cab cac cca bbc abc bbc} + 19 {ccc acc aaa} {aab cbb bca cca caa} {bcb aca aca cab acc bac bcc} + 20 {aab ccc bcb} {bbc cbb bbc aaa bcc} {cbc aab ccc aaa bcb bac cbc} + 21 {aba cab ccc} {bbc cbc cba acc bbb} {acc aab aac acb aca bca acb} + 22 {bcb bca baa} {cca bbc aca ccb cbb} {aab abc bbc aaa cab bcc bcc} + 23 {cac cbb caa} {bbc aba bbb bcc ccb} {bbc bbb cab bbc cac abb acc} + 24 {ccb acb caa} {cab bba cac bbc aac} {aac bca abc cab bca cab bcb} + 25 {bbb aca bca} {bcb acc ccc cac aca} {ccc acb acc cac cac bba bbc} + 26 {bab acc caa} {caa cab cac bac aca} {aba cac caa acc bac ccc aaa} + 27 {bca bca aaa} {ccb aca bca aaa baa} {bab acc aaa cca cba cca bac} + 28 {ccb cac cac} {bca abb bba bbc baa} {aca ccb aac cab ccc cab caa} + 29 {abc bca cab} {cac cbc cbb ccc bcc} {bcc aaa aaa acc aac cac aac} + 30 {aca acc acb} {aab aac cbb caa acb} {acb bbc bbc acc cbb bbc aac} + 31 {aba aca baa} {aca bcc cab bab acb} {bcc acb baa bcb bbc acc aba} + 32 {abb cbc caa} {cba abb bbb cbb aca} {bac aca caa cac caa ccb bbc} + 33 {bcc bcb bcb} {cca cab cbc abb bab} {caa bbc aac bbb cab cba aaa} + 34 {caa cab acc} {ccc ccc bcc acb bcc} {bac bba aca bcb bba bcb cac} + 35 {bac bcb cba} {bcc acb bbc cba bab} {abb cbb abc abc bac acc cbb} + 36 {cab bab ccb} {bca bba bab cca acc} {acc aab bcc bac acb cbb caa} + 37 {aca cbc cab} {bba aac aca aac aaa} {baa cbb cba aba cab bca bcb} + 38 {acb aab baa} {baa bab bca bbc bbb} {abc baa acc aba cab baa cac} + 39 {bcb aac cba} {bcb baa caa cac bbc} {cbc ccc bab ccb bbb caa aba} + 40 {cba ccb abc} {cbb caa cba aac bab} {cbb bbb bca bbb bac cac bca} +} + +set data { + 1 {abb aca aca} {aba bab aab aac caa} {abc cbc ccb bcc bab ccb aca} +} + +proc matchdata {expr {bAsc 1}} { + + set tclexpr [db one { + SELECT fts5_expr_tcl($expr, 'nearset $cols -pc ::pc', 'x', 'y', 'z') + }] + set res [list] + + #puts "$expr -> $tclexpr" + foreach {id x y z} $::data { + set cols [list $x $y $z] + set ::pc 0 + #set hits [lsort -command instcompare [eval $tclexpr]] + set hits [eval $tclexpr] + if {[llength $hits]>0} { + lappend res [list $id $hits] + } + } + + if {$bAsc} { + set res [lsort -integer -increasing -index 0 $res] + } else { + set res [lsort -integer -decreasing -index 0 $res] + } + + return [concat {*}$res] +} + +foreach {tn tbl} { + 1 { CREATE VIRTUAL TABLE t3 USING fts5(x, y, z, detail=col) } + 2 { CREATE VIRTUAL TABLE t3 USING fts5(x, y, z, detail=none) } +} { + reset_db + fts5_aux_test_functions db + execsql $tbl + foreach {id x y z} $data { + execsql { INSERT INTO t3(rowid, x, y, z) VALUES($id, $x, $y, $z) } + } + foreach {tn2 expr} { + 1 aaa 2 ccc 3 bab 4 aac + 5 aa* 6 cc* 7 ba* 8 aa* + 9 a* 10 b* 11 c* + } { + + set res [matchdata $expr] + + do_execsql_test 3.$tn.$tn2.1 { + SELECT rowid, fts5_test_poslist(t3) FROM t3($expr) + } $res + + do_execsql_test 3.$tn.$tn2.2 { + SELECT rowid, fts5_test_poslist2(t3) FROM t3($expr) + } $res + } +} + +#------------------------------------------------------------------------- +# Simple tests for detail=none tables. +# +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE t4 USING fts5(a, b, c, detail=none); + INSERT INTO t4 VALUES('a b c', 'b c d', 'e f g'); + INSERT INTO t4 VALUES('1 2 3', '4 5 6', '7 8 9'); +} + +do_catchsql_test 4.1 { + SELECT * FROM t4('a:a') +} {1 {fts5: column queries are not supported (detail=none)}} + +#------------------------------------------------------------------------- +# Test that for the same content detail=none uses less space than +# detail=col, and that detail=col uses less space than detail=full +# +reset_db +do_test 5.1 { + foreach {tbl detail} {t1 none t2 col t3 full} { + execsql "CREATE VIRTUAL TABLE $tbl USING fts5(x, y, z, detail=$detail)" + foreach {rowid x y z} $::data { + execsql "INSERT INTO $tbl (rowid, x, y, z) VALUES(\$rowid, \$x, \$y, \$z)" + } + } +} {} + +do_execsql_test 5.2 { + SELECT + (SELECT sum(length(block)) from t1_data) < + (SELECT sum(length(block)) from t2_data) +} {1} + +do_execsql_test 5.3 { + SELECT + (SELECT sum(length(block)) from t2_data) < + (SELECT sum(length(block)) from t3_data) +} {1} + + + +finish_test + diff --git a/ext/fts5/test/fts5dlidx.test b/ext/fts5/test/fts5dlidx.test new file mode 100644 index 0000000..232b502 --- /dev/null +++ b/ext/fts5/test/fts5dlidx.test @@ -0,0 +1,200 @@ +# 2015 April 21 +# +# 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 uses of doclist-index records. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5dlidx + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +if { $tcl_platform(wordSize)<8 } { + finish_test + return +} + +foreach_detail_mode $testprefix { + +proc do_fb_test {tn sql res} { + set res2 [lsort -integer -decr $res] + uplevel [list do_execsql_test $tn.1 $sql $res] + uplevel [list do_execsql_test $tn.2 "$sql ORDER BY rowid DESC" $res2] +} + +# This test populates the FTS5 table with $nEntry entries. Rows are +# numbered from 0 to ($nEntry-1). The rowid for row $i is: +# +# ($iFirst + $i*$nStep) +# +# Each document is of the form "a b c a b c a b c...". If the row number ($i) +# is an integer multiple of $spc1, then an "x" token is appended to the +# document. If it is *also* a multiple of $spc2, a "y" token is also appended. +# +proc do_dlidx_test1 {tn spc1 spc2 nEntry iFirst nStep} { + + do_execsql_test $tn.0 { DELETE FROM t1 } + + set xdoc [list] + set ydoc [list] + + execsql BEGIN + for {set i 0} {$i < $nEntry} {incr i} { + set rowid [expr $i * $nStep] + set doc [string trim [string repeat "a b c " 100]] + if {($i % $spc1)==0} { + lappend xdoc $rowid + append doc " x" + if {($i % $spc2)==0} { + lappend ydoc $rowid + append doc " y" + } + } + execsql { INSERT INTO t1(rowid, x) VALUES($rowid, $doc) } + } + execsql COMMIT + + breakpoint + do_test $tn.1 { + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } + } {} + + do_fb_test $tn.3.1 { SELECT rowid FROM t1 WHERE t1 MATCH 'a AND x' } $xdoc + do_fb_test $tn.3.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'x AND a' } $xdoc + + do_fb_test $tn.4.1 { SELECT rowid FROM t1 WHERE t1 MATCH 'a AND y' } $ydoc + do_fb_test $tn.4.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'y AND a' } $ydoc + + if {[detail_is_full]} { + do_fb_test $tn.5.1 { + SELECT rowid FROM t1 WHERE t1 MATCH 'a + b + c + x' } $xdoc + do_fb_test $tn.5.2 { + SELECT rowid FROM t1 WHERE t1 MATCH 'b + c + x + y' } $ydoc + } +} + + +foreach {tn pgsz} { + 1 32 + 2 200 +} { + do_execsql_test $tn.0 { + DROP TABLE IF EXISTS t1; + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz); + } + + do_dlidx_test1 1.$tn.1 10 100 10000 0 1000 + do_dlidx_test1 1.$tn.2 10 10 10000 0 128 + do_dlidx_test1 1.$tn.3 10 10 66 0 36028797018963970 + do_dlidx_test1 1.$tn.4 10 10 50 0 150000000000000000 + do_dlidx_test1 1.$tn.5 10 10 200 0 [expr 1<<55] + do_dlidx_test1 1.$tn.6 10 10 30 0 [expr 1<<58] +} + +proc do_dlidx_test2 {tn nEntry iFirst nStep} { + set str [string repeat "a " 500] + execsql { + BEGIN; + DROP TABLE IF EXISTS t1; + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 64); + INSERT INTO t1 VALUES('b a'); + + WITH iii(ii, i) AS ( + SELECT 1, $iFirst UNION ALL + SELECT ii+1, i+$nStep FROM iii WHERE ii<$nEntry + ) + INSERT INTO t1(rowid,x) SELECT i, $str FROM iii; + COMMIT; + } + + do_execsql_test $tn.1 { + SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' + } {1} + breakpoint + do_execsql_test $tn.2 { + SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' ORDER BY rowid DESC + } {1} +} + +do_dlidx_test2 2.1 [expr 20] [expr 1<<57] [expr (1<<57) + 128] + +#-------------------------------------------------------------------- +# +reset_db + +set ::vocab [list \ + IteratorpItercurrentlypointstothefirstrowidofadoclist \ + Thereisadoclistindexassociatedwiththefinaltermonthecurrent \ + pageIfthecurrenttermisthelasttermonthepageloadthe \ + doclistindexfromdiskandinitializeaniteratoratpIterpDlidx \ + IteratorpItercurrentlypointstothefirstrowidofadoclist \ + Thereisadoclistindexassociatedwiththefinaltermonthecurrent \ + pageIfthecurrenttermisthelasttermonthepageloadthe \ + doclistindexfromdiskandinitializeaniteratoratpIterpDlidx \ +] +proc rnddoc {} { + global vocab + set nVocab [llength $vocab] + set ret [list] + for {set i 0} {$i < 64} {incr i} { + lappend ret [lindex $vocab [expr $i % $nVocab]] + } + set ret +} +db func rnddoc rnddoc + +do_execsql_test 3.1 { + CREATE VIRTUAL TABLE abc USING fts5(a, detail=%DETAIL%); + INSERT INTO abc(abc, rank) VALUES('pgsz', 32); + + INSERT INTO abc VALUES ( rnddoc() ); + INSERT INTO abc VALUES ( rnddoc() ); + INSERT INTO abc VALUES ( rnddoc() ); + INSERT INTO abc VALUES ( rnddoc() ); + + INSERT INTO abc SELECT rnddoc() FROM abc; + INSERT INTO abc SELECT rnddoc() FROM abc; +} + + + +do_execsql_test 3.2 { + SELECT rowid FROM abc WHERE abc + MATCH 'IteratorpItercurrentlypointstothefirstrowidofadoclist' + ORDER BY rowid DESC; +} {16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1} + +do_execsql_test 3.2 { + INSERT INTO abc(abc) VALUES('integrity-check'); + INSERT INTO abc(abc) VALUES('optimize'); + INSERT INTO abc(abc) VALUES('integrity-check'); +} + +set v [lindex $vocab 0] +set i 0 +foreach v $vocab { + do_execsql_test 3.3.[incr i] { + SELECT rowid FROM abc WHERE abc MATCH $v + } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16} +} + +} ;# foreach_detail_mode + + + +finish_test + diff --git a/ext/fts5/test/fts5doclist.test b/ext/fts5/test/fts5doclist.test new file mode 100644 index 0000000..411289a --- /dev/null +++ b/ext/fts5/test/fts5doclist.test @@ -0,0 +1,47 @@ +# 2015 April 21 +# +# 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 edge cases in the doclist format. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5doclist + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + + +#------------------------------------------------------------------------- +# Create a table with 1000 columns. Then add some large documents to it. +# All text is in the right most column of the table. +# +do_test 1.0 { + set cols [list] + for {set i 0} {$i < 900} {incr i} { lappend cols "x$i" } + execsql "CREATE VIRTUAL TABLE ccc USING fts5([join $cols ,])" +} {} + +db func rnddoc fts5_rnddoc +do_execsql_test 1.1 { + WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<100) + INSERT INTO ccc(x899) SELECT rnddoc(500) FROM ii; +} + +do_execsql_test 1.2 { + INSERT INTO ccc(ccc) VALUES('integrity-check'); +} + + +finish_test + diff --git a/ext/fts5/test/fts5ea.test b/ext/fts5/test/fts5ea.test new file mode 100644 index 0000000..3ccbd7d --- /dev/null +++ b/ext/fts5/test/fts5ea.test @@ -0,0 +1,99 @@ +# 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. +# +#************************************************************************* +# +# Test the fts5 expression parser directly using the fts5_expr() SQL +# test function. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5ea + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc do_syntax_error_test {tn expr err} { + set ::se_expr $expr + do_catchsql_test $tn {SELECT fts5_expr($se_expr)} [list 1 $err] +} + +proc do_syntax_test {tn expr res} { + set ::se_expr $expr + do_execsql_test $tn {SELECT fts5_expr($se_expr)} [list $res] +} + +foreach {tn expr res} { + 1 {abc} {"abc"} + 2 {abc def} {"abc" AND "def"} + 3 {abc*} {"abc" *} + 4 {"abc def ghi" *} {"abc" + "def" + "ghi" *} + 5 {one AND two} {"one" AND "two"} + 6 {one+two} {"one" + "two"} + 7 {one AND two OR three} {("one" AND "two") OR "three"} + 8 {one OR two AND three} {"one" OR ("two" AND "three")} + 9 {NEAR(one two)} {NEAR("one" "two", 10)} + 10 {NEAR("one three"* two, 5)} {NEAR("one" + "three" * "two", 5)} + 11 {a OR b NOT c} {"a" OR ("b" NOT "c")} + 12 "\x20one\x20two\x20three" {"one" AND "two" AND "three"} + 13 "\x09one\x0Atwo\x0Dthree" {"one" AND "two" AND "three"} + 14 {"abc""def"} {"abc" + "def"} +} { + do_execsql_test 1.$tn {SELECT fts5_expr($expr)} [list $res] +} + +foreach {tn expr res} { + 1 {c1:abc} + {c1 : "abc"} + 2 {c2 : NEAR(one two) c1:"hello world"} + {c2 : NEAR("one" "two", 10) AND c1 : "hello" + "world"} +} { + do_execsql_test 2.$tn {SELECT fts5_expr($expr, 'c1', 'c2')} [list $res] +} + +foreach {tn expr err} { + 1 {AND} {fts5: syntax error near "AND"} + 2 {abc def AND} {fts5: syntax error near ""} + 3 {abc OR AND} {fts5: syntax error near "AND"} + 4 {(a OR b) abc} {fts5: syntax error near "abc"} + 5 {NEaR (a b)} {fts5: syntax error near "NEaR"} + 6 {NEa (a b)} {fts5: syntax error near "NEa"} + 7 {(a OR b) NOT c)} {fts5: syntax error near ")"} + 8 {nosuch: a nosuch2: b} {no such column: nosuch} + 9 {addr: a nosuch2: b} {no such column: nosuch2} + 10 {NOT} {fts5: syntax error near "NOT"} + 11 {a AND "abc} {unterminated string} + + 12 {NEAR(a b, xyz)} {expected integer, got "xyz"} + 13 {NEAR(a b, // )} {fts5: syntax error near "/"} + 14 {NEAR(a b, "xyz" )} {expected integer, got ""xyz""} +} { + do_catchsql_test 3.$tn {SELECT fts5_expr($expr, 'name', 'addr')} [list 1 $err] +} + +#------------------------------------------------------------------------- +# Experiment with a tokenizer that considers " to be a token character. +# +do_execsql_test 4.0 { + SELECT fts5_expr('a AND """"', 'x', 'tokenize="unicode61 tokenchars ''""''"'); +} {{"a" AND """"}} + +#------------------------------------------------------------------------- +# Experiment with a tokenizer that considers " to be a token character. +# +do_catchsql_test 5.0 { + SELECT fts5_expr('abc | def'); +} {1 {fts5: syntax error near "|"}} + + + +finish_test diff --git a/ext/fts5/test/fts5eb.test b/ext/fts5/test/fts5eb.test new file mode 100644 index 0000000..8205396 --- /dev/null +++ b/ext/fts5/test/fts5eb.test @@ -0,0 +1,69 @@ +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5eb + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc do_syntax_error_test {tn expr err} { + set ::se_expr $expr + do_catchsql_test $tn {SELECT fts5_expr($se_expr)} [list 1 $err] +} + +proc do_syntax_test {tn expr res} { + set ::se_expr $expr + do_execsql_test $tn {SELECT fts5_expr($se_expr)} [list $res] +} + +foreach {tn expr res} { + 1 {abc} {"abc"} + 2 {abc ""} {"abc"} + 3 {""} {} + 4 {abc OR ""} {"abc"} + 5 {abc NOT ""} {"abc"} + 6 {abc AND ""} {"abc"} + 7 {"" OR abc} {"abc"} + 8 {"" NOT abc} {"abc"} + 9 {"" AND abc} {"abc"} + 10 {abc + "" + def} {"abc" + "def"} + 11 {abc "" def} {"abc" AND "def"} + 12 {r+e OR w} {"r" + "e" OR "w"} + + 13 {a AND b NOT c} {"a" AND ("b" NOT "c")} + 14 {a OR b NOT c} {"a" OR ("b" NOT "c")} + 15 {a NOT b AND c} {("a" NOT "b") AND "c"} + 16 {a NOT b OR c} {("a" NOT "b") OR "c"} + + 17 {a AND b OR c} {("a" AND "b") OR "c"} + 18 {a OR b AND c} {"a" OR ("b" AND "c")} + +} { + do_execsql_test 1.$tn {SELECT fts5_expr($expr)} [list $res] +} + +do_catchsql_test 2.1 { + SELECT fts5_expr() +} {1 {wrong number of arguments to function fts5_expr}} + +do_catchsql_test 2.1 { + SELECT fts5_expr_tcl() +} {1 {wrong number of arguments to function fts5_expr_tcl}} + +finish_test + + + diff --git a/ext/fts5/test/fts5fault1.test b/ext/fts5/test/fts5fault1.test new file mode 100644 index 0000000..9d63a11 --- /dev/null +++ b/ext/fts5/test/fts5fault1.test @@ -0,0 +1,354 @@ +# 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] +source $testdir/malloc_common.tcl +set testprefix fts5fault1 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +# Simple tests: +# +# 1: CREATE VIRTUAL TABLE +# 2: INSERT statement +# 3: DELETE statement +# 4: MATCH expressions +# +# + +faultsim_save_and_close +do_faultsim_test 1 -faults ioerr-t* -prep { + faultsim_restore_and_reopen +} -body { + execsql { CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3') } +} -test { + faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} +} + +reset_db +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3'); +} +faultsim_save_and_close +do_faultsim_test 2 -prep { + faultsim_restore_and_reopen +} -body { + execsql { + INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno'); + } +} -test { + faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} +} + +reset_db +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, prefix='1, 2, 3'); + INSERT INTO t1 VALUES('a b c', 'a bc def ghij klmno'); +} +faultsim_save_and_close +do_faultsim_test 3 -prep { + faultsim_restore_and_reopen +} -body { + execsql { DELETE FROM t1 } +} -test { + faultsim_test_result {0 {}} {1 {vtable constructor failed: t1}} +} + +reset_db +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE t2 USING fts5(a, b); + INSERT INTO t2 VALUES('m f a jj th q gi ar', 'hj n h h sg j i m'); + INSERT INTO t2 VALUES('nr s t g od j kf h', 'sb h aq rg op rb n nl'); + INSERT INTO t2 VALUES('do h h pb p p q fr', 'c rj qs or cr a l i'); + INSERT INTO t2 VALUES('lk gp t i lq mq qm p', 'h mr g f op ld aj h'); + INSERT INTO t2 VALUES('ct d sq kc qi k f j', 'sn gh c of g s qt q'); + INSERT INTO t2 VALUES('d ea d d om mp s ab', 'dm hg l df cm ft pa c'); + INSERT INTO t2 VALUES('tc dk c jn n t sr ge', 'a a kn bc n i af h'); + INSERT INTO t2 VALUES('ie ii d i b sa qo rf', 'a h m aq i b m fn'); + INSERT INTO t2 VALUES('gs r fo a er m h li', 'tm c p gl eb ml q r'); + INSERT INTO t2 VALUES('k fe fd rd a gi ho kk', 'ng m c r d ml rm r'); +} +faultsim_save_and_close + +foreach {tn expr res} { + 1 { dk } 7 + 2 { m f } 1 + 3 { f* } {1 3 4 5 6 8 9 10} + 4 { m OR f } {1 4 5 8 9 10} + 5 { sn + gh } {5} + 6 { "sn gh" } {5} + 7 { NEAR(r a, 5) } {9} + 8 { m* f* } {1 4 6 8 9 10} + 9 { m* + f* } {1 8} + 10 { c NOT p } {5 6 7 10} +} { + do_faultsim_test 4.$tn -prep { + faultsim_restore_and_reopen + } -body " + execsql { SELECT rowid FROM t2 WHERE t2 MATCH '$expr' } + " -test " + faultsim_test_result {[list 0 $res]} {1 {vtable constructor failed: t2}} + " +} + + +#------------------------------------------------------------------------- +# The following tests use a larger database populated with random data. +# +# The database page size is set to 512 bytes and the FTS5 page size left +# at the default 1000 bytes. This means that reading a node may require +# pulling an overflow page from disk, which is an extra opportunity for +# an error to occur. +# +reset_db +do_execsql_test 5.0.1 { + PRAGMA main.page_size = 512; + CREATE VIRTUAL TABLE x1 USING fts5(a, b); + PRAGMA main.page_size; +} {512} + +proc rnddoc {n} { + set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] + set doc [list] + for {set i 0} {$i < $n} {incr i} { + lappend doc [string map $map [format %.3d [expr int(rand()*1000)]]] + } + set doc +} +db func rnddoc rnddoc + +do_execsql_test 5.0.2 { + WITH r(a, b) AS ( + SELECT rnddoc(6), rnddoc(6) UNION ALL + SELECT rnddoc(6), rnddoc(6) FROM r + ) + INSERT INTO x1 SELECT * FROM r LIMIT 10000; +} + +set res [db one { + SELECT count(*) FROM x1 WHERE x1.a LIKE '%abc%' OR x1.b LIKE '%abc%'} +] + +do_faultsim_test 5.1 -faults oom* -body { + execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abc' } +} -test { + faultsim_test_result [list 0 $::res] +} +do_faultsim_test 5.2 -faults oom* -body { + execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'abcd' } +} -test { + faultsim_test_result [list 0 0] +} + +proc test_astar {a b} { + return [expr { [regexp {a[^ ][^ ]} $a] || [regexp {a[^ ][^ ]} $b] }] +} +db func test_astar test_astar + +set res [db one { SELECT count(*) FROM x1 WHERE test_astar(a, b) } ] +do_faultsim_test 5.3 -faults oom* -body { + execsql { SELECT count(*) FROM x1 WHERE x1 MATCH 'a*' } +} -test { + faultsim_test_result [list 0 $::res] +} + +do_faultsim_test 5.4 -faults oom* -prep { + db close + sqlite3 db test.db +} -body { + execsql { INSERT INTO x1 VALUES('a b c d', 'e f g h') } +} -test { + faultsim_test_result [list 0 {}] +} + +do_faultsim_test 5.5.1 -faults oom* -body { + execsql { + SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=1 + } +} -test { + faultsim_test_result [list 0 1] +} +do_faultsim_test 5.5.2 -faults oom* -body { + execsql { + SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid=10 + } +} -test { + faultsim_test_result [list 0 1] +} +do_faultsim_test 5.5.3 -faults oom* -body { + execsql { + SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = ( + SELECT min(rowid) FROM x1_data WHERE rowid>20 + ) + } +} -test { + faultsim_test_result [list 0 1] +} +do_faultsim_test 5.5.4 -faults oom* -body { + execsql { + SELECT count(fts5_decode(rowid, block)) FROM x1_data WHERE rowid = ( + SELECT max(rowid) FROM x1_data + ) + } +} -test { + faultsim_test_result [list 0 1] +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('automerge', 0); + + INSERT INTO x1 VALUES('a b c'); -- 1 + INSERT INTO x1 VALUES('a b c'); -- 2 + INSERT INTO x1 VALUES('a b c'); -- 3 + INSERT INTO x1 VALUES('a b c'); -- 4 + INSERT INTO x1 VALUES('a b c'); -- 5 + INSERT INTO x1 VALUES('a b c'); -- 6 + INSERT INTO x1 VALUES('a b c'); -- 7 + INSERT INTO x1 VALUES('a b c'); -- 8 + INSERT INTO x1 VALUES('a b c'); -- 9 + INSERT INTO x1 VALUES('a b c'); -- 10 + INSERT INTO x1 VALUES('a b c'); -- 11 + INSERT INTO x1 VALUES('a b c'); -- 12 + INSERT INTO x1 VALUES('a b c'); -- 13 + INSERT INTO x1 VALUES('a b c'); -- 14 + INSERT INTO x1 VALUES('a b c'); -- 15 + + SELECT count(*) FROM x1_data; +} {17} + +faultsim_save_and_close + +do_faultsim_test 6.1 -faults oom* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO x1 VALUES('d e f') } +} -test { + faultsim_test_result [list 0 {}] + if {$testrc==0} { + set nCnt [db one {SELECT count(*) FROM x1_data}] + if {$nCnt!=3} { error "expected 3 entries but there are $nCnt" } + } +} + +do_faultsim_test 6.2 -faults oom* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO x1(x1, rank) VALUES('pgsz', 32) } +} -test { + faultsim_test_result [list 0 {}] +} + +do_faultsim_test 6.3 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO x1(x1) VALUES('integrity-check') } +} -test { + faultsim_test_result [list 0 {}] +} + +do_faultsim_test 6.4 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO x1(x1) VALUES('optimize') } +} -test { + faultsim_test_result [list 0 {}] +} + +#------------------------------------------------------------------------- +# +do_faultsim_test 7.0 -faults oom* -prep { + catch { db close } +} -body { + sqlite3 db test.db +} -test { + faultsim_test_result [list 0 {}] {1 {}} {1 {initialization of fts5 failed: }} +} + +#------------------------------------------------------------------------- +# A prefix query against a large document set. +# +proc rnddoc {n} { + set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] + set doc [list] + for {set i 0} {$i < $n} {incr i} { + lappend doc "x[string map $map [format %.3d [expr int(rand()*1000)]]]" + } + set doc +} + +reset_db +db func rnddoc rnddoc + +do_test 8.0 { + execsql { CREATE VIRTUAL TABLE x1 USING fts5(a) } + set ::res [list] + for {set i 1} {$i<100} {incr i 1} { + execsql { INSERT INTO x1 VALUES( rnddoc(50) ) } + lappend ::res $i + } +} {} + +do_faultsim_test 8.1 -faults oom* -prep { +} -body { + execsql { + SELECT rowid FROM x1 WHERE x1 MATCH 'x*' + } +} -test { + faultsim_test_result [list 0 $::res] +} + +#------------------------------------------------------------------------- +# Segment promotion. +# +do_test 9.0 { + reset_db + db func rnddoc fts5_rnddoc + execsql { + CREATE VIRTUAL TABLE s2 USING fts5(x); + INSERT INTO s2(s2, rank) VALUES('pgsz', 32); + INSERT INTO s2(s2, rank) VALUES('automerge', 0); + } + + for {set i 1} {$i <= 16} {incr i} { + execsql { INSERT INTO s2 VALUES(rnddoc(5)) } + } + fts5_level_segs s2 +} {0 1} +set insert_doc [db one {SELECT rnddoc(160)}] +faultsim_save_and_close + +do_faultsim_test 9.1 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO s2 VALUES($::insert_doc) } +} -test { + faultsim_test_result {0 {}} + if {$testrc==0} { + set ls [fts5_level_segs s2] + if {$ls != "2 0"} { error "fts5_level_segs says {$ls}" } + } +} + + + +finish_test + diff --git a/ext/fts5/test/fts5fault2.test b/ext/fts5/test/fts5fault2.test new file mode 100644 index 0000000..43c7c7a --- /dev/null +++ b/ext/fts5/test/fts5fault2.test @@ -0,0 +1,140 @@ +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5fault2 + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +set doc [string trim [string repeat "x y z " 200]] +do_execsql_test 1.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, x); + CREATE VIRTUAL TABLE x1 USING fts5(x, content='t1', content_rowid='a'); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + WITH input(a,b) AS ( + SELECT 1, $doc UNION ALL + SELECT a+1, ($doc || CASE WHEN (a+1)%100 THEN '' ELSE ' xyz' END) + FROM input WHERE a < 1000 + ) + INSERT INTO t1 SELECT * FROM input; + + INSERT INTO x1(x1) VALUES('rebuild'); +} + +do_faultsim_test 1.1 -faults oom-* -prep { +} -body { + execsql { SELECT rowid FROM x1 WHERE x1 MATCH 'z AND xyz' } +} -test { + faultsim_test_result {0 {100 200 300 400 500 600 700 800 900 1000}} +} + +do_faultsim_test 1.2 -faults oom-* -prep { +} -body { + execsql { SELECT rowid FROM x1 WHERE x1 MATCH 'z + xyz' ORDER BY 1 DESC} +} -test { + faultsim_test_result {0 {1000 900 800 700 600 500 400 300 200 100}} +} + +#------------------------------------------------------------------------- +# OOM within a query that accesses the in-memory hash table. +# +reset_db +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE "a b c" USING fts5(a, b, c); + INSERT INTO "a b c" VALUES('one two', 'x x x', 'three four'); + INSERT INTO "a b c" VALUES('nine ten', 'y y y', 'two two'); +} + +do_faultsim_test 2.1 -faults oom-trans* -prep { + execsql { + BEGIN; + INSERT INTO "a b c" VALUES('one one', 'z z z', 'nine ten'); + } +} -body { + execsql { SELECT rowid FROM "a b c" WHERE "a b c" MATCH 'one' } +} -test { + faultsim_test_result {0 {1 3}} + catchsql { ROLLBACK } +} + +#------------------------------------------------------------------------- +# OOM within an 'optimize' operation that writes multiple pages to disk. +# +reset_db +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE zzz USING fts5(z); + INSERT INTO zzz(zzz, rank) VALUES('pgsz', 32); + INSERT INTO zzz VALUES('a b c d'); + INSERT INTO zzz SELECT 'c d e f' FROM zzz; + INSERT INTO zzz SELECT 'e f g h' FROM zzz; + INSERT INTO zzz SELECT 'i j k l' FROM zzz; + INSERT INTO zzz SELECT 'l k m n' FROM zzz; + INSERT INTO zzz SELECT 'o p q r' FROM zzz; +} +faultsim_save_and_close + +do_faultsim_test 3.1 -faults oom-trans* -prep { + faultsim_restore_and_reopen + execsql { SELECT rowid FROM zzz } +} -body { + execsql { INSERT INTO zzz(zzz) VALUES('optimize') } +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +# OOM within an 'integrity-check' operation. +# +reset_db +db func rnddoc fts5_rnddoc +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE zzz USING fts5(z); + INSERT INTO zzz(zzz, rank) VALUES('pgsz', 32); + WITH ii(i) AS (SELECT 1 UNION SELECT i+1 FROM ii WHERE i<10) + INSERT INTO zzz SELECT rnddoc(10) || ' xccc' FROM ii; +} + +do_faultsim_test 4.1 -faults oom-trans* -prep { +} -body { + execsql { INSERT INTO zzz(zzz) VALUES('integrity-check') } +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +# OOM while parsing a tokenize=option +# +reset_db +faultsim_save_and_close +do_faultsim_test 5.0 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { + CREATE VIRTUAL TABLE uio USING fts5(a, b, + tokenize="porter 'ascii'", + content="another table", + content_rowid="somecolumn" + ); + } +} -test { + faultsim_test_result {0 {}} +} + +finish_test + diff --git a/ext/fts5/test/fts5fault3.test b/ext/fts5/test/fts5fault3.test new file mode 100644 index 0000000..bfeead4 --- /dev/null +++ b/ext/fts5/test/fts5fault3.test @@ -0,0 +1,113 @@ +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5fault3 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# An OOM while resuming a partially completed segment merge. +# +db func rnddoc fts5_rnddoc +do_test 1.0 { + expr srand(0) + execsql { + CREATE VIRTUAL TABLE xx USING fts5(x); + INSERT INTO xx(xx, rank) VALUES('pgsz', 32); + INSERT INTO xx(xx, rank) VALUES('automerge', 16); + } + for {set i 0} {$i < 10} {incr i} { + execsql { + BEGIN; + INSERT INTO xx(x) VALUES(rnddoc(20)); + INSERT INTO xx(x) VALUES(rnddoc(20)); + INSERT INTO xx(x) VALUES(rnddoc(20)); + COMMIT + } + } + + execsql { + INSERT INTO xx(xx, rank) VALUES('automerge', 2); + INSERT INTO xx(xx, rank) VALUES('merge', 50); + } +} {} +faultsim_save_and_close + +do_faultsim_test 1 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO xx(xx, rank) VALUES('merge', 1) } +} -test { + faultsim_test_result [list 0 {}] +} + +#------------------------------------------------------------------------- +# An OOM while flushing an unusually large term to disk. +# +reset_db +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE xx USING fts5(x); + INSERT INTO xx(xx, rank) VALUES('pgsz', 32); +} +faultsim_save_and_close + +set doc "a long term abcdefghijklmnopqrstuvwxyz " +append doc "and then abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz " +append doc [string repeat "abcdefghijklmnopqrstuvwxyz" 10] + +do_faultsim_test 2 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO xx(x) VALUES ($::doc) } +} -test { + faultsim_test_result [list 0 {}] +} + +#------------------------------------------------------------------------- +# An OOM while flushing an unusually large term to disk. +# +reset_db +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE xx USING fts5(x); +} +faultsim_save_and_close + +set doc [fts5_rnddoc 1000] +do_faultsim_test 3.1 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO xx(x) VALUES ($::doc) } +} -test { + faultsim_test_result [list 0 {}] +} + +set doc [string repeat "abc " 100] +do_faultsim_test 3.2 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO xx(x) VALUES ($::doc) } +} -test { + faultsim_test_result [list 0 {}] +} + + + +finish_test + diff --git a/ext/fts5/test/fts5fault4.test b/ext/fts5/test/fts5fault4.test new file mode 100644 index 0000000..acc43eb --- /dev/null +++ b/ext/fts5/test/fts5fault4.test @@ -0,0 +1,398 @@ +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5fault4 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# An OOM while dropping an fts5 table. +# +db func rnddoc fts5_rnddoc +do_test 1.0 { + execsql { CREATE VIRTUAL TABLE xx USING fts5(x) } +} {} +faultsim_save_and_close + +do_faultsim_test 1 -faults oom-* -prep { + faultsim_restore_and_reopen + execsql { SELECT * FROM xx } +} -body { + execsql { DROP TABLE xx } +} -test { + faultsim_test_result [list 0 {}] +} + +#------------------------------------------------------------------------- +# An OOM while "reseeking" an FTS cursor. +# +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE jj USING fts5(j); + INSERT INTO jj(rowid, j) VALUES(101, 'm t w t f s s'); + INSERT INTO jj(rowid, j) VALUES(202, 't w t f s'); + INSERT INTO jj(rowid, j) VALUES(303, 'w t f'); + INSERT INTO jj(rowid, j) VALUES(404, 't'); +} +faultsim_save_and_close + +do_faultsim_test 3 -faults oom-* -prep { + faultsim_restore_and_reopen + execsql { SELECT * FROM jj } +} -body { + set res [list] + db eval { SELECT rowid FROM jj WHERE jj MATCH 't' } { + lappend res $rowid + if {$rowid==303} { + execsql { DELETE FROM jj WHERE rowid=404 } + } + } + set res +} -test { + faultsim_test_result [list 0 {101 202 303}] +} + +#------------------------------------------------------------------------- +# An OOM within a special "*reads" query. +# +reset_db +db func rnddoc fts5_rnddoc +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + + WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 ) + INSERT INTO x1 SELECT rnddoc(5) FROM ii; +} + +set ::res [db eval {SELECT rowid, x1 FROM x1 WHERE x1 MATCH '*reads'}] + +do_faultsim_test 4 -faults oom-* -body { + db eval {SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads'} +} -test { + faultsim_test_result {0 {0 {} 4}} +} + +#------------------------------------------------------------------------- +# An OOM within a query that uses a custom rank function. +# +reset_db +do_execsql_test 5.0 { + PRAGMA encoding='utf16'; + CREATE VIRTUAL TABLE x2 USING fts5(x); + INSERT INTO x2(rowid, x) VALUES(10, 'a b c'); -- 3 + INSERT INTO x2(rowid, x) VALUES(20, 'a b c'); -- 6 + INSERT INTO x2(rowid, x) VALUES(30, 'a b c'); -- 2 + INSERT INTO x2(rowid, x) VALUES(40, 'a b c'); -- 5 + INSERT INTO x2(rowid, x) VALUES(50, 'a b c'); -- 1 +} + +proc rowidmod {cmd mod} { + set row [$cmd xRowid] + expr {$row % $mod} +} +sqlite3_fts5_create_function db rowidmod rowidmod + +do_faultsim_test 5.1 -faults oom-* -body { + db eval { + SELECT rowid || '-' || rank FROM x2 WHERE x2 MATCH 'b' AND + rank MATCH "rowidmod('7')" ORDER BY rank + } +} -test { + faultsim_test_result {0 {50-1 30-2 10-3 40-5 20-6}} +} + +proc rowidprefix {cmd prefix} { + set row [$cmd xRowid] + set {} "${row}-${prefix}" +} +sqlite3_fts5_create_function db rowidprefix rowidprefix + +set str [string repeat abcdefghijklmnopqrstuvwxyz 10] +do_faultsim_test 5.2 -faults oom-* -body { + db eval " + SELECT rank, x FROM x2 WHERE x2 MATCH 'b' AND + rank MATCH 'rowidprefix(''$::str'')' + LIMIT 1 + " +} -test { + faultsim_test_result "0 {10-$::str {a b c}}" +} + + +#------------------------------------------------------------------------- +# OOM errors within auxiliary functions. +# +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE x3 USING fts5(xxx); + INSERT INTO x3 VALUES('a b c d c b a'); + INSERT INTO x3 VALUES('a a a a a a a'); + INSERT INTO x3 VALUES('a a a a a a a'); +} + +do_faultsim_test 6.1 -faults oom-t* -body { + db eval { SELECT highlight(x3, 0, '*', '*') FROM x3 WHERE x3 MATCH 'c' } +} -test { + faultsim_test_result {0 {{a b *c* d *c* b a}}} +} + +proc firstinst {cmd} { + foreach {p c o} [$cmd xInst 0] {} + expr $c*100 + $o +} +sqlite3_fts5_create_function db firstinst firstinst + +do_faultsim_test 6.2 -faults oom-t* -body { + db eval { SELECT firstinst(x3) FROM x3 WHERE x3 MATCH 'c' } +} -test { + faultsim_test_result {0 2} {1 SQLITE_NOMEM} +} + +proc previc {cmd} { + set res [$cmd xGetAuxdataInt 0] + $cmd xSetAuxdataInt [$cmd xInstCount] + return $res +} +sqlite3_fts5_create_function db previc previc + +do_faultsim_test 6.2 -faults oom-t* -body { + db eval { SELECT previc(x3) FROM x3 WHERE x3 MATCH 'a' } +} -test { + faultsim_test_result {0 {0 2 7}} {1 SQLITE_NOMEM} +} + +#------------------------------------------------------------------------- +# OOM error when querying for a phrase with many tokens. +# +reset_db +do_execsql_test 7.0 { + CREATE VIRTUAL TABLE tt USING fts5(x, y); + INSERT INTO tt VALUES('f b g b c b', 'f a d c c b'); -- 1 + INSERT INTO tt VALUES('d a e f e d', 'f b b d e e'); -- 2 + INSERT INTO tt VALUES('f b g a d c', 'e f c f a d'); -- 3 + INSERT INTO tt VALUES('f f c d g f', 'f a e b g b'); -- 4 + INSERT INTO tt VALUES('a g b d a g', 'e g a e a c'); -- 5 + INSERT INTO tt VALUES('c d b d e f', 'f g e g e e'); -- 6 + INSERT INTO tt VALUES('e g f f b c', 'f c e f g f'); -- 7 + INSERT INTO tt VALUES('e g c f c e', 'f e e a f g'); -- 8 + INSERT INTO tt VALUES('e a e b e e', 'd c c f f f'); -- 9 + INSERT INTO tt VALUES('f a g g c c', 'e g d g c e'); -- 10 + INSERT INTO tt VALUES('c d b a e f', 'f g e h e e'); -- 11 + + CREATE VIRTUAL TABLE tt2 USING fts5(o); + INSERT INTO tt2(rowid, o) SELECT rowid, x||' '||y FROM tt; + INSERT INTO tt2(rowid, o) VALUES(12, 'a b c d e f g h i j k l'); +} + +do_faultsim_test 7.2 -faults oom-* -body { + db eval { SELECT rowid FROM tt WHERE tt MATCH 'f+g+e+g+e+e' } +} -test { + faultsim_test_result {0 6} {1 SQLITE_NOMEM} +} + +do_faultsim_test 7.3 -faults oom-* -body { + db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d e f)' } +} -test { + faultsim_test_result {0 11} {1 SQLITE_NOMEM} +} + +do_faultsim_test 7.4 -faults oom-t* -body { + db eval { SELECT rowid FROM tt2 WHERE tt2 MATCH '"g c f c e f e e a f"' } +} -test { + faultsim_test_result {0 8} {1 SQLITE_NOMEM} +} + +do_faultsim_test 7.5 -faults oom-* -body { + db eval {SELECT rowid FROM tt2 WHERE tt2 MATCH 'NEAR(a b c d e f g h i j k)'} +} -test { + faultsim_test_result {0 12} {1 SQLITE_NOMEM} +} + +do_faultsim_test 7.6 -faults oom-* -body { + db eval {SELECT rowid FROM tt WHERE tt MATCH 'y: "c c"'} +} -test { + faultsim_test_result {0 {1 9}} {1 SQLITE_NOMEM} +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE tt USING fts5(x); + INSERT INTO tt(tt, rank) VALUES('pgsz', 32); + BEGIN; + INSERT INTO tt(rowid, x) VALUES(1, 'a b c d x x'); + WITH ii(i) AS (SELECT 2 UNION ALL SELECT i+1 FROM ii WHERE i<99) + INSERT INTO tt(rowid, x) SELECT i, 'a b c x x d' FROM ii; + INSERT INTO tt(rowid, x) VALUES(100, 'a b c d x x'); + COMMIT; +} + +do_faultsim_test 8.1 -faults oom-t* -body { + db eval { SELECT rowid FROM tt WHERE tt MATCH 'NEAR(a b c d, 2)' } +} -test { + faultsim_test_result {0 {1 100}} {1 SQLITE_NOMEM} +} + +do_faultsim_test 8.2 -faults oom-t* -body { + db eval { SELECT count(*) FROM tt WHERE tt MATCH 'a OR d' } +} -test { + faultsim_test_result {0 100} {1 SQLITE_NOMEM} +} + + +#------------------------------------------------------------------------- +# Fault in NOT query. +# +reset_db +do_execsql_test 9.0 { + CREATE VIRTUAL TABLE tt USING fts5(x); + INSERT INTO tt(tt, rank) VALUES('pgsz', 32); + BEGIN; + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<200) + INSERT INTO tt(rowid, x) + SELECT i, CASE WHEN (i%50)==0 THEN 'a a a a a a' ELSE 'a x a x a x' END + FROM ii; + COMMIT; +} + +do_faultsim_test 9.1 -faults oom-* -body { + db eval { SELECT rowid FROM tt WHERE tt MATCH 'a NOT x' } +} -test { + faultsim_test_result {0 {50 100 150 200}} {1 SQLITE_NOMEM} +} + +#------------------------------------------------------------------------- +# OOM in fts5_expr() SQL function. +# +do_faultsim_test 10.1 -faults oom-t* -body { + db one { SELECT fts5_expr('a AND b NEAR(a b)') } +} -test { + faultsim_test_result {0 {"a" AND "b" AND NEAR("a" "b", 10)}} +} + +do_faultsim_test 10.2 -faults oom-t* -body { + db one { SELECT fts5_expr_tcl('x:"a b c" AND b NEAR(a b)', 'ns', 'x') } +} -test { + set res {AND [ns -col 0 -- {a b c}] [ns -- {b}] [ns -near 10 -- {a} {b}]} + faultsim_test_result [list 0 $res] +} + +do_faultsim_test 10.3 -faults oom-t* -body { + db one { SELECT fts5_expr('x:a', 'x') } +} -test { + faultsim_test_result {0 {x : "a"}} +} + +#------------------------------------------------------------------------- +# OOM while configuring 'rank' option. +# +reset_db +do_execsql_test 11.0 { + CREATE VIRTUAL TABLE ft USING fts5(x); +} +do_faultsim_test 11.1 -faults oom-t* -body { + db eval { INSERT INTO ft(ft, rank) VALUES('rank', 'bm25(10.0, 5.0)') } +} -test { + faultsim_test_result {0 {}} {1 {disk I/O error}} +} + +#------------------------------------------------------------------------- +# OOM while creating an fts5vocab table. +# +reset_db +do_execsql_test 12.0 { + CREATE VIRTUAL TABLE ft USING fts5(x); +} +faultsim_save_and_close +do_faultsim_test 12.1 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval { SELECT * FROM sqlite_master } +} -body { + db eval { CREATE VIRTUAL TABLE vv USING fts5vocab(ft, 'row') } +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +# OOM while querying an fts5vocab table. +# +reset_db +do_execsql_test 13.0 { + CREATE VIRTUAL TABLE ft USING fts5(x); + INSERT INTO ft VALUES('a b'); + CREATE VIRTUAL TABLE vv USING fts5vocab(ft, 'row'); +} +faultsim_save_and_close +do_faultsim_test 13.1 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval { SELECT * FROM vv } +} -body { + db eval { SELECT * FROM vv } +} -test { + faultsim_test_result {0 {a 1 1 b 1 1}} +} + +#------------------------------------------------------------------------- +# OOM in multi-column token query. +# +reset_db +do_execsql_test 13.0 { + CREATE VIRTUAL TABLE ft USING fts5(x, y, z); + INSERT INTO ft(ft, rank) VALUES('pgsz', 32); + INSERT INTO ft VALUES( + 'x x x x x x x x x x x x x x x x', + 'y y y y y y y y y y y y y y y y', + 'z z z z z z z z x x x x x x x x' + ); + INSERT INTO ft SELECT * FROM ft; + INSERT INTO ft SELECT * FROM ft; + INSERT INTO ft SELECT * FROM ft; + INSERT INTO ft SELECT * FROM ft; +} +faultsim_save_and_close +do_faultsim_test 13.1 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval { SELECT * FROM ft } +} -body { + db eval { SELECT rowid FROM ft WHERE ft MATCH '{x z}: x' } +} -test { + faultsim_test_result {0 {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}} +} + +#------------------------------------------------------------------------- +# OOM in an "ALTER TABLE RENAME TO" +# +reset_db +do_execsql_test 14.0 { + CREATE VIRTUAL TABLE "tbl one" USING fts5(x, y, z); +} +faultsim_save_and_close +do_faultsim_test 14.1 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval { SELECT * FROM "tbl one" } +} -body { + db eval { ALTER TABLE "tbl one" RENAME TO "tbl two" } +} -test { + faultsim_test_result {0 {}} +} + +finish_test + diff --git a/ext/fts5/test/fts5fault5.test b/ext/fts5/test/fts5fault5.test new file mode 100644 index 0000000..75b7d9a --- /dev/null +++ b/ext/fts5/test/fts5fault5.test @@ -0,0 +1,133 @@ +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5fault5 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# OOM while creating an FTS5 table. +# +do_faultsim_test 1.1 -faults oom-t* -prep { + db eval { DROP TABLE IF EXISTS abc } +} -body { + db eval { CREATE VIRTUAL TABLE abc USING fts5(x,y) } +} -test { + faultsim_test_result {0 {}} +} + + +#------------------------------------------------------------------------- +# OOM while writing a multi-tier doclist-index. And while running +# integrity-check on the same. +# +reset_db +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE tt USING fts5(x); + INSERT INTO tt(tt, rank) VALUES('pgsz', 32); +} +faultsim_save_and_close + +do_faultsim_test 2.1 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval { SELECT * FROM tt } +} -body { + set str [string repeat "abc " 50] + db eval { + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) + INSERT INTO tt(rowid, x) SELECT i, $str FROM ii; + } +} -test { + faultsim_test_result {0 {}} +} + +do_faultsim_test 2.2 -faults oom-t* -body { + db eval { INSERT INTO tt(tt) VALUES('integrity-check') } +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +# OOM while scanning fts5vocab tables. +# +reset_db +do_test 3.0 { + execsql { + CREATE VIRTUAL TABLE tt USING fts5(x); + CREATE VIRTUAL TABLE tv USING fts5vocab(tt, 'row'); + + CREATE VIRTUAL TABLE tt2 USING fts5(x, detail=col); + CREATE VIRTUAL TABLE tv2 USING fts5vocab(tt2, 'col'); + + INSERT INTO tt(tt, rank) VALUES('pgsz', 32); + INSERT INTO tt2(tt2, rank) VALUES('pgsz', 32); + BEGIN; + } + + for {set i 0} {$i < 20} {incr i} { + set str [string repeat "$i " 50] + execsql { INSERT INTO tt VALUES($str) } + execsql { INSERT INTO tt2 VALUES($str) } + } + execsql COMMIT +} {} + +do_faultsim_test 3.1 -faults oom-t* -body { + db eval { + SELECT term FROM tv; + } +} -test { + faultsim_test_result {0 {0 1 10 11 12 13 14 15 16 17 18 19 2 3 4 5 6 7 8 9}} +} + +do_faultsim_test 3.2 -faults oom-t* -body { + db eval { + SELECT term FROM tv WHERE term BETWEEN '1' AND '2'; + } +} -test { + faultsim_test_result {0 {1 10 11 12 13 14 15 16 17 18 19 2}} +} + +breakpoint +do_execsql_test 3.3.0 { + SELECT * FROM tv2; +} { + 0 x 1 {} 1 x 1 {} 10 x 1 {} 11 x 1 {} 12 x 1 {} 13 x 1 {} + 14 x 1 {} 15 x 1 {} 16 x 1 {} 17 x 1 {} 18 x 1 {} 19 x 1 {} + 2 x 1 {} 3 x 1 {} 4 x 1 {} 5 x 1 {} 6 x 1 {} 7 x 1 {} 8 x 1 {} + 9 x 1 {} +} +do_faultsim_test 3.3 -faults oom-t* -body { + db eval { + SELECT * FROM tv2; + } +} -test { + faultsim_test_result [list 0 [list \ + 0 x 1 {} 1 x 1 {} 10 x 1 {} 11 x 1 {} 12 x 1 {} 13 x 1 {} \ + 14 x 1 {} 15 x 1 {} 16 x 1 {} 17 x 1 {} 18 x 1 {} 19 x 1 {} \ + 2 x 1 {} 3 x 1 {} 4 x 1 {} 5 x 1 {} 6 x 1 {} 7 x 1 {} 8 x 1 {} \ + 9 x 1 {} + ]] +} + + + +finish_test + diff --git a/ext/fts5/test/fts5fault6.test b/ext/fts5/test/fts5fault6.test new file mode 100644 index 0000000..118761f --- /dev/null +++ b/ext/fts5/test/fts5fault6.test @@ -0,0 +1,295 @@ +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5fault6 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + + +#------------------------------------------------------------------------- +# OOM while rebuilding an FTS5 table. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE tt USING fts5(a, b); + INSERT INTO tt VALUES('c d c g g f', 'a a a d g a'); + INSERT INTO tt VALUES('c d g b f d', 'b g e c g c'); + INSERT INTO tt VALUES('c c f d e d', 'c e g d b c'); + INSERT INTO tt VALUES('e a f c e f', 'g b a c d g'); + INSERT INTO tt VALUES('c g f b b d', 'g c d c f g'); + INSERT INTO tt VALUES('d a g a b b', 'g c g g c e'); + INSERT INTO tt VALUES('e f a b c e', 'f d c d c c'); + INSERT INTO tt VALUES('e c a g c d', 'b b g f f b'); + INSERT INTO tt VALUES('g b d d e b', 'f f b d a c'); + INSERT INTO tt VALUES('e a d a e d', 'c e a e f g'); +} +faultsim_save_and_close + +do_faultsim_test 1.1 -faults oom-t* -prep { + faultsim_restore_and_reopen +} -body { + db eval { INSERT INTO tt(tt) VALUES('rebuild') } +} -test { + faultsim_test_result {0 {}} +} + +do_faultsim_test 1.2 -faults oom-t* -prep { + faultsim_restore_and_reopen +} -body { + db eval { REPLACE INTO tt(rowid, a, b) VALUES(6, 'x y z', 'l l l'); } +} -test { + faultsim_test_result {0 {}} +} + + +#------------------------------------------------------------------------- +# OOM within a special delete. +# +reset_db +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE tt USING fts5(a, content=""); + INSERT INTO tt VALUES('c d c g g f'); + INSERT INTO tt VALUES('c d g b f d'); + INSERT INTO tt VALUES('c c f d e d'); + INSERT INTO tt VALUES('e a f c e f'); + INSERT INTO tt VALUES('c g f b b d'); + INSERT INTO tt VALUES('d a g a b b'); + INSERT INTO tt VALUES('e f a b c e'); + INSERT INTO tt VALUES('e c a g c d'); + INSERT INTO tt VALUES('g b d d e b'); + INSERT INTO tt VALUES('e a d a e d'); +} +faultsim_save_and_close + +do_faultsim_test 2.1 -faults oom-t* -prep { + faultsim_restore_and_reopen +} -body { + db eval { INSERT INTO tt(tt, rowid, a) VALUES('delete', 3, 'c d g b f d'); } +} -test { + faultsim_test_result {0 {}} +} + +do_faultsim_test 2.2 -faults oom-t* -prep { + faultsim_restore_and_reopen +} -body { + db eval { INSERT INTO tt(tt) VALUES('delete-all') } +} -test { + faultsim_test_result {0 {}} +} + +do_faultsim_test 2.3 -faults oom-t* -prep { + faultsim_restore_and_reopen +} -body { + db eval { INSERT INTO tt VALUES('x y z') } +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +# OOM in the ASCII tokenizer with very large tokens. +# +# Also the unicode tokenizer. +# +set t1 [string repeat wxyz 20] +set t2 [string repeat wxyz 200] +set t3 [string repeat wxyz 2000] +set doc "$t1 $t2 $t3" +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE xyz USING fts5(c, tokenize=ascii, content=""); + CREATE VIRTUAL TABLE xyz2 USING fts5(c, content=""); +} +faultsim_save_and_close + +do_faultsim_test 3.1 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval { SELECT * FROM xyz } +} -body { + db eval { INSERT INTO xyz VALUES($::doc) } +} -test { + faultsim_test_result {0 {}} +} + +do_faultsim_test 3.2 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval { SELECT * FROM xyz2 } +} -body { + db eval { INSERT INTO xyz2 VALUES($::doc) } +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +# OOM while initializing a unicode61 tokenizer. +# +reset_db +faultsim_save_and_close +do_faultsim_test 4.1 -faults oom-t* -prep { + faultsim_restore_and_reopen +} -body { + db eval { + CREATE VIRTUAL TABLE yu USING fts5(x, tokenize="unicode61 separators abc"); + } +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +# +# 5.2.* OOM while running a query that includes synonyms and matchinfo(). +# +# 5.3.* OOM while running a query that returns a row containing instances +# of more than 4 synonyms for a single term. +# +proc mit {blob} { + set scan(littleEndian) i* + set scan(bigEndian) I* + binary scan $blob $scan($::tcl_platform(byteOrder)) r + return $r +} +proc tcl_tokenize {tflags text} { + foreach {w iStart iEnd} [fts5_tokenize_split $text] { + sqlite3_fts5_token $w $iStart $iEnd + if {$tflags=="query" && [string length $w]==1} { + for {set i 2} {$i < 7} {incr i} { + sqlite3_fts5_token -colo [string repeat $w $i] $iStart $iEnd + } + } + } +} +proc tcl_create {args} { return "tcl_tokenize" } +reset_db +sqlite3_fts5_create_tokenizer db tcl tcl_create +db func mit mit +sqlite3_fts5_register_matchinfo db +do_test 5.0 { + execsql { CREATE VIRTUAL TABLE t1 USING fts5(a, tokenize=tcl) } + execsql { INSERT INTO t1(t1, rank) VALUES('pgsz', 32) } + foreach {rowid text} { + 1 {aaaa cc b aaaaa cc aa} + 2 {aa aa bb a bbb} + 3 {bb aaaaa aaaaa b aaaa aaaaa} + 4 {aa a b aaaa aa} + 5 {aa b ccc aaaaa cc} + 6 {aa aaaaa bbbb cc aaa} + 7 {aaaaa aa aa ccccc bb} + 8 {ccc bbbbb ccccc bbb c} + 9 {cccccc bbbb a aaa cccc c} + + 20 {ddd f ddd eeeee fff ffff eeee ddd fff eeeee dddddd eeee} + 21 {fffff eee dddd fffff dd ee ee eeeee eee eeeeee ee dd e} + 22 {fffff d eeee dddd fffff dddddd ffff ddddd eeeee ee eee dddd ddddd} + 23 {ddddd fff ddd eeeee ffff eeee ddd ff ff ffffff eeeeee dddd ffffff} + 24 {eee dd ee dddd dddd eeeeee e eee fff ffff} + 25 {ddddd ffffff dddddd fff ddd ddddd ddd f eeee fff dddd f} + 26 {f ffff fff fff eeeeee dddd d dddddd ddddd eee ff eeeee} + 27 {eee fff dddddd eeeee eeeee dddd ddddd ffff f eeeee eee dddddd ddddd d} + 28 {dd ddddd d ddd d fff d dddd ee dddd ee ddd dddddd dddddd} + 29 {eeee dddd ee dddd eeee dddd dd fffff f ddd eeeee ddd ee} + 30 {ff ffffff eeeeee eeeee eee ffffff ff ffff f fffff eeeee} + 31 {fffff eeeeee dddd eeee eeee eeeeee eee fffff d ddddd ffffff ffff dddddd} + 32 {dddddd fffff ee eeeeee eeee ee fff dddd fff eeee ffffff eeeeee ffffff} + 33 {ddddd eeee dd ffff dddddd fff eeee ddddd ffff eeee ddd} + 34 {ee dddd ddddd dddddd eeee eeeeee f dd ee dddddd ffffff} + 35 {ee dddd dd eeeeee ddddd eee d eeeeee dddddd eee dddd fffff} + 36 {eee ffffff ffffff e fffff eeeee ff dddddd dddddd fff} + 37 {eeeee fffff dddddd dddd ffffff fff f dd ee dd dd eeeee} + 38 {eeeeee ee d ff eeeeee eeeeee eee eeeee ee ffffff dddd eeee dddddd ee} + 39 {eeeeee ddd fffff e dddd ee eee eee ffffff ee f d dddd} + 40 {ffffff dddddd eee ee ffffff eee eeee ddddd ee eeeeee f} + 41 {ddd ddd fff fffff ee fffff f fff ddddd fffff} + 42 {dddd ee ff d f ffffff fff ffffff ff dd dddddd f eeee} + 43 {d dd fff fffff d f fff e dddd ee ee} + 44 {ff ffff eee ddd d dd ffff dddd d eeee d eeeeee} + 45 {eeee f eeeee ee e ffff f ddd e fff} + 46 {ffff d ffff eeee ffff eeeee f ffff ddddd eee} + 47 {dd dd dddddd ddddd fffff dddddd ddd ddddd eeeeee ffff eeee eee ee} + 48 {ffff ffff e dddd ffffff dd dd dddd f fffff} + 49 {ffffff d dddddd ffff eeeee f ffff ffff d dd fffff eeeee} + + 50 {x e} + } { + execsql { INSERT INTO t1(rowid, a) VALUES($rowid, $text) } + } +} {} + +set res [list {*}{ + 1 {3 24 8 2 12 6} + 5 {2 24 8 2 12 6} + 6 {3 24 8 1 12 6} + 7 {3 24 8 1 12 6} + 9 {2 24 8 3 12 6} +}] +do_execsql_test 5.1.1 { + SELECT rowid, mit(matchinfo(t1, 'x')) FROM t1 WHERE t1 MATCH 'a AND c' +} $res +do_execsql_test 5.1.2 { + SELECT count(*) FROM t1 WHERE t1 MATCH 'd e f' +} 29 + +faultsim_save_and_close +do_faultsim_test 5.2 -faults oom* -prep { + faultsim_restore_and_reopen + sqlite3_fts5_create_tokenizer db tcl tcl_create + sqlite3_fts5_register_matchinfo db + db func mit mit +} -body { + db eval { + SELECT rowid, mit(matchinfo(t1, 'x')) FROM t1 WHERE t1 MATCH 'a AND c' + } +} -test { + faultsim_test_result [list 0 $::res] +} + +do_faultsim_test 5.3 -faults oom* -prep { + faultsim_restore_and_reopen + sqlite3_fts5_create_tokenizer db tcl tcl_create +} -body { + db eval { + SELECT count(*) FROM t1 WHERE t1 MATCH 'd AND e AND f' + } +} -test { + faultsim_test_result {0 29} +} + +do_faultsim_test 5.4 -faults oom* -prep { + faultsim_restore_and_reopen + sqlite3_fts5_create_tokenizer db tcl tcl_create +} -body { + db eval { + SELECT count(*) FROM t1 WHERE t1 MATCH 'x + e' + } +} -test { + faultsim_test_result {0 1} +} + +#------------------------------------------------------------------------- +catch { db close } +breakpoint +do_faultsim_test 6 -faults oom* -prep { + sqlite_orig db test.db + sqlite3_db_config_lookaside db 0 0 0 +} -test { + faultsim_test_result {0 {}} {1 {initialization of fts5 failed: }} + if {$testrc==0} { + db eval { CREATE VIRTUAL TABLE temp.t1 USING fts5(x) } + } + db close +} +finish_test + diff --git a/ext/fts5/test/fts5fault7.test b/ext/fts5/test/fts5fault7.test new file mode 100644 index 0000000..a35b19a --- /dev/null +++ b/ext/fts5/test/fts5fault7.test @@ -0,0 +1,119 @@ +# 2015 September 3 +# +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5fault7 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +if 1 { + +#------------------------------------------------------------------------- +# Test fault-injection on a query that uses xColumnSize() on columnsize=0 +# table. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=0); + INSERT INTO t1 VALUES('a b c d e f g'); + INSERT INTO t1 VALUES('a b c d'); + INSERT INTO t1 VALUES('a b c d e f g h i j'); +} + + +fts5_aux_test_functions db +do_faultsim_test 1 -faults oom* -body { + execsql { SELECT fts5_test_columnsize(t1) FROM t1 WHERE t1 MATCH 'b' } +} -test { + faultsim_test_result {0 {7 4 10}} {1 SQLITE_NOMEM} +} + +} + +#------------------------------------------------------------------------- +# Test fault-injection when a segment is promoted. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t2 USING fts5(a); + INSERT INTO t2(t2, rank) VALUES('automerge', 0); + INSERT INTO t2(t2, rank) VALUES('crisismerge', 4); + INSERT INTO t2(t2, rank) VALUES('pgsz', 40); + + INSERT INTO t2 VALUES('a b c'); + INSERT INTO t2 VALUES('d e f'); + INSERT INTO t2 VALUES('f e d'); + INSERT INTO t2 VALUES('c b a'); + + INSERT INTO t2 VALUES('a b c'); + INSERT INTO t2 VALUES('d e f'); + INSERT INTO t2 VALUES('f e d'); + INSERT INTO t2 VALUES('c b a'); +} {} + +faultsim_save_and_close +do_faultsim_test 1 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval { + BEGIN; + INSERT INTO t2 VALUES('c d c g g f'); + INSERT INTO t2 VALUES('c d g b f d'); + INSERT INTO t2 VALUES('c c f d e d'); + INSERT INTO t2 VALUES('e a f c e f'); + INSERT INTO t2 VALUES('c g f b b d'); + INSERT INTO t2 VALUES('d a g a b b'); + INSERT INTO t2 VALUES('e f a b c e'); + INSERT INTO t2 VALUES('e c a g c d'); + INSERT INTO t2 VALUES('g b d d e b'); + INSERT INTO t2 VALUES('e a d a e d'); + } +} -body { + db eval COMMIT +} -test { + faultsim_test_result {0 {}} +} + +#------------------------------------------------------------------------- +# Test fault-injection when a segment is promoted. +# +reset_db +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE xy USING fts5(x); + INSERT INTO xy(rowid, x) VALUES(1, '1 2 3'); + INSERT INTO xy(rowid, x) VALUES(2, '2 3 4'); + INSERT INTO xy(rowid, x) VALUES(3, '3 4 5'); +} +faultsim_save_and_close + +do_faultsim_test 2.1 -faults oom-* -prep { + faultsim_restore_and_reopen +} -body { + db eval { UPDATE OR REPLACE xy SET rowid=3 WHERE rowid = 2 } +} -test { + faultsim_test_result {0 {}} +} + +# Test fault-injection when an empty expression is parsed. +# +do_faultsim_test 2.2 -faults oom-* -body { + db eval { SELECT * FROM xy('""') } +} -test { + faultsim_test_result {0 {}} +} + +finish_test + diff --git a/ext/fts5/test/fts5fault8.test b/ext/fts5/test/fts5fault8.test new file mode 100644 index 0000000..ae58494 --- /dev/null +++ b/ext/fts5/test/fts5fault8.test @@ -0,0 +1,60 @@ +# 2015 September 3 +# +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5fault8 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + + fts5_aux_test_functions db + do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t1 VALUES('a b c d', '1 2 3 4'); + INSERT INTO t1 VALUES('a b a b', NULL); + INSERT INTO t1 VALUES(NULL, '1 2 1 2'); + } + + do_faultsim_test 1 -faults oom-* -body { + execsql { + SELECT rowid, fts5_test_poslist(t1) FROM t1 WHERE t1 MATCH 'b OR 2' + } + } -test { + faultsim_test_result {0 {1 {0.0.1 1.1.1} 2 {0.0.1 0.0.3} 3 {1.1.1 1.1.3}}} \ + {1 SQLITE_NOMEM} + } + + do_faultsim_test 2 -faults oom-* -body { + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } + } -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + } + + if {[detail_is_none]==0} { + do_faultsim_test 3 -faults oom-* -body { + execsql { SELECT rowid FROM t1('b:2') } + } -test { + faultsim_test_result {0 {1 3}} {1 SQLITE_NOMEM} + } + } +} ;# foreach_detail_mode... + +finish_test + diff --git a/ext/fts5/test/fts5fault9.test b/ext/fts5/test/fts5fault9.test new file mode 100644 index 0000000..908a91d --- /dev/null +++ b/ext/fts5/test/fts5fault9.test @@ -0,0 +1,156 @@ +# 2015 September 3 +# +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5fault9 + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +fts5_aux_test_functions db + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + WITH seq(s) AS ( SELECT 1 UNION ALL SELECT s+1 FROM seq WHERE s<50) + INSERT INTO t1 SELECT 'x x x y y y', 'a b c d e f' FROM seq; +} + +do_faultsim_test 1 -faults oom-* -body { + execsql { SELECT count(*) FROM t1('x AND y') } +} -test { + faultsim_test_result {0 50} +} + +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t2 USING fts5(a, b, detail=%DETAIL%); + INSERT INTO t2(t2, rank) VALUES('pgsz', 32); + INSERT INTO t2 VALUES('abc cba', 'cba abc'); + INSERT INTO t2 VALUES('abc cba', 'cba abc'); + INSERT INTO t2 VALUES('abc cba', 'cba abc'); + + INSERT INTO t2 VALUES('axy cyx', 'cyx axy'); + INSERT INTO t2 VALUES('axy cyx', 'cyx axy'); + INSERT INTO t2 VALUES('axy cyx', 'cyx axy'); +} + +do_faultsim_test 2 -faults oom-* -body { + execsql { SELECT count(*) FROM t2('a* AND c*') } +} -test { + faultsim_test_result {0 6} +} + + +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t3 USING fts5(a, detail=%DETAIL%); + INSERT INTO t3 VALUES('a x x a x a a a'); + INSERT INTO t3 VALUES('x a a x a x x x'); +} + +do_faultsim_test 3.1 -faults oom-* -body { + execsql { SELECT highlight(t3, 0, '[', ']') FROM t3('a') } +} -test { + faultsim_test_result {0 {{[a] x x [a] x [a] [a] [a]} {x [a] [a] x [a] x x x}}} +} + +do_faultsim_test 3.2 -faults oom-t* -body { + execsql { SELECT fts5_test_poslist2(t3) FROM t3('x') } +} -test { + faultsim_test_result \ + {0 {{0.0.1 0.0.2 0.0.4} {0.0.0 0.0.3 0.0.5 0.0.6 0.0.7}}} \ + {1 SQLITE_NOMEM} +} + +#------------------------------------------------------------------------- +# Test OOM injection with the xPhraseFirstColumn() API and a tokenizer +# uses query synonyms. +# +fts5_tclnum_register db +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE t4 USING fts5(x, y, z, detail=%DETAIL%, tokenize=tclnum); + INSERT INTO t4 VALUES('one two three', '1 2 3', 'i ii iii'); + INSERT INTO t4 VALUES('1 2 3', 'i ii iii', 'one two three'); + INSERT INTO t4 VALUES('i ii iii', 'one two three', 'i ii iii'); + + INSERT INTO t4 VALUES('a1 a2 a3', 'a4 a5 a6', 'a7 a8 a9'); + INSERT INTO t4 VALUES('b1 b2 b3', 'b4 b5 b6', 'b7 b8 b9'); + INSERT INTO t4 VALUES('c1 c2 c3', 'c4 c5 c6', 'c7 c8 c9'); +} + +do_faultsim_test 4.1 -faults oom-t* -body { + execsql { SELECT rowid, fts5_test_collist(t4) FROM t4('2') } +} -test { + faultsim_test_result \ + {0 {1 {0.0 0.1 0.2} 2 {0.0 0.1 0.2} 3 {0.0 0.1 0.2}}} {1 SQLITE_NOMEM} +} + +do_faultsim_test 4.2 -faults oom-t* -body { + execsql { SELECT rowid, fts5_test_collist(t4) FROM t4('a5 OR b5 OR c5') } +} -test { + faultsim_test_result \ + {0 {4 {0.0 0.1 0.2} 5 {1.0 1.1 1.2} 6 {2.0 2.1 2.2}}} {1 SQLITE_NOMEM} +} + + +#------------------------------------------------------------------------- +# An OOM within an "ORDER BY rank" query. +# +db func rnddoc fts5_rnddoc +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE xx USING fts5(x, y, detail=%DETAIL%); + INSERT INTO xx VALUES ('def', 'abc ' || rnddoc(10)); + INSERT INTO xx VALUES ('def', 'abc abc' || rnddoc(9)); + INSERT INTO xx VALUES ('def', 'abc abc abc' || rnddoc(8)); +} {} +faultsim_save_and_close + +do_faultsim_test 5 -faults oom-* -prep { + faultsim_restore_and_reopen + execsql { SELECT * FROM xx } +} -body { + execsql { SELECT rowid FROM xx('abc AND def') ORDER BY rank } +} -test { + faultsim_test_result [list 0 {3 2 1}] +} + +set doc [string repeat "xyz " 500] +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE yy USING fts5(y, detail=%DETAIL%); + INSERT INTO yy(yy, rank) VALUES('pgsz', 64); + INSERT INTO yy VALUES ($doc); + INSERT INTO yy VALUES ('1 2 3'); + INSERT INTO yy VALUES ('xyz'); + UPDATE yy SET y = y WHERE rowid = 1; + UPDATE yy SET y = y WHERE rowid = 1; + UPDATE yy SET y = y WHERE rowid = 1; + UPDATE yy SET y = y WHERE rowid = 1; +} {} + +do_faultsim_test 6 -faults oom-* -body { + execsql { SELECT rowid FROM yy('xyz') } +} -test { + faultsim_test_result [list 0 {1 3}] +} + + +} ;# foreach_detail_mode... + +finish_test + diff --git a/ext/fts5/test/fts5faultA.test b/ext/fts5/test/fts5faultA.test new file mode 100644 index 0000000..817ccb4 --- /dev/null +++ b/ext/fts5/test/fts5faultA.test @@ -0,0 +1,64 @@ +# 2016 February 2 +# +# 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 is focused on OOM errors. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +source $testdir/malloc_common.tcl +set testprefix fts5faultA + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + do_execsql_test 1.0 { + CREATE VIRTUAL TABLE o1 USING fts5(a, detail=%DETAIL%); + INSERT INTO o1(o1, rank) VALUES('pgsz', 32); + + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 ) + INSERT INTO o1 SELECT 'A B C' FROM s; + + INSERT INTO o1 VALUES('A X C'); + + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 ) + INSERT INTO o1 SELECT 'A B C' FROM s; + } + + do_faultsim_test 1 -faults oom* -prep { + sqlite3 db test.db + } -body { + execsql { SELECT rowid FROM o1('a NOT b') } + } -test { + faultsim_test_result {0 301} + } +} + +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE o2 USING fts5(a); + + INSERT INTO o2 VALUES('A B C'); + WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<300 ) + INSERT INTO o2 SELECT group_concat('A B C ') FROM s; +} + +do_faultsim_test 2 -faults oom* -prep { + sqlite3 db test.db +} -body { + execsql { SELECT rowid FROM o2('a+b+c NOT xyz') } +} -test { + faultsim_test_result {0 {1 2}} +} +finish_test + diff --git a/ext/fts5/test/fts5full.test b/ext/fts5/test/fts5full.test new file mode 100644 index 0000000..c640f56 --- /dev/null +++ b/ext/fts5/test/fts5full.test @@ -0,0 +1,43 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Test that SQLITE_FULL is returned if the FTS5 table cannot find a free +# segid to use. In practice this can only really happen when automerge and +# crisismerge are both disabled. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5full + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE x8 USING fts5(i); + INSERT INTO x8(x8, rank) VALUES('automerge', 0); + INSERT INTO x8(x8, rank) VALUES('crisismerge', 100000); +} + +db func rnddoc fts5_rnddoc +do_test 1.1 { + list [catch { + for {set i 0} {$i < 2500} {incr i} { + execsql { INSERT INTO x8 VALUES( rnddoc(5) ); } + } + } msg] $msg +} {1 {database or disk is full}} + + +finish_test + diff --git a/ext/fts5/test/fts5hash.test b/ext/fts5/test/fts5hash.test new file mode 100644 index 0000000..f3952d6 --- /dev/null +++ b/ext/fts5/test/fts5hash.test @@ -0,0 +1,133 @@ +# 2015 April 21 +# +# 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 tests in this file are focused on the code in fts5_hash.c. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5hash + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +#------------------------------------------------------------------------- +# Return a list of tokens (a vocabulary) that all share the same hash +# key value. This can be used to test hash collisions. +# +proc build_vocab1 {args} { + + set O(-nslot) 1024 + set O(-nword) 20 + set O(-hash) 88 + set O(-prefix) "" + + if {[llength $args] % 2} { error "bad args" } + array set O2 $args + foreach {k v} $args { + if {[info exists O($k)]==0} { error "bad option: $k" } + set O($k) $v + } + + set L [list] + while {[llength $L] < $O(-nword)} { + set t "$O(-prefix)[random_token]" + set h [sqlite3_fts5_token_hash $O(-nslot) $t] + if {$O(-hash)==$h} { lappend L $t } + } + return $L +} + +proc random_token {} { + set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] + set iVal [expr int(rand() * 2000000)] + return [string map $map $iVal] +} + +proc random_doc {vocab nWord} { + set doc "" + set nVocab [llength $vocab] + for {set i 0} {$i<$nWord} {incr i} { + set j [expr {int(rand() * $nVocab)}] + lappend doc [lindex $vocab $j] + } + return $doc +} + +foreach_detail_mode $testprefix { + + set vocab [build_vocab1] + db func r random_doc + + do_execsql_test 1.0 { + CREATE VIRTUAL TABLE eee USING fts5(e, ee, detail=%DETAIL%); + BEGIN; + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) + INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii; + INSERT INTO eee(eee) VALUES('integrity-check'); + COMMIT; + INSERT INTO eee(eee) VALUES('integrity-check'); + } + + set hash [sqlite3_fts5_token_hash 1024 xyz] + set vocab [build_vocab1 -prefix xyz -hash $hash] + lappend vocab xyz + + do_execsql_test 1.1 { + CREATE VIRTUAL TABLE vocab USING fts5vocab(eee, 'row'); + BEGIN; + } + do_test 1.2 { + for {set i 1} {$i <= 100} {incr i} { + execsql { INSERT INTO eee VALUES( r($vocab, 5), r($vocab, 7) ) } + } + } {} + + do_test 1.3 { + db eval { SELECT term, doc FROM vocab } { + set nRow [db one {SELECT count(*) FROM eee WHERE eee MATCH $term}] + if {$nRow != $doc} { + error "term=$term fts5vocab=$doc cnt=$nRow" + } + } + set {} {} + } {} + + do_execsql_test 1.4 { + COMMIT; + INSERT INTO eee(eee) VALUES('integrity-check'); + } + + #----------------------------------------------------------------------- + # Add a small and very large token with the same hash value to an + # empty table. At one point this would provoke an asan error. + # + do_test 2.0 { + set big [string repeat 12345 40] + set hash [sqlite3_fts5_token_hash 1024 $big] + while {1} { + set small [random_token] + if {[sqlite3_fts5_token_hash 1024 $small]==$hash} break + } + + execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) } +breakpoint + execsql { + INSERT INTO t2 VALUES($small || ' ' || $big); + } + } {} + +} ;# foreach_detail_mode + +finish_test + diff --git a/ext/fts5/test/fts5integrity.test b/ext/fts5/test/fts5integrity.test new file mode 100644 index 0000000..37ca933 --- /dev/null +++ b/ext/fts5/test/fts5integrity.test @@ -0,0 +1,213 @@ +# 2015 Jan 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 file contains tests focused on the integrity-check procedure. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5integrity + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE xx USING fts5(x); + INSERT INTO xx VALUES('term'); +} +do_execsql_test 1.1 { + INSERT INTO xx(xx) VALUES('integrity-check'); +} + +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE yy USING fts5(x, prefix=1); + INSERT INTO yy VALUES('term'); +} +do_execsql_test 2.1 { + INSERT INTO yy(yy) VALUES('integrity-check'); +} + +#-------------------------------------------------------------------- +# +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE zz USING fts5(z); + INSERT INTO zz(zz, rank) VALUES('pgsz', 32); + INSERT INTO zz VALUES('b b b b b b b b b b b b b b'); + INSERT INTO zz SELECT z FROM zz; + INSERT INTO zz SELECT z FROM zz; + INSERT INTO zz SELECT z FROM zz; + INSERT INTO zz SELECT z FROM zz; + INSERT INTO zz SELECT z FROM zz; + INSERT INTO zz SELECT z FROM zz; + INSERT INTO zz(zz) VALUES('optimize'); +} + +do_execsql_test 3.1 { INSERT INTO zz(zz) VALUES('integrity-check'); } + +#-------------------------------------------------------------------- +# Mess around with a docsize record. And the averages record. Then +# check that integrity-check picks it up. +# +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE aa USING fts5(zz); + INSERT INTO aa(zz) VALUES('a b c d e'); + INSERT INTO aa(zz) VALUES('a b c d'); + INSERT INTO aa(zz) VALUES('a b c'); + INSERT INTO aa(zz) VALUES('a b'); + INSERT INTO aa(zz) VALUES('a'); + SELECT length(sz) FROM aa_docsize; +} {1 1 1 1 1} +do_execsql_test 4.1 { + INSERT INTO aa(aa) VALUES('integrity-check'); +} + +do_catchsql_test 4.2 { + BEGIN; + UPDATE aa_docsize SET sz = X'44' WHERE rowid = 3; + INSERT INTO aa(aa) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +do_catchsql_test 4.3 { + ROLLBACK; + BEGIN; + UPDATE aa_data SET block = X'44' WHERE rowid = 1; + INSERT INTO aa(aa) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +do_catchsql_test 4.4 { + ROLLBACK; + BEGIN; + INSERT INTO aa_docsize VALUES(23, X'04'); + INSERT INTO aa(aa) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +do_catchsql_test 4.5 { + ROLLBACK; + BEGIN; + INSERT INTO aa_docsize VALUES(23, X'00'); + INSERT INTO aa_content VALUES(23, ''); + INSERT INTO aa(aa) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM zz_data} {puts $r} +#exit + +execsql { ROLLBACK } + + +#------------------------------------------------------------------------- +# Test that integrity-check works on a reasonably large db with many +# different terms. + +# Document generator command. +proc rnddoc {n} { + set doc [list] + for {set i 0} {$i<$n} {incr i} { + lappend doc [format %.5d [expr int(rand()*10000)]] + } + return $doc +} +db func rnddoc rnddoc + +expr srand(0) +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE gg USING fts5(a, prefix="1,2,3"); + INSERT INTO gg(gg, rank) VALUES('pgsz', 256); + INSERT INTO gg VALUES(rnddoc(20)); + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; + INSERT INTO gg SELECT rnddoc(20) FROM gg; +} + +do_execsql_test 5.1 { + INSERT INTO gg(gg) VALUES('integrity-check'); +} + +do_execsql_test 5.2 { + INSERT INTO gg(gg) VALUES('optimize'); +} + +do_execsql_test 5.3 { + INSERT INTO gg(gg) VALUES('integrity-check'); +} + +do_test 5.4.1 { + set ok 0 + for {set i 0} {$i < 10000} {incr i} { + set T [format %.5d $i] + set res [db eval { SELECT rowid FROM gg($T) ORDER BY rowid ASC }] + set res2 [db eval { SELECT rowid FROM gg($T) ORDER BY rowid DESC }] + if {$res == [lsort -integer $res2]} { incr ok } + } + set ok +} {10000} + +do_test 5.4.2 { + set ok 0 + for {set i 0} {$i < 100} {incr i} { + set T "[format %.3d $i]*" + set res [db eval { SELECT rowid FROM gg($T) ORDER BY rowid ASC }] + set res2 [db eval { SELECT rowid FROM gg($T) ORDER BY rowid DESC }] + if {$res == [lsort -integer $res2]} { incr ok } + } + set ok +} {100} + +#------------------------------------------------------------------------- +# Similar to 5.*. +# +foreach {tn pgsz} { + 1 32 + 2 36 + 3 40 + 4 44 + 5 48 +} { + do_execsql_test 6.$tn.1 { + DROP TABLE IF EXISTS hh; + CREATE VIRTUAL TABLE hh USING fts5(y); + INSERT INTO hh(hh, rank) VALUES('pgsz', $pgsz); + + WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999) + INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1) + FROM s; + + WITH s(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM s WHERE i<999) + INSERT INTO hh SELECT printf("%.3d%.3d%.3d %.3d%.3d%.3d",i,i,i,i+1,i+1,i+1) + FROM s; + + INSERT INTO hh(hh) VALUES('optimize'); + } + + do_test 6.$tn.2 { + set ok 0 + for {set i 0} {$i < 1000} {incr i} { + set T [format %.3d%.3d%.3d $i $i $i] + set res [db eval { SELECT rowid FROM hh($T) ORDER BY rowid ASC }] + set res2 [db eval { SELECT rowid FROM hh($T) ORDER BY rowid DESC }] + if {$res == [lsort -integer $res2]} { incr ok } + } + set ok + } {1000} +} + +finish_test + diff --git a/ext/fts5/test/fts5matchinfo.test b/ext/fts5/test/fts5matchinfo.test new file mode 100644 index 0000000..06f4550 --- /dev/null +++ b/ext/fts5/test/fts5matchinfo.test @@ -0,0 +1,471 @@ +# 2015 August 05 +# +# 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. +# +#*********************************************************************** +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5matchinfo + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { finish_test ; return } + +foreach_detail_mode $testprefix { + +proc mit {blob} { + set scan(littleEndian) i* + set scan(bigEndian) I* + binary scan $blob $scan($::tcl_platform(byteOrder)) r + return $r +} +db func mit mit + +sqlite3_fts5_register_matchinfo db + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(content, detail=%DETAIL%); +} + +do_execsql_test 1.1 { + INSERT INTO t1(content) VALUES('I wandered lonely as a cloud'); + INSERT INTO t1(content) VALUES('That floats on high o''er vales and hills,'); + INSERT INTO t1(content) VALUES('When all at once I saw a crowd,'); + INSERT INTO t1(content) VALUES('A host, of golden daffodils,'); + SELECT mit(matchinfo(t1)) FROM t1 WHERE t1 MATCH 'I'; +} {{1 1 1 2 2} {1 1 1 2 2}} + +# Now create an FTS4 table that does not specify matchinfo=fts3. +# +do_execsql_test 1.2 { + CREATE VIRTUAL TABLE t2 USING fts5(content, detail=%DETAIL%); + INSERT INTO t2 SELECT * FROM t1; + SELECT mit(matchinfo(t2)) FROM t2 WHERE t2 MATCH 'I'; +} {{1 1 1 2 2} {1 1 1 2 2}} + + +#-------------------------------------------------------------------------- +# Proc [do_matchinfo_test] is used to test the FTSX matchinfo() function. +# +# The first argument - $tn - is a test identifier. This may be either a +# full identifier (i.e. "fts3matchinfo-1.1") or, if global var $testprefix +# is set, just the numeric component (i.e. "1.1"). +# +# The second argument is the name of an FTSX table. The third is the +# full text of a WHERE/MATCH expression to query the table for +# (i.e. "t1 MATCH 'abc'"). The final argument - $results - should be a +# key-value list (serialized array) with matchinfo() format specifiers +# as keys, and the results of executing the statement: +# +# SELECT matchinfo($tbl, '$key') FROM $tbl WHERE $expr +# +# For example: +# +# CREATE VIRTUAL TABLE t1 USING fts4; +# INSERT INTO t1 VALUES('abc'); +# INSERT INTO t1 VALUES('def'); +# INSERT INTO t1 VALUES('abc abc'); +# +# do_matchinfo_test 1.1 t1 "t1 MATCH 'abc'" { +# n {3 3} +# p {1 1} +# c {1 1} +# x {{1 3 2} {2 3 2}} +# } +# +# If the $results list contains keys mapped to "-" instead of a matchinfo() +# result, then this command computes the expected results based on other +# mappings to test the matchinfo() function. For example, the command above +# could be changed to: +# +# do_matchinfo_test 1.1 t1 "t1 MATCH 'abc'" { +# n {3 3} p {1 1} c {1 1} x {{1 3 2} {2 3 2}} +# pcx - +# } +# +# And this command would compute the expected results for matchinfo(t1, 'pcx') +# based on the results of matchinfo(t1, 'p'), matchinfo(t1, 'c') and +# matchinfo(t1, 'x') in order to test 'pcx'. +# +proc do_matchinfo_test {tn tbl expr results} { + + foreach {fmt res} $results { + if {$res == "-"} continue + set resarray($fmt) $res + } + + set nRow 0 + foreach {fmt res} [array get resarray] { + if {[llength $res]>$nRow} { set nRow [llength $res] } + } + + # Construct expected results for any formats for which the caller + # supplied result is "-". + # + foreach {fmt res} $results { + if {$res == "-"} { + set res [list] + for {set iRow 0} {$iRow<$nRow} {incr iRow} { + set rowres [list] + foreach c [split $fmt ""] { + set rowres [concat $rowres [lindex $resarray($c) $iRow]] + } + lappend res $rowres + } + set resarray($fmt) $res + } + } + + # Test each matchinfo() request individually. + # + foreach {fmt res} [array get resarray] { + set sql "SELECT mit(matchinfo($tbl, '$fmt')) FROM $tbl WHERE $expr" + do_execsql_test $tn.$fmt $sql [normalize2 $res] + } + + # Test them all executed together (multiple invocations of matchinfo()). + # + set exprlist [list] + foreach {format res} [array get resarray] { + lappend exprlist "mit(matchinfo($tbl, '$format'))" + } + set allres [list] + for {set iRow 0} {$iRow<$nRow} {incr iRow} { + foreach {format res} [array get resarray] { + lappend allres [lindex $res $iRow] + } + } + set sql "SELECT [join $exprlist ,] FROM $tbl WHERE $expr" + do_execsql_test $tn.multi $sql [normalize2 $allres] +} +proc normalize2 {list_of_lists} { + set res [list] + foreach elem $list_of_lists { + lappend res [list {*}$elem] + } + return $res +} + +# Similar to [do_matchinfo_test], except that this is a no-op if the FTS5 +# mode is not detail=full. +# +proc do_matchinfo_p_test {tn tbl expr results} { + if {[detail_is_full]} { + uplevel [list do_matchinfo_test $tn $tbl $expr $results] + } +} + +do_execsql_test 4.1.0 { + CREATE VIRTUAL TABLE t4 USING fts5(x, y, detail=%DETAIL%); + INSERT INTO t4 VALUES('a b c d e', 'f g h i j'); + INSERT INTO t4 VALUES('f g h i j', 'a b c d e'); +} + +do_matchinfo_test 4.1.1 t4 {t4 MATCH 'a b c'} { + s {{3 0} {0 3}} +} + +do_matchinfo_test 4.1.1 t4 {t4 MATCH 'a b c'} { + p {3 3} + x { + {1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1} + {0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1} + } +} + +do_matchinfo_test 4.1.1 t4 {t4 MATCH 'a b c'} { + p {3 3} + c {2 2} + x { + {1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1} + {0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1} + } + n {2 2} + l {{5 5} {5 5}} + a {{5 5} {5 5}} + + s {{3 0} {0 3}} + + xxxxxxxxxxxxxxxxxx - pcx - xpc - ccc - pppxpcpcx - laxnpc - + xpxsscplax - +} + +do_matchinfo_p_test 4.1.2 t4 {t4 MATCH '"g h i"'} { + p {1 1} + c {2 2} + x { + {0 1 1 1 1 1} + {1 1 1 0 1 1} + } + n {2 2} + l {{5 5} {5 5}} + a {{5 5} {5 5}} + + s {{0 1} {1 0}} + + xxxxxxxxxxxxxxxxxx - pcx - xpc - ccc - pppxpcpcx - laxnpc - + sxsxs - +} + +do_matchinfo_test 4.1.3 t4 {t4 MATCH 'a b'} { s {{2 0} {0 2}} } +do_matchinfo_p_test 4.1.4 t4 {t4 MATCH '"a b" c'} { s {{2 0} {0 2}} } +do_matchinfo_p_test 4.1.5 t4 {t4 MATCH 'a "b c"'} { s {{2 0} {0 2}} } +do_matchinfo_test 4.1.6 t4 {t4 MATCH 'd d'} { s {{1 0} {0 1}} } +do_matchinfo_test 4.1.7 t4 {t4 MATCH 'f OR abcd'} { + x { + {0 1 1 1 1 1 0 0 0 0 0 0} + {1 1 1 0 1 1 0 0 0 0 0 0} + } +} +do_matchinfo_test 4.1.8 t4 {t4 MATCH 'f NOT abcd'} { + x { + {0 1 1 1 1 1 0 0 0 0 0 0} + {1 1 1 0 1 1 0 0 0 0 0 0} + } +} + +do_execsql_test 4.2.0 { + CREATE VIRTUAL TABLE t5 USING fts5(content, detail=%DETAIL%); + INSERT INTO t5 VALUES('a a a a a'); + INSERT INTO t5 VALUES('a b a b a'); + INSERT INTO t5 VALUES('c b c b c'); + INSERT INTO t5 VALUES('x x x x x'); +} +do_matchinfo_test 4.2.1 t5 {t5 MATCH 'a a'} { + x {{5 8 2 5 8 2} {3 8 2 3 8 2}} + s {2 1} +} +do_matchinfo_test 4.2.2 t5 {t5 MATCH 'a b'} { s {2} } +do_matchinfo_test 4.2.3 t5 {t5 MATCH 'a b a'} { s {3} } +do_matchinfo_test 4.2.4 t5 {t5 MATCH 'a a a'} { s {3 1} } +do_matchinfo_p_test 4.2.5 t5 {t5 MATCH '"a b" "a b"'} { s {2} } +do_matchinfo_test 4.2.6 t5 {t5 MATCH 'a OR b'} { s {1 2 1} } + +do_execsql_test 4.3.0 "INSERT INTO t5 VALUES('x y [string repeat {b } 50000]')"; + +# It used to be that the second 'a' token would be deferred. That doesn't +# work any longer. +if 0 { + do_matchinfo_test 4.3.1 t5 {t5 MATCH 'a a'} { + x {{5 8 2 5 5 5} {3 8 2 3 5 5}} + s {2 1} + } +} + +do_matchinfo_test 4.3.2 t5 {t5 MATCH 'a b'} { s {2} } +do_matchinfo_test 4.3.3 t5 {t5 MATCH 'a b a'} { s {3} } +do_matchinfo_test 4.3.4 t5 {t5 MATCH 'a a a'} { s {3 1} } +do_matchinfo_p_test 4.3.5 t5 {t5 MATCH '"a b" "a b"'} { s {2} } +do_matchinfo_test 4.3.6 t5 {t5 MATCH 'a OR b'} { s {1 2 1 1} } + +do_execsql_test 4.4.0.1 { INSERT INTO t5(t5) VALUES('optimize') } + +do_matchinfo_test 4.4.2 t5 {t5 MATCH 'a b'} { s {2} } +do_matchinfo_test 4.4.1 t5 {t5 MATCH 'a a'} { s {2 1} } +do_matchinfo_test 4.4.2 t5 {t5 MATCH 'a b'} { s {2} } +do_matchinfo_test 4.4.3 t5 {t5 MATCH 'a b a'} { s {3} } +do_matchinfo_test 4.4.4 t5 {t5 MATCH 'a a a'} { s {3 1} } +do_matchinfo_p_test 4.4.5 t5 {t5 MATCH '"a b" "a b"'} { s {2} } + +do_execsql_test 4.5.0 { + CREATE VIRTUAL TABLE t6 USING fts5(a, b, c, detail=%DETAIL%); + INSERT INTO t6 VALUES('a', 'b', 'c'); +} +do_matchinfo_test 4.5.1 t6 {t6 MATCH 'a b c'} { s {{1 1 1}} } + + +#------------------------------------------------------------------------- +# Test the outcome of matchinfo() when used within a query that does not +# use the full-text index (i.e. lookup by rowid or full-table scan). +# +do_execsql_test 7.1 { + CREATE VIRTUAL TABLE t10 USING fts5(content, detail=%DETAIL%); + INSERT INTO t10 VALUES('first record'); + INSERT INTO t10 VALUES('second record'); +} +do_execsql_test 7.2 { + SELECT typeof(matchinfo(t10)), length(matchinfo(t10)) FROM t10; +} {blob 8 blob 8} +do_execsql_test 7.3 { + SELECT typeof(matchinfo(t10)), length(matchinfo(t10)) FROM t10 WHERE rowid=1; +} {blob 8} +do_execsql_test 7.4 { + SELECT typeof(matchinfo(t10)), length(matchinfo(t10)) + FROM t10 WHERE t10 MATCH 'record' +} {blob 20 blob 20} + +#------------------------------------------------------------------------- +# Test a special case - matchinfo('nxa') with many zero length documents. +# Special because "x" internally uses a statement used by both "n" and "a". +# This was causing a problem at one point in the obscure case where the +# total number of bytes of data stored in an fts3 table was greater than +# the number of rows. i.e. when the following query returns true: +# +# SELECT sum(length(content)) < count(*) FROM fts4table; +# +do_execsql_test 8.1 { + CREATE VIRTUAL TABLE t11 USING fts5(content, detail=%DETAIL%); + INSERT INTO t11(t11, rank) VALUES('pgsz', 32); + INSERT INTO t11 VALUES('quitealongstringoftext'); + INSERT INTO t11 VALUES('anotherquitealongstringoftext'); + INSERT INTO t11 VALUES('athirdlongstringoftext'); + INSERT INTO t11 VALUES('andonemoreforgoodluck'); +} +do_test 8.2 { + for {set i 0} {$i < 200} {incr i} { + execsql { INSERT INTO t11 VALUES('') } + } + execsql { INSERT INTO t11(t11) VALUES('optimize') } +} {} +do_execsql_test 8.3 { + SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' +} {{204 1 3 3 0} {204 1 3 3 0} {204 1 3 3 0}} + +#------------------------------------------------------------------------- + +if {[detail_is_full]} { + do_execsql_test 9.1 { + CREATE VIRTUAL TABLE t12 USING fts5(content, detail=%DETAIL%); + INSERT INTO t12 VALUES('a b c d'); + SELECT mit(matchinfo(t12,'x')) FROM t12 WHERE t12 MATCH 'NEAR(a d, 1) OR a'; + } {{0 1 1 0 1 1 1 1 1}} + do_execsql_test 9.2 { + INSERT INTO t12 VALUES('a d c d'); + SELECT mit(matchinfo(t12,'x')) FROM t12 WHERE t12 MATCH 'NEAR(a d, 1) OR a'; + } { + {0 2 2 0 3 2 1 2 2} {1 2 2 1 3 2 1 2 2} + } + do_execsql_test 9.3 { + INSERT INTO t12 VALUES('a d d a'); + SELECT mit(matchinfo(t12,'x')) FROM t12 WHERE t12 MATCH 'NEAR(a d, 1) OR a'; + } { + {0 4 3 0 5 3 1 4 3} {1 4 3 1 5 3 1 4 3} {2 4 3 2 5 3 2 4 3} + } +} + +#--------------------------------------------------------------------------- +# Test for a memory leak +# +do_execsql_test 10.1 { + DROP TABLE t10; + CREATE VIRTUAL TABLE t10 USING fts5(idx, value, detail=%DETAIL%); + INSERT INTO t10 values (1, 'one'),(2, 'two'),(3, 'three'); + SELECT t10.rowid, t10.* + FROM t10 + JOIN (SELECT 1 AS idx UNION SELECT 2 UNION SELECT 3) AS x + WHERE t10 MATCH x.idx + AND matchinfo(t10) not null + GROUP BY t10.rowid + ORDER BY 1; +} {1 1 one 2 2 two 3 3 three} + +#--------------------------------------------------------------------------- +# Test the 'y' matchinfo flag +# +reset_db +sqlite3_fts5_register_matchinfo db +do_execsql_test 11.0 { + CREATE VIRTUAL TABLE tt USING fts5(x, y, detail=%DETAIL%); + INSERT INTO tt VALUES('c d a c d d', 'e a g b d a'); -- 1 + INSERT INTO tt VALUES('c c g a e b', 'c g d g e c'); -- 2 + INSERT INTO tt VALUES('b e f d e g', 'b a c b c g'); -- 3 + INSERT INTO tt VALUES('a c f f g d', 'd b f d e g'); -- 4 + INSERT INTO tt VALUES('g a c f c f', 'd g g b c c'); -- 5 + INSERT INTO tt VALUES('g a c e b b', 'd b f b g g'); -- 6 + INSERT INTO tt VALUES('f d a a f c', 'e e a d c f'); -- 7 + INSERT INTO tt VALUES('a c b b g f', 'a b a e d f'); -- 8 + INSERT INTO tt VALUES('b a f e c c', 'f d b b a b'); -- 9 + INSERT INTO tt VALUES('f d c e a c', 'f a f a a f'); -- 10 +} + +db func mit mit +foreach {tn expr res} { + 1 "a" { + 1 {1 2} 2 {1 0} 3 {0 1} 4 {1 0} 5 {1 0} + 6 {1 0} 7 {2 1} 8 {1 2} 9 {1 1} 10 {1 3} + } + + 2 "b" { + 1 {0 1} 2 {1 0} 3 {1 2} 4 {0 1} 5 {0 1} + 6 {2 2} 8 {2 1} 9 {1 3} + } + + 3 "y:a" { + 1 {0 2} 3 {0 1} + 7 {0 1} 8 {0 2} 9 {0 1} 10 {0 3} + } + + 4 "x:a" { + 1 {1 0} 2 {1 0} 4 {1 0} 5 {1 0} + 6 {1 0} 7 {2 0} 8 {1 0} 9 {1 0} 10 {1 0} + } + + 5 "a OR b" { + 1 {1 2 0 1} 2 {1 0 1 0} 3 {0 1 1 2} 4 {1 0 0 1} 5 {1 0 0 1} + 6 {1 0 2 2} 7 {2 1 0 0} 8 {1 2 2 1} 9 {1 1 1 3} 10 {1 3 0 0} + } + + 6 "a AND b" { + 1 {1 2 0 1} 2 {1 0 1 0} 3 {0 1 1 2} 4 {1 0 0 1} 5 {1 0 0 1} + 6 {1 0 2 2} 8 {1 2 2 1} 9 {1 1 1 3} + } + + 7 "a OR (a AND b)" { + 1 {1 2 1 2 0 1} 2 {1 0 1 0 1 0} 3 {0 1 0 1 1 2} 4 {1 0 1 0 0 1} + 5 {1 0 1 0 0 1} 6 {1 0 1 0 2 2} 7 {2 1 0 0 0 0} 8 {1 2 1 2 2 1} + 9 {1 1 1 1 1 3} 10 {1 3 0 0 0 0} + } + +} { + + if {[string match *:* $expr] && [detail_is_none]} continue + do_execsql_test 11.1.$tn.1 { + SELECT rowid, mit(matchinfo(tt, 'y')) FROM tt WHERE tt MATCH $expr + } $res + + set r2 [list] + foreach {rowid L} $res { + lappend r2 $rowid + set M [list] + foreach {a b} $L { + lappend M [expr ($a ? 1 : 0) + ($b ? 2 : 0)] + } + lappend r2 $M + } + + do_execsql_test 11.1.$tn.2 { + SELECT rowid, mit(matchinfo(tt, 'b')) FROM tt WHERE tt MATCH $expr + } $r2 + + do_execsql_test 11.1.$tn.2 { + SELECT rowid, mit(matchinfo(tt, 'b')) FROM tt WHERE tt MATCH $expr + } $r2 +} + +#--------------------------------------------------------------------------- +# Test the 'b' matchinfo flag +# +reset_db +sqlite3_fts5_register_matchinfo db +db func mit mit + +do_test 12.0 { + set cols [list] + for {set i 0} {$i < 50} {incr i} { lappend cols "c$i" } + execsql "CREATE VIRTUAL TABLE tt USING fts5([join $cols ,], detail=%DETAIL%)" +} {} + +do_execsql_test 12.1 { + INSERT INTO tt (rowid, c4, c45) VALUES(1, 'abc', 'abc'); + SELECT mit(matchinfo(tt, 'b')) FROM tt WHERE tt MATCH 'abc'; +} [list [list [expr 1<<4] [expr 1<<(45-32)]]] + +} ;# foreach_detail_mode + +finish_test + diff --git a/ext/fts5/test/fts5merge.test b/ext/fts5/test/fts5merge.test new file mode 100644 index 0000000..9dd1ecd --- /dev/null +++ b/ext/fts5/test/fts5merge.test @@ -0,0 +1,194 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Test that focus on incremental merges of segments. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5merge + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +db func repeat [list string repeat] + +#------------------------------------------------------------------------- +# Create an fts index so that: +# +# * the index consists of two top-level segments +# * each segment contains records related to $nRowPerSeg rows +# * all rows consist of tokens "x" and "y" only. +# +# Then run ('merge', 1) until everything is completely merged. +# +proc do_merge1_test {testname nRowPerSeg} { + set ::nRowPerSeg [expr $nRowPerSeg] + do_execsql_test $testname.0 { + DROP TABLE IF EXISTS x8; + CREATE VIRTUAL TABLE x8 USING fts5(i); + INSERT INTO x8(x8, rank) VALUES('pgsz', 32); + + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg) + INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii; + + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg) + INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii; + + INSERT INTO x8(x8, rank) VALUES('automerge', 2); + } + + for {set tn 1} {[lindex [fts5_level_segs x8] 0]>0} {incr tn} { + do_execsql_test $testname.$tn { + INSERT INTO x8(x8, rank) VALUES('merge', 1); + INSERT INTO x8(x8) VALUES('integrity-check'); + } + if {$tn>5} break + } + + do_test $testname.x [list expr "$tn < 5"] 1 +} + +do_merge1_test 1.1 1 +do_merge1_test 1.2 2 +do_merge1_test 1.3 3 +do_merge1_test 1.4 4 +do_merge1_test 1.5 10 +do_merge1_test 1.6 20 +do_merge1_test 1.7 100 + +#------------------------------------------------------------------------- +# +proc do_merge2_test {testname nRow} { + db func rnddoc fts5_rnddoc + + do_execsql_test $testname.0 { + DROP TABLE IF EXISTS x8; + CREATE VIRTUAL TABLE x8 USING fts5(i); + INSERT INTO x8(x8, rank) VALUES('pgsz', 32); + } + + set ::nRow $nRow + do_test $testname.1 { + for {set i 0} {$i < $::nRow} {incr i} { + execsql { INSERT INTO x8 VALUES( rnddoc(($i%16) + 5) ) } + while {[not_merged x8]} { + execsql { + INSERT INTO x8(x8, rank) VALUES('automerge', 2); + INSERT INTO x8(x8, rank) VALUES('merge', 1); + INSERT INTO x8(x8, rank) VALUES('automerge', 16); + INSERT INTO x8(x8) VALUES('integrity-check'); + } + } + } + } {} +} +proc not_merged {tbl} { + set segs [fts5_level_segs $tbl] + foreach s $segs { if {$s>1} { return 1 } } + return 0 +} + +do_merge2_test 2.1 5 +do_merge2_test 2.2 10 +do_merge2_test 2.3 20 + +#------------------------------------------------------------------------- +# Test that an auto-merge will complete any merge that has already been +# started, even if the number of input segments is less than the current +# value of the 'automerge' configuration parameter. +# +db func rnddoc fts5_rnddoc + +do_execsql_test 3.1 { + DROP TABLE IF EXISTS x8; + CREATE VIRTUAL TABLE x8 USING fts5(i); + INSERT INTO x8(x8, rank) VALUES('pgsz', 32); + INSERT INTO x8 VALUES(rnddoc(100)); + INSERT INTO x8 VALUES(rnddoc(100)); +} +do_test 3.2 { + execsql { + INSERT INTO x8(x8, rank) VALUES('automerge', 4); + INSERT INTO x8(x8, rank) VALUES('merge', 1); + } + fts5_level_segs x8 +} {2} + +do_test 3.3 { + execsql { + INSERT INTO x8(x8, rank) VALUES('automerge', 2); + INSERT INTO x8(x8, rank) VALUES('merge', 1); + } + fts5_level_segs x8 +} {2 1} + +do_test 3.4 { + execsql { INSERT INTO x8(x8, rank) VALUES('automerge', 4) } + while {[not_merged x8]} { + execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1) } + } + fts5_level_segs x8 +} {0 1} + +#------------------------------------------------------------------------- +# +proc mydoc {} { + set x [lindex {a b c d e f g h i j} [expr int(rand()*10)]] + return [string repeat "$x " 30] +} +db func mydoc mydoc + +proc mycount {} { + set res [list] + foreach x {a b c d e f g h i j} { + lappend res [db one {SELECT count(*) FROM x8 WHERE x8 MATCH $x}] + } + set res +} + + #1 32 +foreach {tn pgsz} { + 2 1000 +} { + do_execsql_test 4.$tn.1 { + DROP TABLE IF EXISTS x8; + CREATE VIRTUAL TABLE x8 USING fts5(i); + INSERT INTO x8(x8, rank) VALUES('pgsz', $pgsz); + } + + do_execsql_test 4.$tn.2 { + INSERT INTO x8(x8, rank) VALUES('merge', 1); + } + + do_execsql_test 4.$tn.3 { + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) + INSERT INTO x8 SELECT mydoc() FROM ii; + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) + INSERT INTO x8 SELECT mydoc() FROM ii; + INSERT INTO x8(x8, rank) VALUES('automerge', 2); + } + + set expect [mycount] + for {set i 0} {$i < 20} {incr i} { + do_test 4.$tn.4.$i { + execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1); } + mycount + } $expect + break + } +# db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r } +} + +finish_test + diff --git a/ext/fts5/test/fts5merge2.test b/ext/fts5/test/fts5merge2.test new file mode 100644 index 0000000..87dbf14 --- /dev/null +++ b/ext/fts5/test/fts5merge2.test @@ -0,0 +1,59 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Test that focus on incremental merges of segments. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5merge + +proc dump_structure {} { + db eval {SELECT fts5_decode(id, block) AS t FROM t1_data WHERE id=10} { + foreach lvl [lrange $t 1 end] { + set seg [string repeat . [expr [llength $lvl]-2]] + puts "[lrange $lvl 0 1] $seg" + } + } +} + +foreach_detail_mode $testprefix { + +if {[detail_is_none]==0} continue + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + INSERT INTO t1(t1, rank) VALUES('crisismerge', 2); + INSERT INTO t1 VALUES('1 2 3 4'); +} + +expr srand(0) +db func rnddoc fts5_rnddoc +do_test 1.1 { + for {set i 0} {$i < 100} {incr i} { + execsql { + BEGIN; + DELETE FROM t1 WHERE rowid = 1; + INSERT INTO t1(rowid, x) VALUES(1, '1 2 3 4'); + INSERT INTO t1 VALUES(rnddoc(10)); + COMMIT; + } + } +} {} + +do_execsql_test 1.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +} + +finish_test + diff --git a/ext/fts5/test/fts5near.test b/ext/fts5/test/fts5near.test new file mode 100644 index 0000000..b4ae205 --- /dev/null +++ b/ext/fts5/test/fts5near.test @@ -0,0 +1,71 @@ +# 2014 Jan 08 +# +# 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. +# +#*********************************************************************** +# +# Tests focused on the NEAR operator. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5near + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc do_near_test {tn doc near res} { + uplevel [list do_execsql_test $tn " + DELETE FROM t1; + INSERT INTO t1 VALUES('$doc'); + SELECT count(*) FROM t1 WHERE t1 MATCH '$near'; + " $res] +} + +execsql { + CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = "ascii tokenchars '.'") +} + +do_near_test 1.1 ". . a . . . b . ." { NEAR(a b, 5) } 1 +do_near_test 1.2 ". . a . . . b . ." { NEAR(a b, 4) } 1 +do_near_test 1.3 ". . a . . . b . ." { NEAR(a b, 3) } 1 +do_near_test 1.4 ". . a . . . b . ." { NEAR(a b, 2) } 0 + +do_near_test 1.5 ". . a . . . b . ." { NEAR(b a, 5) } 1 +do_near_test 1.6 ". . a . . . b . ." { NEAR(b a, 4) } 1 +do_near_test 1.7 ". . a . . . b . ." { NEAR(b a, 3) } 1 +do_near_test 1.8 ". . a . . . b . ." { NEAR(b a, 2) } 0 + +do_near_test 1.9 ". a b . . . c . ." { NEAR("a b" c, 3) } 1 +do_near_test 1.10 ". a b . . . c . ." { NEAR("a b" c, 2) } 0 +do_near_test 1.11 ". a b . . . c . ." { NEAR(c "a b", 3) } 1 +do_near_test 1.12 ". a b . . . c . ." { NEAR(c "a b", 2) } 0 + +do_near_test 1.13 ". a b . . . c d ." { NEAR(a+b c+d, 3) } 1 +do_near_test 1.14 ". a b . . . c d ." { NEAR(a+b c+d, 2) } 0 +do_near_test 1.15 ". a b . . . c d ." { NEAR(c+d a+b, 3) } 1 +do_near_test 1.16 ". a b . . . c d ." { NEAR(c+d a+b, 2) } 0 + +do_near_test 1.17 ". a b . . . c d ." { NEAR(a b c d, 5) } 1 +do_near_test 1.18 ". a b . . . c d ." { NEAR(a b c d, 4) } 0 +do_near_test 1.19 ". a b . . . c d ." { NEAR(a+b c d, 4) } 1 + +do_near_test 1.20 "a b c d e f g h i" { NEAR(b+c a+b+c+d i, 5) } 1 +do_near_test 1.21 "a b c d e f g h i" { NEAR(b+c a+b+c+d i, 4) } 0 + +do_near_test 1.22 "a b c d e f g h i" { NEAR(a+b+c+d i b+c, 5) } 1 +do_near_test 1.23 "a b c d e f g h i" { NEAR(a+b+c+d i b+c, 4) } 0 + +do_near_test 1.24 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 5) } 1 +do_near_test 1.25 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 4) } 0 + + +finish_test + diff --git a/ext/fts5/test/fts5onepass.test b/ext/fts5/test/fts5onepass.test new file mode 100644 index 0000000..a614b78 --- /dev/null +++ b/ext/fts5/test/fts5onepass.test @@ -0,0 +1,181 @@ +# 2015 Sep 27 +# +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5onepass + +# If SQLITE_ENABLE_FTS3 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE ft USING fts5(content); + INSERT INTO ft(rowid, content) VALUES(1, '1 2 3'); + INSERT INTO ft(rowid, content) VALUES(2, '4 5 6'); + INSERT INTO ft(rowid, content) VALUES(3, '7 8 9'); +} + +#------------------------------------------------------------------------- +# Check that UPDATE and DELETE statements that feature "WHERE rowid=?" or +# or "WHERE rowid=?" clauses do not use statement journals. But that other +# DELETE and UPDATE statements do. +# +# Note: "MATCH ? AND rowid=?" does use a statement journal. +# +foreach {tn sql uses} { + 1.1 { DELETE FROM ft } 1 + 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=? } 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=? } 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 +} + +#------------------------------------------------------------------------- +# Check that putting a "DELETE/UPDATE ... WHERE rowid=?" statement in a +# trigger program does not prevent the VM from using a statement +# transaction. Even if the calling statement cannot hit a constraint. +# +do_execsql_test 2.0 { + CREATE TABLE t1(x); + + CREATE TRIGGER t1_ai AFTER INSERT ON t1 BEGIN + DELETE FROM ft WHERE rowid=new.x; + END; + + CREATE TRIGGER t1_ad AFTER DELETE ON t1 BEGIN + UPDATE ft SET content = 'a b c' WHERE rowid=old.x; + END; + + CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 BEGIN + DELETE FROM ft WHERE rowid=old.x; + END; +} + +foreach {tn sql uses} { + 1 { INSERT INTO t1 VALUES(1) } 1 + 2 { DELETE FROM t1 WHERE x=4 } 1 + 3 { UPDATE t1 SET x=10 WHERE x=11 } 1 +} { + do_test 2.$tn { sql_uses_stmt db $sql } $uses +} + +#------------------------------------------------------------------------- +# Test that an "UPDATE ... WHERE rowid=?" works and does not corrupt the +# index when it strikes a constraint. Both inside and outside a +# transaction. +# +foreach {tn tcl1 tcl2} { + 1 {} {} + + 2 { + execsql BEGIN + } { + if {[sqlite3_get_autocommit db]==1} { error "transaction rolled back!" } + execsql COMMIT + } +} { + + do_execsql_test 3.$tn.0 { + DROP TABLE IF EXISTS ft2; + CREATE VIRTUAL TABLE ft2 USING fts5(content); + INSERT INTO ft2(rowid, content) VALUES(1, 'a b c'); + INSERT INTO ft2(rowid, content) VALUES(2, 'a b d'); + INSERT INTO ft2(rowid, content) VALUES(3, 'a b e'); + } + + eval $tcl1 + foreach {tn2 sql content} { + 1 { UPDATE ft2 SET rowid=2 WHERE rowid=1 } + { 1 {a b c} 2 {a b d} 3 {a b e} } + + 2 { + INSERT INTO ft2(rowid, content) VALUES(4, 'a b f'); + UPDATE ft2 SET rowid=5 WHERE rowid=4; + UPDATE ft2 SET rowid=3 WHERE rowid=5; + } { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} } + + 3 { + UPDATE ft2 SET rowid=3 WHERE rowid=4; -- matches 0 rows + UPDATE ft2 SET rowid=2 WHERE rowid=3; + } { 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} } + + 4 { + INSERT INTO ft2(rowid, content) VALUES(4, 'a b g'); + UPDATE ft2 SET rowid=-1 WHERE rowid=4; + UPDATE ft2 SET rowid=3 WHERE rowid=-1; + } {-1 {a b g} 1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} } + + 5 { + DELETE FROM ft2 WHERE rowid=451; + DELETE FROM ft2 WHERE rowid=-1; + UPDATE ft2 SET rowid = 2 WHERE rowid = 1; + } {1 {a b c} 2 {a b d} 3 {a b e} 5 {a b f} } + } { + do_catchsql_test 3.$tn.$tn2.a $sql {1 {constraint failed}} + do_execsql_test 3.$tn.$tn2.b { SELECT rowid, content FROM ft2 } $content + + do_execsql_test 3.$tn.$tn2.c { + INSERT INTO ft2(ft2) VALUES('integrity-check'); + } + } + eval $tcl2 +} + +#------------------------------------------------------------------------- +# Check that DELETE and UPDATE operations can be done without flushing +# the in-memory hash table to disk. +# +reset_db +do_execsql_test 4.1.1 { + CREATE VIRTUAL TABLE ttt USING fts5(x); + BEGIN; + INSERT INTO ttt(rowid, x) VALUES(1, 'a b c'); + INSERT INTO ttt(rowid, x) VALUES(2, 'a b c'); + INSERT INTO ttt(rowid, x) VALUES(3, 'a b c'); + COMMIT +} +do_test 4.1.2 { fts5_level_segs ttt } {1} + +do_execsql_test 4.2.1 { + BEGIN; + DELETE FROM ttt WHERE rowid=1; + DELETE FROM ttt WHERE rowid=3; + INSERT INTO ttt(rowid, x) VALUES(4, 'd e f'); + INSERT INTO ttt(rowid, x) VALUES(5, 'd e f'); + COMMIT; +} {} +do_test 4.2.2 { fts5_level_segs ttt } {2} + + +do_execsql_test 4.3.1 { + BEGIN; + UPDATE ttt SET x = 'd e f' WHERE rowid = 2; + UPDATE ttt SET x = 'A B C' WHERE rowid = 4; + INSERT INTO ttt(rowid, x) VALUES(6, 'd e f'); + COMMIT; +} {} +do_test 4.2.2 { fts5_level_segs ttt } {3} + +finish_test + diff --git a/ext/fts5/test/fts5optimize.test b/ext/fts5/test/fts5optimize.test new file mode 100644 index 0000000..984af8c --- /dev/null +++ b/ext/fts5/test/fts5optimize.test @@ -0,0 +1,66 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5optimize + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc rnddoc {nWord} { + set vocab {a b c d e f g h i j k l m n o p q r s t u v w x y z} + set nVocab [llength $vocab] + set ret [list] + for {set i 0} {$i < $nWord} {incr i} { + lappend ret [lindex $vocab [expr {int(rand() * $nVocab)}]] + } + return $ret +} + + +foreach {tn nStep} { + 1 2 + 2 10 + 3 50 + 4 500 +} { +if {$tn!=4} continue + reset_db + db func rnddoc rnddoc + do_execsql_test 1.$tn.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y); + } + do_test 1.$tn.2 { + for {set i 0} {$i < $nStep} {incr i} { + execsql { INSERT INTO t1 VALUES( rnddoc(5), rnddoc(5) ) } + } + } {} + + do_execsql_test 1.$tn.3 { + INSERT INTO t1(t1) VALUES('integrity-check'); + } + + do_execsql_test 1.$tn.4 { + INSERT INTO t1(t1) VALUES('optimize'); + } + + do_execsql_test 1.$tn.5 { + INSERT INTO t1(t1) VALUES('integrity-check'); + } +} + +finish_test + diff --git a/ext/fts5/test/fts5phrase.test b/ext/fts5/test/fts5phrase.test new file mode 100644 index 0000000..6dac684 --- /dev/null +++ b/ext/fts5/test/fts5phrase.test @@ -0,0 +1,119 @@ +# 2014 Jan 08 +# +# 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. +# +#*********************************************************************** +# +# Tests focused on phrase queries. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5phrase + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t3 USING fts5(a, b, c); + INSERT INTO t3 VALUES('d e a', 'd i j j f', 'i j i e b f h'); -- 1 + INSERT INTO t3 VALUES('g a e', 'f g i g a', 'h d g i g h c'); -- 2 + INSERT INTO t3 VALUES('e a d', 'e i h a f', 'c e h i f b i'); -- 3 + INSERT INTO t3 VALUES('a g c', 'd j d j c', 'c d f j i g j'); -- 4 + INSERT INTO t3 VALUES('b c b', 'j g c d f', 'j c j d g f b'); -- 5 + INSERT INTO t3 VALUES('j a d', 'e b i h h', 'c c f g d i d'); -- 6 + INSERT INTO t3 VALUES('a d f', 'h g i i i', 'e a g c i f b'); -- 7 + INSERT INTO t3 VALUES('g f d', 'f c g b j', 'b b h h h j j'); -- 8 + INSERT INTO t3 VALUES('f h g', 'c j f g j', 'd h d f e b h'); -- 9 + INSERT INTO t3 VALUES('f h d', 'c i a d b', 'g b j b a d e'); -- 10 + INSERT INTO t3 VALUES('j h h', 'j i h a g', 'd e i e a g j'); -- 11 + INSERT INTO t3 VALUES('a b e', 'h g a g c', 'h c a a d e g'); -- 12 + INSERT INTO t3 VALUES('a j g', 'i h i f i', 'a g h j g i b'); -- 13 + INSERT INTO t3 VALUES('j h e', 'f e d i e', 'i d c f e d c'); -- 14 + INSERT INTO t3 VALUES('d j d', 'd b i a c', 'g d h i d b e'); -- 15 + INSERT INTO t3 VALUES('h j e', 'e b b c f', 'j a f g h d j'); -- 16 + INSERT INTO t3 VALUES('c b j', 'c a b a i', 'h f i d a d c'); -- 17 + INSERT INTO t3 VALUES('e e d', 'i d f c c', 'g i d a f e a'); -- 18 + INSERT INTO t3 VALUES('e i g', 'e a b i h', 'i f d d a d f'); -- 19 + INSERT INTO t3 VALUES('h g f', 'b h h j d', 'i f d e g j a'); -- 20 + INSERT INTO t3 VALUES('e h f', 'j c b c f', 'j a j g h a c'); -- 21 + INSERT INTO t3 VALUES('d c h', 'b g i c e', 'i i c d e h i'); -- 22 + INSERT INTO t3 VALUES('a h i', 'a g d f f', 'e f i i b b h'); -- 23 + INSERT INTO t3 VALUES('d d g', 'c c b c g', 'g c h e b c e'); -- 24 + INSERT INTO t3 VALUES('a b b', 'b f a d i', 'd a h a b c i'); -- 25 + INSERT INTO t3 VALUES('a f d', 'a j e a h', 'j i h j a i f'); -- 26 + INSERT INTO t3 VALUES('d j d', 'h a d i a', 'h h f j h g a'); -- 27 + INSERT INTO t3 VALUES('g a e', 'd g f a g', 'i d b c g g j'); -- 28 + INSERT INTO t3 VALUES('j e h', 'g h j h g', 'd a e j a a h'); -- 29 + INSERT INTO t3 VALUES('e j e', 'g e j g c', 'f c e b e e a'); -- 30 + INSERT INTO t3 VALUES('h f f', 'i j g e c', 'j j f c a i j'); -- 31 + INSERT INTO t3 VALUES('a g c', 'c g d b i', 'g h c b a a f'); -- 32 + INSERT INTO t3 VALUES('c h i', 'j d h e e', 'a h i d c c j'); -- 33 + INSERT INTO t3 VALUES('d a c', 'e d d b j', 'c e b b h i h'); -- 34 + INSERT INTO t3 VALUES('d f h', 'c a f c c', 'j b b c c j f'); -- 35 + INSERT INTO t3 VALUES('b g h', 'g c c c f', 'c g c f h e e'); -- 36 + INSERT INTO t3 VALUES('f e a', 'b h f j h', 'j g h f d g f'); -- 37 + INSERT INTO t3 VALUES('h f a', 'a e i j g', 'f d a f d f c'); -- 38 + INSERT INTO t3 VALUES('f i c', 'f i i i i', 'e c f d h j f'); -- 39 + INSERT INTO t3 VALUES('h h d', 'd i e d i', 'd f e i a h a'); -- 40 + INSERT INTO t3 VALUES('f g c', 'd a f c h', 'b b g j c e g'); -- 41 + INSERT INTO t3 VALUES('h i h', 'h d j d e', 'e d b b i e g'); -- 42 + INSERT INTO t3 VALUES('b h i', 'j e i d a', 'j j h e e c a'); -- 43 + INSERT INTO t3 VALUES('g i g', 'f c c f d', 'a c i c a d a'); -- 44 + INSERT INTO t3 VALUES('c c f', 'a b j d b', 'c a e g f e c'); -- 45 + INSERT INTO t3 VALUES('d h j', 'g c b j d', 'e a h f h j g'); -- 46 + INSERT INTO t3 VALUES('a a d', 'j e j a i', 'i d c f f f b'); -- 47 + INSERT INTO t3 VALUES('b g j', 'e c i h f', 'd d h b g a d'); -- 48 + INSERT INTO t3 VALUES('c i a', 'a c c c c', 'e h i e h i e'); -- 49 + INSERT INTO t3 VALUES('f f c', 'f f b i i', 'f f a j e c i'); -- 50 +} + +proc pmatch {col expr} { + return [expr {[string first $expr $col]>=0}] +} +db func pmatch pmatch + +foreach {tn cols tokens} { + 1 a "c c" + 2 b "c c" + 3 c "c c" + 4 {a b c} "c c" + 5 {a b c} "b h" + 6 {a b} "b h" + 7 {a c} "b h" + 8 {c a} "b h" + 9 {c} "i e" + 10 {b} "i e" + 11 {a} "i e" +} { + set fts "{$cols}:[join $tokens +]" + set where [list] + foreach c $cols { lappend where "pmatch($c, '$tokens')" } + set where [join $where " OR "] + + set res [db eval "SELECT rowid FROM t3 WHERE $where"] + do_execsql_test "1.$tn.$fts->([llength $res] rows)" { + SELECT rowid FROM t3($fts) + } $res +} + +do_execsql_test 2.0 { + SELECT rowid, + highlight(t3, 0, '*', '*'), + highlight(t3, 1, '*', '*'), + highlight(t3, 2, '*', '*') + FROM t3('a:f+f') +} { + 31 {h *f f*} {i j g e c} {j j f c a i j} + 50 {*f f* c} {f f b i i} {f f a j e c i} +} + +finish_test + diff --git a/ext/fts5/test/fts5plan.test b/ext/fts5/test/fts5plan.test new file mode 100644 index 0000000..d7f5fd6 --- /dev/null +++ b/ext/fts5/test/fts5plan.test @@ -0,0 +1,67 @@ +# 2014 Dec 20 +# +# 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 focuses on testing the planner (xBestIndex function). +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5plan + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(x, y); + CREATE VIRTUAL TABLE f1 USING fts5(ff); +} + +do_eqp_test 1.1 { + SELECT * FROM t1, f1 WHERE f1 MATCH t1.x +} { + 0 0 0 {SCAN TABLE t1} + 0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 1:} +} + +do_eqp_test 1.2 { + SELECT * FROM t1, f1 WHERE f1 > t1.x +} { + 0 0 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:} + 0 1 0 {SCAN TABLE t1} +} + +do_eqp_test 1.3 { + SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff +} { + 0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 1:} + 0 0 0 {USE TEMP B-TREE FOR ORDER BY} +} + +do_eqp_test 1.4 { + SELECT * FROM f1 ORDER BY rank +} { + 0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:} + 0 0 0 {USE TEMP B-TREE FOR ORDER BY} +} + +do_eqp_test 1.5 { + SELECT * FROM f1 WHERE rank MATCH ? +} { + 0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:} +} + + + + +finish_test + diff --git a/ext/fts5/test/fts5porter.test b/ext/fts5/test/fts5porter.test new file mode 100644 index 0000000..2535eb7 --- /dev/null +++ b/ext/fts5/test/fts5porter.test @@ -0,0 +1,11806 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on the fts5 porter stemmer implementation. +# +# http://tartarus.org/martin/PorterStemmer/ +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5porter + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +set test_vocab { + a a aaron aaron + abaissiez abaissiez abandon abandon + abandoned abandon abase abas + abash abash abate abat + abated abat abatement abat + abatements abat abates abat + abbess abbess abbey abbei + abbeys abbei abbominable abbomin + abbot abbot abbots abbot + abbreviated abbrevi abed ab + abel abel aberga aberga + abergavenny abergavenni abet abet + abetting abet abhominable abhomin + abhor abhor abhorr abhorr + abhorred abhor abhorring abhor + abhors abhor abhorson abhorson + abide abid abides abid + abilities abil ability abil + abject abject abjectly abjectli + abjects abject abjur abjur + abjure abjur able abl + abler abler aboard aboard + abode abod aboded abod + abodements abod aboding abod + abominable abomin abominably abomin + abominations abomin abortive abort + abortives abort abound abound + abounding abound about about + above abov abr abr + abraham abraham abram abram + abreast abreast abridg abridg + abridge abridg abridged abridg + abridgment abridg abroach abroach + abroad abroad abrogate abrog + abrook abrook abrupt abrupt + abruption abrupt abruptly abruptli + absence absenc absent absent + absey absei absolute absolut + absolutely absolut absolv absolv + absolver absolv abstains abstain + abstemious abstemi abstinence abstin + abstract abstract absurd absurd + absyrtus absyrtu abundance abund + abundant abund abundantly abundantli + abus abu abuse abus + abused abus abuser abus + abuses abus abusing abus + abutting abut aby abi + abysm abysm ac ac + academe academ academes academ + accent accent accents accent + accept accept acceptable accept + acceptance accept accepted accept + accepts accept access access + accessary accessari accessible access + accidence accid accident accid + accidental accident accidentally accident + accidents accid accite accit + accited accit accites accit + acclamations acclam accommodate accommod + accommodated accommod accommodation accommod + accommodations accommod accommodo accommodo + accompanied accompani accompany accompani + accompanying accompani accomplices accomplic + accomplish accomplish accomplished accomplish + accomplishing accomplish accomplishment accomplish + accompt accompt accord accord + accordant accord accorded accord + accordeth accordeth according accord + accordingly accordingli accords accord + accost accost accosted accost + account account accountant account + accounted account accounts account + accoutred accoutr accoutrement accoutr + accoutrements accoutr accrue accru + accumulate accumul accumulated accumul + accumulation accumul accurs accur + accursed accurs accurst accurst + accus accu accusation accus + accusations accus accusative accus + accusativo accusativo accuse accus + accused accus accuser accus + accusers accus accuses accus + accuseth accuseth accusing accus + accustom accustom accustomed accustom + ace ac acerb acerb + ache ach acheron acheron + aches ach achiev achiev + achieve achiev achieved achiev + achievement achiev achievements achiev + achiever achiev achieves achiev + achieving achiev achilles achil + aching ach achitophel achitophel + acknowledg acknowledg acknowledge acknowledg + acknowledged acknowledg acknowledgment acknowledg + acknown acknown acold acold + aconitum aconitum acordo acordo + acorn acorn acquaint acquaint + acquaintance acquaint acquainted acquaint + acquaints acquaint acquir acquir + acquire acquir acquisition acquisit + acquit acquit acquittance acquitt + acquittances acquitt acquitted acquit + acre acr acres acr + across across act act + actaeon actaeon acted act + acting act action action + actions action actium actium + active activ actively activ + activity activ actor actor + actors actor acts act + actual actual acture actur + acute acut acutely acut + ad ad adage adag + adallas adalla adam adam + adamant adam add add + added ad adder adder + adders adder addeth addeth + addict addict addicted addict + addiction addict adding ad + addition addit additions addit + addle addl address address + addressing address addrest addrest + adds add adhere adher + adheres adher adieu adieu + adieus adieu adjacent adjac + adjoin adjoin adjoining adjoin + adjourn adjourn adjudg adjudg + adjudged adjudg adjunct adjunct + administer administ administration administr + admir admir admirable admir + admiral admir admiration admir + admire admir admired admir + admirer admir admiring admir + admiringly admiringli admission admiss + admit admit admits admit + admittance admitt admitted admit + admitting admit admonish admonish + admonishing admonish admonishment admonish + admonishments admonish admonition admonit + ado ado adonis adoni + adopt adopt adopted adopt + adoptedly adoptedli adoption adopt + adoptious adopti adopts adopt + ador ador adoration ador + adorations ador adore ador + adorer ador adores ador + adorest adorest adoreth adoreth + adoring ador adorn adorn + adorned adorn adornings adorn + adornment adorn adorns adorn + adown adown adramadio adramadio + adrian adrian adriana adriana + adriano adriano adriatic adriat + adsum adsum adulation adul + adulterate adulter adulterates adulter + adulterers adulter adulteress adulteress + adulteries adulteri adulterous adulter + adultery adulteri adultress adultress + advanc advanc advance advanc + advanced advanc advancement advanc + advancements advanc advances advanc + advancing advanc advantage advantag + advantageable advantag advantaged advantag + advantageous advantag advantages advantag + advantaging advantag advent advent + adventur adventur adventure adventur + adventures adventur adventuring adventur + adventurous adventur adventurously adventur + adversaries adversari adversary adversari + adverse advers adversely advers + adversities advers adversity advers + advertis adverti advertise advertis + advertised advertis advertisement advertis + advertising advertis advice advic + advis advi advise advis + advised advis advisedly advisedli + advises advis advisings advis + advocate advoc advocation advoc + aeacida aeacida aeacides aeacid + aedile aedil aediles aedil + aegeon aegeon aegion aegion + aegles aegl aemelia aemelia + aemilia aemilia aemilius aemiliu + aeneas aenea aeolus aeolu + aer aer aerial aerial + aery aeri aesculapius aesculapiu + aeson aeson aesop aesop + aetna aetna afar afar + afear afear afeard afeard + affability affabl affable affabl + affair affair affaire affair + affairs affair affect affect + affectation affect affectations affect + affected affect affectedly affectedli + affecteth affecteth affecting affect + affection affect affectionate affection + affectionately affection affections affect + affects affect affeer affeer + affianc affianc affiance affianc + affianced affianc affied affi + affin affin affined affin + affinity affin affirm affirm + affirmation affirm affirmatives affirm + afflict afflict afflicted afflict + affliction afflict afflictions afflict + afflicts afflict afford afford + affordeth affordeth affords afford + affray affrai affright affright + affrighted affright affrights affright + affront affront affronted affront + affy affi afield afield + afire afir afloat afloat + afoot afoot afore afor + aforehand aforehand aforesaid aforesaid + afraid afraid afresh afresh + afric afric africa africa + african african afront afront + after after afternoon afternoon + afterward afterward afterwards afterward + ag ag again again + against against agamemmon agamemmon + agamemnon agamemnon agate agat + agaz agaz age ag + aged ag agenor agenor + agent agent agents agent + ages ag aggravate aggrav + aggrief aggrief agile agil + agincourt agincourt agitation agit + aglet aglet agnize agniz + ago ago agone agon + agony agoni agree agre + agreed agre agreeing agre + agreement agreement agrees agre + agrippa agrippa aground aground + ague agu aguecheek aguecheek + agued agu agueface aguefac + agues agu ah ah + aha aha ahungry ahungri + ai ai aialvolio aialvolio + aiaria aiaria aid aid + aidance aidanc aidant aidant + aided aid aiding aid + aidless aidless aids aid + ail ail aim aim + aimed aim aimest aimest + aiming aim aims aim + ainsi ainsi aio aio + air air aired air + airless airless airs air + airy airi ajax ajax + akilling akil al al + alabaster alabast alack alack + alacrity alacr alarbus alarbu + alarm alarm alarms alarm + alarum alarum alarums alarum + alas ala alb alb + alban alban albans alban + albany albani albeit albeit + albion albion alchemist alchemist + alchemy alchemi alcibiades alcibiad + alcides alcid alder alder + alderman alderman aldermen aldermen + ale al alecto alecto + alehouse alehous alehouses alehous + alencon alencon alengon alengon + aleppo aleppo ales al + alewife alewif alexander alexand + alexanders alexand alexandria alexandria + alexandrian alexandrian alexas alexa + alias alia alice alic + alien alien aliena aliena + alight alight alighted alight + alights alight aliis alii + alike alik alisander alisand + alive aliv all all + alla alla allay allai + allayed allai allaying allai + allayment allay allayments allay + allays allai allegation alleg + allegations alleg allege alleg + alleged alleg allegiance allegi + allegiant allegi alley allei + alleys allei allhallowmas allhallowma + alliance allianc allicholy allicholi + allied alli allies alli + alligant allig alligator allig + allons allon allot allot + allots allot allotted allot + allottery allotteri allow allow + allowance allow allowed allow + allowing allow allows allow + allur allur allure allur + allurement allur alluring allur + allusion allus ally alli + allycholly allycholli almain almain + almanac almanac almanack almanack + almanacs almanac almighty almighti + almond almond almost almost + alms alm almsman almsman + aloes alo aloft aloft + alone alon along along + alonso alonso aloof aloof + aloud aloud alphabet alphabet + alphabetical alphabet alphonso alphonso + alps alp already alreadi + also also alt alt + altar altar altars altar + alter alter alteration alter + altered alter alters alter + althaea althaea although although + altitude altitud altogether altogeth + alton alton alway alwai + always alwai am am + amaimon amaimon amain amain + amaking amak amamon amamon + amaz amaz amaze amaz + amazed amaz amazedly amazedli + amazedness amazed amazement amaz + amazes amaz amazeth amazeth + amazing amaz amazon amazon + amazonian amazonian amazons amazon + ambassador ambassador ambassadors ambassador + amber amber ambiguides ambiguid + ambiguities ambigu ambiguous ambigu + ambition ambit ambitions ambit + ambitious ambiti ambitiously ambiti + amble ambl ambled ambl + ambles ambl ambling ambl + ambo ambo ambuscadoes ambuscado + ambush ambush amen amen + amend amend amended amend + amendment amend amends amend + amerce amerc america america + ames am amiable amiabl + amid amid amidst amidst + amiens amien amis ami + amiss amiss amities amiti + amity amiti amnipotent amnipot + among among amongst amongst + amorous amor amorously amor + amort amort amount amount + amounts amount amour amour + amphimacus amphimacu ample ampl + ampler ampler amplest amplest + amplified amplifi amplify amplifi + amply ampli ampthill ampthil + amurath amurath amyntas amynta + an an anatomiz anatomiz + anatomize anatom anatomy anatomi + ancestor ancestor ancestors ancestor + ancestry ancestri anchises anchis + anchor anchor anchorage anchorag + anchored anchor anchoring anchor + anchors anchor anchovies anchovi + ancient ancient ancientry ancientri + ancients ancient ancus ancu + and and andirons andiron + andpholus andpholu andren andren + andrew andrew andromache andromach + andronici andronici andronicus andronicu + anew anew ang ang + angel angel angelica angelica + angelical angel angelo angelo + angels angel anger anger + angerly angerli angers anger + anges ang angiers angier + angl angl anglais anglai + angle angl angler angler + angleterre angleterr angliae anglia + angling angl anglish anglish + angrily angrili angry angri + anguish anguish angus angu + animal anim animals anim + animis animi anjou anjou + ankle ankl anna anna + annals annal anne ann + annex annex annexed annex + annexions annexion annexment annex + annothanize annothan announces announc + annoy annoi annoyance annoy + annoying annoi annual annual + anoint anoint anointed anoint + anon anon another anoth + anselmo anselmo answer answer + answerable answer answered answer + answerest answerest answering answer + answers answer ant ant + ante ant antenor antenor + antenorides antenorid anteroom anteroom + anthem anthem anthems anthem + anthony anthoni anthropophagi anthropophagi + anthropophaginian anthropophaginian antiates antiat + antic antic anticipate anticip + anticipates anticip anticipatest anticipatest + anticipating anticip anticipation anticip + antick antick anticly anticli + antics antic antidote antidot + antidotes antidot antigonus antigonu + antiopa antiopa antipathy antipathi + antipholus antipholu antipholuses antipholus + antipodes antipod antiquary antiquari + antique antiqu antiquity antiqu + antium antium antoniad antoniad + antonio antonio antonius antoniu + antony antoni antres antr + anvil anvil any ani + anybody anybodi anyone anyon + anything anyth anywhere anywher + ap ap apace apac + apart apart apartment apart + apartments apart ape ap + apemantus apemantu apennines apennin + apes ap apiece apiec + apish apish apollinem apollinem + apollo apollo apollodorus apollodoru + apology apolog apoplex apoplex + apoplexy apoplexi apostle apostl + apostles apostl apostrophas apostropha + apoth apoth apothecary apothecari + appal appal appall appal + appalled appal appals appal + apparel apparel apparell apparel + apparelled apparel apparent appar + apparently appar apparition apparit + apparitions apparit appeach appeach + appeal appeal appeals appeal + appear appear appearance appear + appeared appear appeareth appeareth + appearing appear appears appear + appeas appea appease appeas + appeased appeas appelant appel + appele appel appelee appele + appeles appel appelez appelez + appellant appel appellants appel + appelons appelon appendix appendix + apperil apperil appertain appertain + appertaining appertain appertainings appertain + appertains appertain appertinent appertin + appertinents appertin appetite appetit + appetites appetit applaud applaud + applauded applaud applauding applaud + applause applaus applauses applaus + apple appl apples appl + appletart appletart appliance applianc + appliances applianc applications applic + applied appli applies appli + apply appli applying appli + appoint appoint appointed appoint + appointment appoint appointments appoint + appoints appoint apprehend apprehend + apprehended apprehend apprehends apprehend + apprehension apprehens apprehensions apprehens + apprehensive apprehens apprendre apprendr + apprenne apprenn apprenticehood apprenticehood + appris appri approach approach + approachers approach approaches approach + approacheth approacheth approaching approach + approbation approb approof approof + appropriation appropri approv approv + approve approv approved approv + approvers approv approves approv + appurtenance appurten appurtenances appurten + apricocks apricock april april + apron apron aprons apron + apt apt apter apter + aptest aptest aptly aptli + aptness apt aqua aqua + aquilon aquilon aquitaine aquitain + arabia arabia arabian arabian + araise arais arbitrate arbitr + arbitrating arbitr arbitrator arbitr + arbitrement arbitr arbors arbor + arbour arbour arc arc + arch arch archbishop archbishop + archbishopric archbishopr archdeacon archdeacon + arched arch archelaus archelau + archer archer archers archer + archery archeri archibald archibald + archidamus archidamu architect architect + arcu arcu arde ard + arden arden ardent ardent + ardour ardour are ar + argal argal argier argier + argo argo argosies argosi + argosy argosi argu argu + argue argu argued argu + argues argu arguing argu + argument argument arguments argument + argus argu ariachne ariachn + ariadne ariadn ariel ariel + aries ari aright aright + arinado arinado arinies arini + arion arion arise aris + arises aris ariseth ariseth + arising aris aristode aristod + aristotle aristotl arithmetic arithmet + arithmetician arithmetician ark ark + arm arm arma arma + armado armado armadoes armado + armagnac armagnac arme arm + armed arm armenia armenia + armies armi armigero armigero + arming arm armipotent armipot + armor armor armour armour + armourer armour armourers armour + armours armour armoury armouri + arms arm army armi + arn arn aroint aroint + arose aros arouse arous + aroused arous arragon arragon + arraign arraign arraigned arraign + arraigning arraign arraignment arraign + arrant arrant arras arra + array arrai arrearages arrearag + arrest arrest arrested arrest + arrests arrest arriv arriv + arrival arriv arrivance arriv + arrive arriv arrived arriv + arrives arriv arriving arriv + arrogance arrog arrogancy arrog + arrogant arrog arrow arrow + arrows arrow art art + artemidorus artemidoru arteries arteri + arthur arthur article articl + articles articl articulate articul + artificer artific artificial artifici + artillery artilleri artire artir + artist artist artists artist + artless artless artois artoi + arts art artus artu + arviragus arviragu as as + asaph asaph ascanius ascaniu + ascend ascend ascended ascend + ascendeth ascendeth ascends ascend + ascension ascens ascent ascent + ascribe ascrib ascribes ascrib + ash ash asham asham + ashamed asham asher asher + ashes ash ashford ashford + ashore ashor ashouting ashout + ashy ashi asia asia + aside asid ask ask + askance askanc asked ask + asker asker asketh asketh + asking ask asks ask + aslant aslant asleep asleep + asmath asmath asp asp + aspect aspect aspects aspect + aspen aspen aspersion aspers + aspic aspic aspicious aspici + aspics aspic aspir aspir + aspiration aspir aspire aspir + aspiring aspir asquint asquint + ass ass assail assail + assailable assail assailant assail + assailants assail assailed assail + assaileth assaileth assailing assail + assails assail assassination assassin + assault assault assaulted assault + assaults assault assay assai + assaying assai assays assai + assemblance assembl assemble assembl + assembled assembl assemblies assembl + assembly assembl assent assent + asses ass assez assez + assign assign assigned assign + assigns assign assinico assinico + assist assist assistance assist + assistances assist assistant assist + assistants assist assisted assist + assisting assist associate associ + associated associ associates associ + assuage assuag assubjugate assubjug + assum assum assume assum + assumes assum assumption assumpt + assur assur assurance assur + assure assur assured assur + assuredly assuredli assures assur + assyrian assyrian astonish astonish + astonished astonish astraea astraea + astray astrai astrea astrea + astronomer astronom astronomers astronom + astronomical astronom astronomy astronomi + asunder asund at at + atalanta atalanta ate at + ates at athenian athenian + athenians athenian athens athen + athol athol athversary athversari + athwart athwart atlas atla + atomies atomi atomy atomi + atone aton atonement aton + atonements aton atropos atropo + attach attach attached attach + attachment attach attain attain + attainder attaind attains attain + attaint attaint attainted attaint + attainture attaintur attempt attempt + attemptable attempt attempted attempt + attempting attempt attempts attempt + attend attend attendance attend + attendant attend attendants attend + attended attend attendents attend + attendeth attendeth attending attend + attends attend attent attent + attention attent attentive attent + attentivenes attentiven attest attest + attested attest attir attir + attire attir attired attir + attires attir attorney attornei + attorneyed attornei attorneys attornei + attorneyship attorneyship attract attract + attraction attract attractive attract + attracts attract attribute attribut + attributed attribut attributes attribut + attribution attribut attributive attribut + atwain atwain au au + aubrey aubrei auburn auburn + aucun aucun audacious audaci + audaciously audaci audacity audac + audible audibl audience audienc + audis audi audit audit + auditor auditor auditors auditor + auditory auditori audre audr + audrey audrei aufidius aufidiu + aufidiuses aufidius auger auger + aught aught augment augment + augmentation augment augmented augment + augmenting augment augurer augur + augurers augur augures augur + auguring augur augurs augur + augury auguri august august + augustus augustu auld auld + aumerle aumerl aunchient aunchient + aunt aunt aunts aunt + auricular auricular aurora aurora + auspicious auspici aussi aussi + austere auster austerely auster + austereness auster austerity auster + austria austria aut aut + authentic authent author author + authorities author authority author + authorized author authorizing author + authors author autolycus autolycu + autre autr autumn autumn + auvergne auvergn avail avail + avails avail avarice avaric + avaricious avarici avaunt avaunt + ave av aveng aveng + avenge aveng avenged aveng + averring aver avert avert + aves av avez avez + avis avi avoid avoid + avoided avoid avoiding avoid + avoids avoid avoirdupois avoirdupoi + avouch avouch avouched avouch + avouches avouch avouchment avouch + avow avow aw aw + await await awaits await + awak awak awake awak + awaked awak awaken awaken + awakened awaken awakens awaken + awakes awak awaking awak + award award awards award + awasy awasi away awai + awe aw aweary aweari + aweless aweless awful aw + awhile awhil awkward awkward + awl awl awooing awoo + awork awork awry awri + axe ax axle axl + axletree axletre ay ay + aye ay ayez ayez + ayli ayli azur azur + azure azur b b + ba ba baa baa + babbl babbl babble babbl + babbling babbl babe babe + babes babe babies babi + baboon baboon baboons baboon + baby babi babylon babylon + bacare bacar bacchanals bacchan + bacchus bacchu bach bach + bachelor bachelor bachelors bachelor + back back backbite backbit + backbitten backbitten backing back + backs back backward backward + backwardly backwardli backwards backward + bacon bacon bacons bacon + bad bad bade bade + badge badg badged badg + badges badg badly badli + badness bad baes bae + baffl baffl baffle baffl + baffled baffl bag bag + baggage baggag bagot bagot + bagpipe bagpip bags bag + bail bail bailiff bailiff + baillez baillez baily baili + baisant baisant baisees baise + baiser baiser bait bait + baited bait baiting bait + baitings bait baits bait + bajazet bajazet bak bak + bake bake baked bake + baker baker bakers baker + bakes bake baking bake + bal bal balanc balanc + balance balanc balcony balconi + bald bald baldrick baldrick + bale bale baleful bale + balk balk ball ball + ballad ballad ballads ballad + ballast ballast ballasting ballast + ballet ballet ballow ballow + balls ball balm balm + balms balm balmy balmi + balsam balsam balsamum balsamum + balth balth balthasar balthasar + balthazar balthazar bames bame + ban ban banbury banburi + band band bandied bandi + banding band bandit bandit + banditti banditti banditto banditto + bands band bandy bandi + bandying bandi bane bane + banes bane bang bang + bangor bangor banish banish + banished banish banishers banish + banishment banish banister banist + bank bank bankrout bankrout + bankrupt bankrupt bankrupts bankrupt + banks bank banner banner + bannerets banneret banners banner + banning ban banns bann + banquet banquet banqueted banquet + banqueting banquet banquets banquet + banquo banquo bans ban + baptism baptism baptista baptista + baptiz baptiz bar bar + barbarian barbarian barbarians barbarian + barbarism barbar barbarous barbar + barbary barbari barbason barbason + barbed barb barber barber + barbermonger barbermong bard bard + bardolph bardolph bards bard + bare bare bared bare + barefac barefac barefaced barefac + barefoot barefoot bareheaded barehead + barely bare bareness bare + barful bar bargain bargain + bargains bargain barge barg + bargulus bargulu baring bare + bark bark barking bark + barkloughly barkloughli barks bark + barky barki barley barlei + barm barm barn barn + barnacles barnacl barnardine barnardin + barne barn barnes barn + barnet barnet barns barn + baron baron barons baron + barony baroni barr barr + barrabas barraba barrel barrel + barrels barrel barren barren + barrenly barrenli barrenness barren + barricado barricado barricadoes barricado + barrow barrow bars bar + barson barson barter barter + bartholomew bartholomew bas ba + basan basan base base + baseless baseless basely base + baseness base baser baser + bases base basest basest + bashful bash bashfulness bash + basilisco basilisco basilisk basilisk + basilisks basilisk basimecu basimecu + basin basin basingstoke basingstok + basins basin basis basi + bask bask basket basket + baskets basket bass bass + bassanio bassanio basset basset + bassianus bassianu basta basta + bastard bastard bastardizing bastard + bastardly bastardli bastards bastard + bastardy bastardi basted bast + bastes bast bastinado bastinado + basting bast bat bat + batailles batail batch batch + bate bate bated bate + bates bate bath bath + bathe bath bathed bath + bathing bath baths bath + bating bate batler batler + bats bat batt batt + battalia battalia battalions battalion + batten batten batter batter + battering batter batters batter + battery batteri battle battl + battled battl battlefield battlefield + battlements battlement battles battl + batty batti bauble baubl + baubles baubl baubling baubl + baulk baulk bavin bavin + bawcock bawcock bawd bawd + bawdry bawdri bawds bawd + bawdy bawdi bawl bawl + bawling bawl bay bai + baying bai baynard baynard + bayonne bayonn bays bai + be be beach beach + beached beach beachy beachi + beacon beacon bead bead + beaded bead beadle beadl + beadles beadl beads bead + beadsmen beadsmen beagle beagl + beagles beagl beak beak + beaks beak beam beam + beamed beam beams beam + bean bean beans bean + bear bear beard beard + bearded beard beardless beardless + beards beard bearer bearer + bearers bearer bearest bearest + beareth beareth bearing bear + bears bear beast beast + beastliest beastliest beastliness beastli + beastly beastli beasts beast + beat beat beated beat + beaten beaten beating beat + beatrice beatric beats beat + beau beau beaufort beaufort + beaumond beaumond beaumont beaumont + beauteous beauteou beautied beauti + beauties beauti beautified beautifi + beautiful beauti beautify beautifi + beauty beauti beaver beaver + beavers beaver became becam + because becaus bechanc bechanc + bechance bechanc bechanced bechanc + beck beck beckon beckon + beckons beckon becks beck + becom becom become becom + becomed becom becomes becom + becoming becom becomings becom + bed bed bedabbled bedabbl + bedash bedash bedaub bedaub + bedazzled bedazzl bedchamber bedchamb + bedclothes bedcloth bedded bed + bedeck bedeck bedecking bedeck + bedew bedew bedfellow bedfellow + bedfellows bedfellow bedford bedford + bedlam bedlam bedrench bedrench + bedrid bedrid beds bed + bedtime bedtim bedward bedward + bee bee beef beef + beefs beef beehives beehiv + been been beer beer + bees bee beest beest + beetle beetl beetles beetl + beeves beev befall befal + befallen befallen befalls befal + befell befel befits befit + befitted befit befitting befit + befor befor before befor + beforehand beforehand befortune befortun + befriend befriend befriended befriend + befriends befriend beg beg + began began beget beget + begets beget begetting beget + begg begg beggar beggar + beggared beggar beggarly beggarli + beggarman beggarman beggars beggar + beggary beggari begging beg + begin begin beginners beginn + beginning begin beginnings begin + begins begin begnawn begnawn + begone begon begot begot + begotten begotten begrimed begrim + begs beg beguil beguil + beguile beguil beguiled beguil + beguiles beguil beguiling beguil + begun begun behalf behalf + behalfs behalf behav behav + behaved behav behavedst behavedst + behavior behavior behaviors behavior + behaviour behaviour behaviours behaviour + behead behead beheaded behead + beheld beheld behest behest + behests behest behind behind + behold behold beholder behold + beholders behold beholdest beholdest + beholding behold beholds behold + behoof behoof behooffull behoofful + behooves behoov behove behov + behoves behov behowls behowl + being be bel bel + belarius belariu belch belch + belching belch beldam beldam + beldame beldam beldams beldam + belee bele belgia belgia + belie beli belied beli + belief belief beliest beliest + believ believ believe believ + believed believ believes believ + believest believest believing believ + belike belik bell bell + bellario bellario belle bell + bellied belli bellies belli + bellman bellman bellona bellona + bellow bellow bellowed bellow + bellowing bellow bellows bellow + bells bell belly belli + bellyful belly belman belman + belmont belmont belock belock + belong belong belonging belong + belongings belong belongs belong + belov belov beloved belov + beloving belov below below + belt belt belzebub belzebub + bemadding bemad bemet bemet + bemete bemet bemoan bemoan + bemoaned bemoan bemock bemock + bemoil bemoil bemonster bemonst + ben ben bench bench + bencher bencher benches bench + bend bend bended bend + bending bend bends bend + bene bene beneath beneath + benedicite benedicit benedick benedick + benediction benedict benedictus benedictu + benefactors benefactor benefice benefic + beneficial benefici benefit benefit + benefited benefit benefits benefit + benetted benet benevolence benevol + benevolences benevol benied beni + benison benison bennet bennet + bent bent bentii bentii + bentivolii bentivolii bents bent + benumbed benumb benvolio benvolio + bepaint bepaint bepray beprai + bequeath bequeath bequeathed bequeath + bequeathing bequeath bequest bequest + ber ber berard berard + berattle berattl beray berai + bere bere bereave bereav + bereaved bereav bereaves bereav + bereft bereft bergamo bergamo + bergomask bergomask berhym berhym + berhyme berhym berkeley berkelei + bermoothes bermooth bernardo bernardo + berod berod berowne berown + berri berri berries berri + berrord berrord berry berri + bertram bertram berwick berwick + bescreen bescreen beseech beseech + beseeched beseech beseechers beseech + beseeching beseech beseek beseek + beseem beseem beseemeth beseemeth + beseeming beseem beseems beseem + beset beset beshrew beshrew + beside besid besides besid + besieg besieg besiege besieg + besieged besieg beslubber beslubb + besmear besmear besmeared besmear + besmirch besmirch besom besom + besort besort besotted besot + bespake bespak bespeak bespeak + bespice bespic bespoke bespok + bespotted bespot bess bess + bessy bessi best best + bestained bestain bested best + bestial bestial bestir bestir + bestirr bestirr bestow bestow + bestowed bestow bestowing bestow + bestows bestow bestraught bestraught + bestrew bestrew bestrid bestrid + bestride bestrid bestrides bestrid + bet bet betake betak + beteem beteem bethink bethink + bethought bethought bethrothed bethroth + bethump bethump betid betid + betide betid betideth betideth + betime betim betimes betim + betoken betoken betook betook + betossed betoss betray betrai + betrayed betrai betraying betrai + betrays betrai betrims betrim + betroth betroth betrothed betroth + betroths betroth bett bett + betted bet better better + bettered better bettering better + betters better betting bet + bettre bettr between between + betwixt betwixt bevel bevel + beverage beverag bevis bevi + bevy bevi bewail bewail + bewailed bewail bewailing bewail + bewails bewail beware bewar + bewasted bewast beweep beweep + bewept bewept bewet bewet + bewhored bewhor bewitch bewitch + bewitched bewitch bewitchment bewitch + bewray bewrai beyond beyond + bezonian bezonian bezonians bezonian + bianca bianca bianco bianco + bias bia bibble bibbl + bickerings bicker bid bid + bidden bidden bidding bid + biddings bid biddy biddi + bide bide bides bide + biding bide bids bid + bien bien bier bier + bifold bifold big big + bigamy bigami biggen biggen + bigger bigger bigness big + bigot bigot bilberry bilberri + bilbo bilbo bilboes bilbo + bilbow bilbow bill bill + billeted billet billets billet + billiards billiard billing bill + billow billow billows billow + bills bill bin bin + bind bind bindeth bindeth + binding bind binds bind + biondello biondello birch birch + bird bird birding bird + birdlime birdlim birds bird + birnam birnam birth birth + birthday birthdai birthdom birthdom + birthplace birthplac birthright birthright + birthrights birthright births birth + bis bi biscuit biscuit + bishop bishop bishops bishop + bisson bisson bit bit + bitch bitch bite bite + biter biter bites bite + biting bite bits bit + bitt bitt bitten bitten + bitter bitter bitterest bitterest + bitterly bitterli bitterness bitter + blab blab blabb blabb + blabbing blab blabs blab + black black blackamoor blackamoor + blackamoors blackamoor blackberries blackberri + blackberry blackberri blacker blacker + blackest blackest blackfriars blackfriar + blackheath blackheath blackmere blackmer + blackness black blacks black + bladder bladder bladders bladder + blade blade bladed blade + blades blade blains blain + blam blam blame blame + blamed blame blameful blame + blameless blameless blames blame + blanc blanc blanca blanca + blanch blanch blank blank + blanket blanket blanks blank + blaspheme blasphem blaspheming blasphem + blasphemous blasphem blasphemy blasphemi + blast blast blasted blast + blasting blast blastments blastment + blasts blast blaz blaz + blaze blaze blazes blaze + blazing blaze blazon blazon + blazoned blazon blazoning blazon + bleach bleach bleaching bleach + bleak bleak blear blear + bleared blear bleat bleat + bleated bleat bleats bleat + bled bled bleed bleed + bleedest bleedest bleedeth bleedeth + bleeding bleed bleeds bleed + blemish blemish blemishes blemish + blench blench blenches blench + blend blend blended blend + blent blent bless bless + blessed bless blessedly blessedli + blessedness blessed blesses bless + blesseth blesseth blessing bless + blessings bless blest blest + blew blew blind blind + blinded blind blindfold blindfold + blinding blind blindly blindli + blindness blind blinds blind + blink blink blinking blink + bliss bliss blist blist + blister blister blisters blister + blithe blith blithild blithild + bloat bloat block block + blockish blockish blocks block + blois bloi blood blood + blooded blood bloodhound bloodhound + bloodied bloodi bloodier bloodier + bloodiest bloodiest bloodily bloodili + bloodless bloodless bloods blood + bloodshed bloodsh bloodshedding bloodshed + bloodstained bloodstain bloody bloodi + bloom bloom blooms bloom + blossom blossom blossoming blossom + blossoms blossom blot blot + blots blot blotted blot + blotting blot blount blount + blow blow blowed blow + blowers blower blowest blowest + blowing blow blown blown + blows blow blowse blows + blubb blubb blubber blubber + blubbering blubber blue blue + bluecaps bluecap bluest bluest + blunt blunt blunted blunt + blunter blunter bluntest bluntest + blunting blunt bluntly bluntli + bluntness blunt blunts blunt + blur blur blurr blurr + blurs blur blush blush + blushes blush blushest blushest + blushing blush blust blust + bluster bluster blusterer bluster + blusters bluster bo bo + boar boar board board + boarded board boarding board + boards board boarish boarish + boars boar boast boast + boasted boast boastful boast + boasting boast boasts boast + boat boat boats boat + boatswain boatswain bob bob + bobb bobb boblibindo boblibindo + bobtail bobtail bocchus bocchu + bode bode boded bode + bodements bodement bodes bode + bodg bodg bodied bodi + bodies bodi bodiless bodiless + bodily bodili boding bode + bodkin bodkin body bodi + bodykins bodykin bog bog + boggle boggl boggler boggler + bogs bog bohemia bohemia + bohemian bohemian bohun bohun + boil boil boiling boil + boils boil boist boist + boisterous boister boisterously boister + boitier boitier bold bold + bolden bolden bolder bolder + boldest boldest boldly boldli + boldness bold bolds bold + bolingbroke bolingbrok bolster bolster + bolt bolt bolted bolt + bolter bolter bolters bolter + bolting bolt bolts bolt + bombard bombard bombards bombard + bombast bombast bon bon + bona bona bond bond + bondage bondag bonded bond + bondmaid bondmaid bondman bondman + bondmen bondmen bonds bond + bondslave bondslav bone bone + boneless boneless bones bone + bonfire bonfir bonfires bonfir + bonjour bonjour bonne bonn + bonnet bonnet bonneted bonnet + bonny bonni bonos bono + bonto bonto bonville bonvil + bood bood book book + bookish bookish books book + boon boon boor boor + boorish boorish boors boor + boot boot booted boot + booties booti bootless bootless + boots boot booty booti + bor bor bora bora + borachio borachio bordeaux bordeaux + border border bordered border + borderers border borders border + bore bore boreas borea + bores bore boring bore + born born borne born + borough borough boroughs borough + borrow borrow borrowed borrow + borrower borrow borrowing borrow + borrows borrow bosko bosko + boskos bosko bosky boski + bosom bosom bosoms bosom + boson boson boss boss + bosworth bosworth botch botch + botcher botcher botches botch + botchy botchi both both + bots bot bottle bottl + bottled bottl bottles bottl + bottom bottom bottomless bottomless + bottoms bottom bouciqualt bouciqualt + bouge boug bough bough + boughs bough bought bought + bounce bounc bouncing bounc + bound bound bounded bound + bounden bounden boundeth boundeth + bounding bound boundless boundless + bounds bound bounteous bounteou + bounteously bounteous bounties bounti + bountiful bounti bountifully bountifulli + bounty bounti bourbier bourbier + bourbon bourbon bourchier bourchier + bourdeaux bourdeaux bourn bourn + bout bout bouts bout + bove bove bow bow + bowcase bowcas bowed bow + bowels bowel bower bower + bowing bow bowl bowl + bowler bowler bowling bowl + bowls bowl bows bow + bowsprit bowsprit bowstring bowstr + box box boxes box + boy boi boyet boyet + boyish boyish boys boi + brabant brabant brabantio brabantio + brabble brabbl brabbler brabbler + brac brac brace brace + bracelet bracelet bracelets bracelet + brach brach bracy braci + brag brag bragg bragg + braggardism braggard braggards braggard + braggart braggart braggarts braggart + bragged brag bragging brag + bragless bragless brags brag + braid braid braided braid + brain brain brained brain + brainford brainford brainish brainish + brainless brainless brains brain + brainsick brainsick brainsickly brainsickli + brake brake brakenbury brakenburi + brakes brake brambles brambl + bran bran branch branch + branches branch branchless branchless + brand brand branded brand + brandish brandish brandon brandon + brands brand bras bra + brass brass brassy brassi + brat brat brats brat + brav brav brave brave + braved brave bravely brave + braver braver bravery braveri + braves brave bravest bravest + braving brave brawl brawl + brawler brawler brawling brawl + brawls brawl brawn brawn + brawns brawn bray brai + braying brai braz braz + brazen brazen brazier brazier + breach breach breaches breach + bread bread breadth breadth + break break breaker breaker + breakfast breakfast breaking break + breaks break breast breast + breasted breast breasting breast + breastplate breastplat breasts breast + breath breath breathe breath + breathed breath breather breather + breathers breather breathes breath + breathest breathest breathing breath + breathless breathless breaths breath + brecknock brecknock bred bred + breech breech breeches breech + breeching breech breed breed + breeder breeder breeders breeder + breeding breed breeds breed + breese brees breeze breez + breff breff bretagne bretagn + brethen brethen bretheren bretheren + brethren brethren brevis brevi + brevity breviti brew brew + brewage brewag brewer brewer + brewers brewer brewing brew + brews brew briareus briareu + briars briar brib brib + bribe bribe briber briber + bribes bribe brick brick + bricklayer bricklay bricks brick + bridal bridal bride bride + bridegroom bridegroom bridegrooms bridegroom + brides bride bridge bridg + bridgenorth bridgenorth bridges bridg + bridget bridget bridle bridl + bridled bridl brief brief + briefer briefer briefest briefest + briefly briefli briefness brief + brier brier briers brier + brigandine brigandin bright bright + brighten brighten brightest brightest + brightly brightli brightness bright + brim brim brimful brim + brims brim brimstone brimston + brinded brind brine brine + bring bring bringer bringer + bringeth bringeth bringing bring + bringings bring brings bring + brinish brinish brink brink + brisk brisk brisky briski + bristle bristl bristled bristl + bristly bristli bristol bristol + bristow bristow britain britain + britaine britain britaines britain + british british briton briton + britons briton brittany brittani + brittle brittl broach broach + broached broach broad broad + broader broader broadsides broadsid + brocas broca brock brock + brogues brogu broil broil + broiling broil broils broil + broke broke broken broken + brokenly brokenli broker broker + brokers broker brokes broke + broking broke brooch brooch + brooches brooch brood brood + brooded brood brooding brood + brook brook brooks brook + broom broom broomstaff broomstaff + broth broth brothel brothel + brother brother brotherhood brotherhood + brotherhoods brotherhood brotherly brotherli + brothers brother broths broth + brought brought brow brow + brown brown browner browner + brownist brownist browny browni + brows brow browse brows + browsing brows bruis brui + bruise bruis bruised bruis + bruises bruis bruising bruis + bruit bruit bruited bruit + brundusium brundusium brunt brunt + brush brush brushes brush + brute brute brutish brutish + brutus brutu bubble bubbl + bubbles bubbl bubbling bubbl + bubukles bubukl buck buck + bucket bucket buckets bucket + bucking buck buckingham buckingham + buckle buckl buckled buckl + buckler buckler bucklers buckler + bucklersbury bucklersburi buckles buckl + buckram buckram bucks buck + bud bud budded bud + budding bud budge budg + budger budger budget budget + buds bud buff buff + buffet buffet buffeting buffet + buffets buffet bug bug + bugbear bugbear bugle bugl + bugs bug build build + builded build buildeth buildeth + building build buildings build + builds build built built + bulk bulk bulks bulk + bull bull bullcalf bullcalf + bullen bullen bullens bullen + bullet bullet bullets bullet + bullocks bullock bulls bull + bully bulli bulmer bulmer + bulwark bulwark bulwarks bulwark + bum bum bumbast bumbast + bump bump bumper bumper + bums bum bunch bunch + bunches bunch bundle bundl + bung bung bunghole bunghol + bungle bungl bunting bunt + buoy buoi bur bur + burbolt burbolt burd burd + burden burden burdened burden + burdening burden burdenous burden + burdens burden burgh burgh + burgher burgher burghers burgher + burglary burglari burgomasters burgomast + burgonet burgonet burgundy burgundi + burial burial buried buri + burier burier buriest buriest + burly burli burn burn + burned burn burnet burnet + burneth burneth burning burn + burnish burnish burns burn + burnt burnt burr burr + burrows burrow burs bur + burst burst bursting burst + bursts burst burthen burthen + burthens burthen burton burton + bury buri burying buri + bush bush bushels bushel + bushes bush bushy bushi + busied busi busily busili + busines busin business busi + businesses busi buskin buskin + busky buski buss buss + busses buss bussing buss + bustle bustl bustling bustl + busy busi but but + butcheed butche butcher butcher + butchered butcher butcheries butcheri + butcherly butcherli butchers butcher + butchery butcheri butler butler + butt butt butter butter + buttered butter butterflies butterfli + butterfly butterfli butterwoman butterwoman + buttery butteri buttock buttock + buttocks buttock button button + buttonhole buttonhol buttons button + buttress buttress buttry buttri + butts butt buxom buxom + buy bui buyer buyer + buying bui buys bui + buzz buzz buzzard buzzard + buzzards buzzard buzzers buzzer + buzzing buzz by by + bye bye byzantium byzantium + c c ca ca + cabbage cabbag cabileros cabilero + cabin cabin cabins cabin + cable cabl cables cabl + cackling cackl cacodemon cacodemon + caddis caddi caddisses caddiss + cade cade cadence cadenc + cadent cadent cades cade + cadmus cadmu caduceus caduceu + cadwal cadwal cadwallader cadwallad + caelius caeliu caelo caelo + caesar caesar caesarion caesarion + caesars caesar cage cage + caged cage cagion cagion + cain cain caithness caith + caitiff caitiff caitiffs caitiff + caius caiu cak cak + cake cake cakes cake + calaber calab calais calai + calamities calam calamity calam + calchas calcha calculate calcul + calen calen calendar calendar + calendars calendar calf calf + caliban caliban calibans caliban + calipolis calipoli cality caliti + caliver caliv call call + callat callat called call + callet callet calling call + calls call calm calm + calmest calmest calmly calmli + calmness calm calms calm + calpurnia calpurnia calumniate calumni + calumniating calumni calumnious calumni + calumny calumni calve calv + calved calv calves calv + calveskins calveskin calydon calydon + cam cam cambio cambio + cambria cambria cambric cambric + cambrics cambric cambridge cambridg + cambyses cambys came came + camel camel camelot camelot + camels camel camest camest + camillo camillo camlet camlet + camomile camomil camp camp + campeius campeiu camping camp + camps camp can can + canakin canakin canaries canari + canary canari cancel cancel + cancell cancel cancelled cancel + cancelling cancel cancels cancel + cancer cancer candidatus candidatu + candied candi candle candl + candles candl candlesticks candlestick + candy candi canidius canidiu + cank cank canker canker + cankerblossom cankerblossom cankers canker + cannibally cannib cannibals cannib + cannon cannon cannoneer cannon + cannons cannon cannot cannot + canon canon canoniz canoniz + canonize canon canonized canon + canons canon canopied canopi + canopies canopi canopy canopi + canst canst canstick canstick + canterbury canterburi cantle cantl + cantons canton canus canu + canvas canva canvass canvass + canzonet canzonet cap cap + capability capabl capable capabl + capacities capac capacity capac + caparison caparison capdv capdv + cape cape capel capel + capels capel caper caper + capers caper capet capet + caphis caphi capilet capilet + capitaine capitain capital capit + capite capit capitol capitol + capitulate capitul capocchia capocchia + capon capon capons capon + capp capp cappadocia cappadocia + capriccio capriccio capricious caprici + caps cap capt capt + captain captain captains captain + captainship captainship captious captiou + captivate captiv captivated captiv + captivates captiv captive captiv + captives captiv captivity captiv + captum captum capucius capuciu + capulet capulet capulets capulet + car car carack carack + caracks carack carat carat + caraways carawai carbonado carbonado + carbuncle carbuncl carbuncled carbuncl + carbuncles carbuncl carcanet carcanet + carcase carcas carcases carcas + carcass carcass carcasses carcass + card card cardecue cardecu + carded card carders carder + cardinal cardin cardinally cardin + cardinals cardin cardmaker cardmak + cards card carduus carduu + care care cared care + career career careers career + careful care carefully carefulli + careless careless carelessly carelessli + carelessness careless cares care + caret caret cargo cargo + carl carl carlisle carlisl + carlot carlot carman carman + carmen carmen carnal carnal + carnally carnal carnarvonshire carnarvonshir + carnation carnat carnations carnat + carol carol carous carou + carouse carous caroused carous + carouses carous carousing carous + carp carp carpenter carpent + carper carper carpet carpet + carpets carpet carping carp + carriage carriag carriages carriag + carried carri carrier carrier + carriers carrier carries carri + carrion carrion carrions carrion + carry carri carrying carri + cars car cart cart + carters carter carthage carthag + carts cart carv carv + carve carv carved carv + carver carver carves carv + carving carv cas ca + casa casa casaer casaer + casca casca case case + casement casement casements casement + cases case cash cash + cashier cashier casing case + cask cask casket casket + casketed casket caskets casket + casque casqu casques casqu + cassado cassado cassandra cassandra + cassibelan cassibelan cassio cassio + cassius cassiu cassocks cassock + cast cast castalion castalion + castaway castawai castaways castawai + casted cast caster caster + castigate castig castigation castig + castile castil castiliano castiliano + casting cast castle castl + castles castl casts cast + casual casual casually casual + casualties casualti casualty casualti + cat cat cataian cataian + catalogue catalogu cataplasm cataplasm + cataracts cataract catarrhs catarrh + catastrophe catastroph catch catch + catcher catcher catches catch + catching catch cate cate + catechising catechis catechism catech + catechize catech cater cater + caterpillars caterpillar caters cater + caterwauling caterwaul cates cate + catesby catesbi cathedral cathedr + catlike catlik catling catl + catlings catl cato cato + cats cat cattle cattl + caucasus caucasu caudle caudl + cauf cauf caught caught + cauldron cauldron caus cau + cause caus caused caus + causeless causeless causer causer + causes caus causest causest + causeth causeth cautel cautel + cautelous cautel cautels cautel + cauterizing cauter caution caution + cautions caution cavaleiro cavaleiro + cavalery cavaleri cavaliers cavali + cave cave cavern cavern + caverns cavern caves cave + caveto caveto caviary caviari + cavil cavil cavilling cavil + cawdor cawdor cawdron cawdron + cawing caw ce ce + ceas cea cease ceas + ceases ceas ceaseth ceaseth + cedar cedar cedars cedar + cedius cediu celebrate celebr + celebrated celebr celebrates celebr + celebration celebr celerity celer + celestial celesti celia celia + cell cell cellar cellar + cellarage cellarag celsa celsa + cement cement censer censer + censor censor censorinus censorinu + censur censur censure censur + censured censur censurers censur + censures censur censuring censur + centaur centaur centaurs centaur + centre centr cents cent + centuries centuri centurion centurion + centurions centurion century centuri + cerberus cerberu cerecloth cerecloth + cerements cerement ceremonial ceremoni + ceremonies ceremoni ceremonious ceremoni + ceremoniously ceremoni ceremony ceremoni + ceres cere cerns cern + certain certain certainer certain + certainly certainli certainties certainti + certainty certainti certes cert + certificate certif certified certifi + certifies certifi certify certifi + ces ce cesario cesario + cess cess cesse cess + cestern cestern cetera cetera + cette cett chaces chace + chaf chaf chafe chafe + chafed chafe chafes chafe + chaff chaff chaffless chaffless + chafing chafe chain chain + chains chain chair chair + chairs chair chalic chalic + chalice chalic chalices chalic + chalk chalk chalks chalk + chalky chalki challeng challeng + challenge challeng challenged challeng + challenger challeng challengers challeng + challenges challeng cham cham + chamber chamber chamberers chamber + chamberlain chamberlain chamberlains chamberlain + chambermaid chambermaid chambermaids chambermaid + chambers chamber chameleon chameleon + champ champ champagne champagn + champain champain champains champain + champion champion champions champion + chanc chanc chance chanc + chanced chanc chancellor chancellor + chances chanc chandler chandler + chang chang change chang + changeable changeabl changed chang + changeful chang changeling changel + changelings changel changer changer + changes chang changest changest + changing chang channel channel + channels channel chanson chanson + chant chant chanticleer chanticl + chanting chant chantries chantri + chantry chantri chants chant + chaos chao chap chap + chape chape chapel chapel + chapeless chapeless chapels chapel + chaplain chaplain chaplains chaplain + chapless chapless chaplet chaplet + chapmen chapmen chaps chap + chapter chapter character charact + charactered charact characterless characterless + characters charact charactery characteri + characts charact charbon charbon + chare chare chares chare + charg charg charge charg + charged charg chargeful charg + charges charg chargeth chargeth + charging charg chariest chariest + chariness chari charing chare + chariot chariot chariots chariot + charitable charit charitably charit + charities chariti charity chariti + charlemain charlemain charles charl + charm charm charmed charm + charmer charmer charmeth charmeth + charmian charmian charming charm + charmingly charmingli charms charm + charneco charneco charnel charnel + charolois charoloi charon charon + charter charter charters charter + chartreux chartreux chary chari + charybdis charybdi chas cha + chase chase chased chase + chaser chaser chaseth chaseth + chasing chase chaste chast + chastely chast chastis chasti + chastise chastis chastised chastis + chastisement chastis chastity chastiti + chat chat chatham chatham + chatillon chatillon chats chat + chatt chatt chattels chattel + chatter chatter chattering chatter + chattles chattl chaud chaud + chaunted chaunt chaw chaw + chawdron chawdron che che + cheap cheap cheapen cheapen + cheaper cheaper cheapest cheapest + cheaply cheapli cheapside cheapsid + cheat cheat cheated cheat + cheater cheater cheaters cheater + cheating cheat cheats cheat + check check checked check + checker checker checking check + checks check cheek cheek + cheeks cheek cheer cheer + cheered cheer cheerer cheerer + cheerful cheer cheerfully cheerfulli + cheering cheer cheerless cheerless + cheerly cheerli cheers cheer + cheese chees chequer chequer + cher cher cherish cherish + cherished cherish cherisher cherish + cherishes cherish cherishing cherish + cherries cherri cherry cherri + cherrypit cherrypit chertsey chertsei + cherub cherub cherubims cherubim + cherubin cherubin cherubins cherubin + cheshu cheshu chess chess + chest chest chester chester + chestnut chestnut chestnuts chestnut + chests chest chetas cheta + chev chev cheval cheval + chevalier chevali chevaliers chevali + cheveril cheveril chew chew + chewed chew chewet chewet + chewing chew chez chez + chi chi chick chick + chicken chicken chickens chicken + chicurmurco chicurmurco chid chid + chidden chidden chide chide + chiders chider chides chide + chiding chide chief chief + chiefest chiefest chiefly chiefli + chien chien child child + childed child childeric childer + childhood childhood childhoods childhood + childing child childish childish + childishness childish childlike childlik + childness child children children + chill chill chilling chill + chime chime chimes chime + chimney chimnei chimneypiece chimneypiec + chimneys chimnei chimurcho chimurcho + chin chin china china + chine chine chines chine + chink chink chinks chink + chins chin chipp chipp + chipper chipper chips chip + chiron chiron chirping chirp + chirrah chirrah chirurgeonly chirurgeonli + chisel chisel chitopher chitoph + chivalrous chivalr chivalry chivalri + choice choic choicely choic + choicest choicest choir choir + choirs choir chok chok + choke choke choked choke + chokes choke choking choke + choler choler choleric choler + cholers choler chollors chollor + choose choos chooser chooser + chooses choos chooseth chooseth + choosing choos chop chop + chopine chopin choplogic choplog + chopp chopp chopped chop + chopping chop choppy choppi + chops chop chopt chopt + chor chor choristers chorist + chorus choru chose chose + chosen chosen chough chough + choughs chough chrish chrish + christ christ christen christen + christendom christendom christendoms christendom + christening christen christenings christen + christian christian christianlike christianlik + christians christian christmas christma + christom christom christopher christoph + christophero christophero chronicle chronicl + chronicled chronicl chronicler chronicl + chroniclers chronicl chronicles chronicl + chrysolite chrysolit chuck chuck + chucks chuck chud chud + chuffs chuff church church + churches church churchman churchman + churchmen churchmen churchyard churchyard + churchyards churchyard churl churl + churlish churlish churlishly churlishli + churls churl churn churn + chus chu cicatrice cicatric + cicatrices cicatric cicely cice + cicero cicero ciceter cicet + ciel ciel ciitzens ciitzen + cilicia cilicia cimber cimber + cimmerian cimmerian cinable cinabl + cincture cinctur cinders cinder + cine cine cinna cinna + cinque cinqu cipher cipher + ciphers cipher circa circa + circe circ circle circl + circled circl circlets circlet + circling circl circuit circuit + circum circum circumcised circumcis + circumference circumfer circummur circummur + circumscrib circumscrib circumscribed circumscrib + circumscription circumscript circumspect circumspect + circumstance circumst circumstanced circumstanc + circumstances circumst circumstantial circumstanti + circumvent circumv circumvention circumvent + cistern cistern citadel citadel + cital cital cite cite + cited cite cites cite + cities citi citing cite + citizen citizen citizens citizen + cittern cittern city citi + civet civet civil civil + civility civil civilly civilli + clack clack clad clad + claim claim claiming claim + claims claim clamb clamb + clamber clamber clammer clammer + clamor clamor clamorous clamor + clamors clamor clamour clamour + clamours clamour clang clang + clangor clangor clap clap + clapp clapp clapped clap + clapper clapper clapping clap + claps clap clare clare + clarence clarenc claret claret + claribel claribel clasp clasp + clasps clasp clatter clatter + claud claud claudio claudio + claudius claudiu clause claus + claw claw clawed claw + clawing claw claws claw + clay clai clays clai + clean clean cleanliest cleanliest + cleanly cleanli cleans clean + cleanse cleans cleansing cleans + clear clear clearer clearer + clearest clearest clearly clearli + clearness clear clears clear + cleave cleav cleaving cleav + clef clef cleft cleft + cleitus cleitu clemency clemenc + clement clement cleomenes cleomen + cleopatpa cleopatpa cleopatra cleopatra + clepeth clepeth clept clept + clerestories clerestori clergy clergi + clergyman clergyman clergymen clergymen + clerk clerk clerkly clerkli + clerks clerk clew clew + client client clients client + cliff cliff clifford clifford + cliffords clifford cliffs cliff + clifton clifton climate climat + climature climatur climb climb + climbed climb climber climber + climbeth climbeth climbing climb + climbs climb clime clime + cling cling clink clink + clinking clink clinquant clinquant + clip clip clipp clipp + clipper clipper clippeth clippeth + clipping clip clipt clipt + clitus clitu clo clo + cloak cloak cloakbag cloakbag + cloaks cloak clock clock + clocks clock clod clod + cloddy cloddi clodpole clodpol + clog clog clogging clog + clogs clog cloister cloister + cloistress cloistress cloquence cloquenc + clos clo close close + closed close closely close + closeness close closer closer + closes close closest closest + closet closet closing close + closure closur cloten cloten + clotens cloten cloth cloth + clothair clothair clotharius clothariu + clothe cloth clothes cloth + clothier clothier clothiers clothier + clothing cloth cloths cloth + clotpoles clotpol clotpoll clotpol + cloud cloud clouded cloud + cloudiness cloudi clouds cloud + cloudy cloudi clout clout + clouted clout clouts clout + cloven cloven clover clover + cloves clove clovest clovest + clowder clowder clown clown + clownish clownish clowns clown + cloy cloi cloyed cloi + cloying cloi cloyless cloyless + cloyment cloyment cloys cloi + club club clubs club + cluck cluck clung clung + clust clust clusters cluster + clutch clutch clyster clyster + cneius cneiu cnemies cnemi + co co coach coach + coaches coach coachmakers coachmak + coact coact coactive coactiv + coagulate coagul coal coal + coals coal coarse coars + coarsely coars coast coast + coasting coast coasts coast + coat coat coated coat + coats coat cobble cobbl + cobbled cobbl cobbler cobbler + cobham cobham cobloaf cobloaf + cobweb cobweb cobwebs cobweb + cock cock cockatrice cockatric + cockatrices cockatric cockle cockl + cockled cockl cockney cocknei + cockpit cockpit cocks cock + cocksure cocksur coctus coctu + cocytus cocytu cod cod + codding cod codling codl + codpiece codpiec codpieces codpiec + cods cod coelestibus coelestibu + coesar coesar coeur coeur + coffer coffer coffers coffer + coffin coffin coffins coffin + cog cog cogging cog + cogitation cogit cogitations cogit + cognition cognit cognizance cogniz + cogscomb cogscomb cohabitants cohabit + coher coher cohere coher + coherence coher coherent coher + cohorts cohort coif coif + coign coign coil coil + coin coin coinage coinag + coiner coiner coining coin + coins coin col col + colbrand colbrand colchos colcho + cold cold colder colder + coldest coldest coldly coldli + coldness cold coldspur coldspur + colebrook colebrook colic colic + collar collar collars collar + collateral collater colleagued colleagu + collect collect collected collect + collection collect college colleg + colleges colleg collied colli + collier collier colliers collier + collop collop collusion collus + colme colm colmekill colmekil + coloquintida coloquintida color color + colors color colossus colossu + colour colour colourable colour + coloured colour colouring colour + colours colour colt colt + colted colt colts colt + columbine columbin columbines columbin + colville colvil com com + comagene comagen comart comart + comb comb combat combat + combatant combat combatants combat + combated combat combating combat + combin combin combinate combin + combination combin combine combin + combined combin combless combless + combustion combust come come + comedian comedian comedians comedian + comedy comedi comeliness comeli + comely come comer comer + comers comer comes come + comest comest comet comet + cometh cometh comets comet + comfect comfect comfit comfit + comfits comfit comfort comfort + comfortable comfort comforted comfort + comforter comfort comforting comfort + comfortless comfortless comforts comfort + comic comic comical comic + coming come comings come + cominius cominiu comma comma + command command commande command + commanded command commander command + commanders command commanding command + commandment command commandments command + commands command comme comm + commenc commenc commence commenc + commenced commenc commencement commenc + commences commenc commencing commenc + commend commend commendable commend + commendation commend commendations commend + commended commend commending commend + commends commend comment comment + commentaries commentari commenting comment + comments comment commerce commerc + commingled commingl commiseration commiser + commission commiss commissioners commission + commissions commiss commit commit + commits commit committ committ + committed commit committing commit + commix commix commixed commix + commixtion commixt commixture commixtur + commodious commodi commodities commod + commodity commod common common + commonalty commonalti commoner common + commoners common commonly commonli + commons common commonweal commonw + commonwealth commonwealth commotion commot + commotions commot commune commun + communicat communicat communicate commun + communication commun communities commun + community commun comonty comonti + compact compact companies compani + companion companion companions companion + companionship companionship company compani + compar compar comparative compar + compare compar compared compar + comparing compar comparison comparison + comparisons comparison compartner compartn + compass compass compasses compass + compassing compass compassion compass + compassionate compassion compeers compeer + compel compel compell compel + compelled compel compelling compel + compels compel compensation compens + competence compet competency compet + competent compet competitor competitor + competitors competitor compil compil + compile compil compiled compil + complain complain complainer complain + complainest complainest complaining complain + complainings complain complains complain + complaint complaint complaints complaint + complement complement complements complement + complete complet complexion complexion + complexioned complexion complexions complexion + complices complic complies compli + compliment compliment complimental compliment + compliments compliment complot complot + complots complot complotted complot + comply compli compos compo + compose compos composed compos + composition composit compost compost + composture compostur composure composur + compound compound compounded compound + compounds compound comprehend comprehend + comprehended comprehend comprehends comprehend + compremises compremis compris compri + comprising compris compromis compromi + compromise compromis compt compt + comptible comptibl comptrollers comptrol + compulsatory compulsatori compulsion compuls + compulsive compuls compunctious compuncti + computation comput comrade comrad + comrades comrad comutual comutu + con con concave concav + concavities concav conceal conceal + concealed conceal concealing conceal + concealment conceal concealments conceal + conceals conceal conceit conceit + conceited conceit conceitless conceitless + conceits conceit conceiv conceiv + conceive conceiv conceived conceiv + conceives conceiv conceiving conceiv + conception concept conceptions concept + conceptious concepti concern concern + concernancy concern concerneth concerneth + concerning concern concernings concern + concerns concern conclave conclav + conclud conclud conclude conclud + concluded conclud concludes conclud + concluding conclud conclusion conclus + conclusions conclus concolinel concolinel + concord concord concubine concubin + concupiscible concupisc concupy concupi + concur concur concurring concur + concurs concur condemn condemn + condemnation condemn condemned condemn + condemning condemn condemns condemn + condescend condescend condign condign + condition condit conditionally condition + conditions condit condole condol + condolement condol condoling condol + conduce conduc conduct conduct + conducted conduct conducting conduct + conductor conductor conduit conduit + conduits conduit conected conect + coney conei confection confect + confectionary confectionari confections confect + confederacy confederaci confederate confeder + confederates confeder confer confer + conference confer conferr conferr + conferring confer confess confess + confessed confess confesses confess + confesseth confesseth confessing confess + confession confess confessions confess + confessor confessor confidence confid + confident confid confidently confid + confin confin confine confin + confined confin confineless confineless + confiners confin confines confin + confining confin confirm confirm + confirmation confirm confirmations confirm + confirmed confirm confirmer confirm + confirmers confirm confirming confirm + confirmities confirm confirms confirm + confiscate confisc confiscated confisc + confiscation confisc confixed confix + conflict conflict conflicting conflict + conflicts conflict confluence confluenc + conflux conflux conform conform + conformable conform confound confound + confounded confound confounding confound + confounds confound confront confront + confronted confront confus confu + confused confus confusedly confusedli + confusion confus confusions confus + confutation confut confutes confut + congeal congeal congealed congeal + congealment congeal congee conge + conger conger congest congest + congied congi congratulate congratul + congreeing congre congreeted congreet + congregate congreg congregated congreg + congregation congreg congregations congreg + congruent congruent congruing congru + conies coni conjectural conjectur + conjecture conjectur conjectures conjectur + conjoin conjoin conjoined conjoin + conjoins conjoin conjointly conjointli + conjunct conjunct conjunction conjunct + conjunctive conjunct conjur conjur + conjuration conjur conjurations conjur + conjure conjur conjured conjur + conjurer conjur conjurers conjur + conjures conjur conjuring conjur + conjuro conjuro conn conn + connected connect connive conniv + conqu conqu conquer conquer + conquered conquer conquering conquer + conqueror conqueror conquerors conqueror + conquers conquer conquest conquest + conquests conquest conquring conqur + conrade conrad cons con + consanguineous consanguin consanguinity consanguin + conscienc conscienc conscience conscienc + consciences conscienc conscionable conscion + consecrate consecr consecrated consecr + consecrations consecr consent consent + consented consent consenting consent + consents consent consequence consequ + consequences consequ consequently consequ + conserve conserv conserved conserv + conserves conserv consider consid + considerance consider considerate consider + consideration consider considerations consider + considered consid considering consid + considerings consid considers consid + consign consign consigning consign + consist consist consisteth consisteth + consisting consist consistory consistori + consists consist consolate consol + consolation consol consonancy conson + consonant conson consort consort + consorted consort consortest consortest + conspectuities conspectu conspir conspir + conspiracy conspiraci conspirant conspir + conspirator conspir conspirators conspir + conspire conspir conspired conspir + conspirers conspir conspires conspir + conspiring conspir constable constabl + constables constabl constance constanc + constancies constanc constancy constanc + constant constant constantine constantin + constantinople constantinopl constantly constantli + constellation constel constitution constitut + constrain constrain constrained constrain + constraineth constraineth constrains constrain + constraint constraint constring constr + construction construct construe constru + consul consul consuls consul + consulship consulship consulships consulship + consult consult consulting consult + consults consult consum consum + consume consum consumed consum + consumes consum consuming consum + consummate consumm consummation consumm + consumption consumpt consumptions consumpt + contagion contagion contagious contagi + contain contain containing contain + contains contain contaminate contamin + contaminated contamin contemn contemn + contemned contemn contemning contemn + contemns contemn contemplate contempl + contemplation contempl contemplative contempl + contempt contempt contemptible contempt + contempts contempt contemptuous contemptu + contemptuously contemptu contend contend + contended contend contending contend + contendon contendon content content + contenta contenta contented content + contenteth contenteth contention content + contentious contenti contentless contentless + contento contento contents content + contest contest contestation contest + continence contin continency contin + continent contin continents contin + continu continu continual continu + continually continu continuance continu + continuantly continuantli continuate continu + continue continu continued continu + continuer continu continues continu + continuing continu contract contract + contracted contract contracting contract + contraction contract contradict contradict + contradicted contradict contradiction contradict + contradicts contradict contraries contrari + contrarieties contrarieti contrariety contrarieti + contrarious contrari contrariously contrari + contrary contrari contre contr + contribution contribut contributors contributor + contrite contrit contriv contriv + contrive contriv contrived contriv + contriver contriv contrives contriv + contriving contriv control control + controll control controller control + controlling control controlment control + controls control controversy controversi + contumelious contumeli contumeliously contumeli + contumely contum contusions contus + convenience conveni conveniences conveni + conveniency conveni convenient conveni + conveniently conveni convented convent + conventicles conventicl convents convent + convers conver conversant convers + conversation convers conversations convers + converse convers conversed convers + converses convers conversing convers + conversion convers convert convert + converted convert convertest convertest + converting convert convertite convertit + convertites convertit converts convert + convey convei conveyance convey + conveyances convey conveyers convey + conveying convei convict convict + convicted convict convince convinc + convinced convinc convinces convinc + convive conviv convocation convoc + convoy convoi convulsions convuls + cony coni cook cook + cookery cookeri cooks cook + cool cool cooled cool + cooling cool cools cool + coop coop coops coop + cop cop copatain copatain + cope cope cophetua cophetua + copied copi copies copi + copious copiou copper copper + copperspur copperspur coppice coppic + copulation copul copulatives copul + copy copi cor cor + coragio coragio coral coral + coram coram corambus corambu + coranto coranto corantos coranto + corbo corbo cord cord + corded cord cordelia cordelia + cordial cordial cordis cordi + cords cord core core + corin corin corinth corinth + corinthian corinthian coriolanus coriolanu + corioli corioli cork cork + corky corki cormorant cormor + corn corn cornelia cornelia + cornelius corneliu corner corner + corners corner cornerstone cornerston + cornets cornet cornish cornish + corns corn cornuto cornuto + cornwall cornwal corollary corollari + coronal coron coronation coron + coronet coronet coronets coronet + corporal corpor corporals corpor + corporate corpor corpse corps + corpulent corpul correct correct + corrected correct correcting correct + correction correct correctioner correction + corrects correct correspondence correspond + correspondent correspond corresponding correspond + corresponsive correspons corrigible corrig + corrival corriv corrivals corriv + corroborate corrobor corrosive corros + corrupt corrupt corrupted corrupt + corrupter corrupt corrupters corrupt + corruptible corrupt corruptibly corrupt + corrupting corrupt corruption corrupt + corruptly corruptli corrupts corrupt + corse cors corses cors + corslet corslet cosmo cosmo + cost cost costard costard + costermongers costermong costlier costlier + costly costli costs cost + cot cot cote cote + coted cote cotsall cotsal + cotsole cotsol cotswold cotswold + cottage cottag cottages cottag + cotus cotu couch couch + couched couch couching couch + couchings couch coude coud + cough cough coughing cough + could could couldst couldst + coulter coulter council council + councillor councillor councils council + counsel counsel counsell counsel + counsellor counsellor counsellors counsellor + counselor counselor counselors counselor + counsels counsel count count + counted count countenanc countenanc + countenance counten countenances counten + counter counter counterchange counterchang + countercheck countercheck counterfeit counterfeit + counterfeited counterfeit counterfeiting counterfeit + counterfeitly counterfeitli counterfeits counterfeit + countermand countermand countermands countermand + countermines countermin counterpart counterpart + counterpoints counterpoint counterpois counterpoi + counterpoise counterpois counters counter + countervail countervail countess countess + countesses countess counties counti + counting count countless countless + countries countri countrv countrv + country countri countryman countryman + countrymen countrymen counts count + county counti couper couper + couple coupl coupled coupl + couplement couplement couples coupl + couplet couplet couplets couplet + cour cour courage courag + courageous courag courageously courag + courages courag courier courier + couriers courier couronne couronn + cours cour course cours + coursed cours courser courser + coursers courser courses cours + coursing cours court court + courted court courteous courteou + courteously courteous courtesan courtesan + courtesies courtesi courtesy courtesi + courtezan courtezan courtezans courtezan + courtier courtier courtiers courtier + courtlike courtlik courtly courtli + courtney courtnei courts court + courtship courtship cousin cousin + cousins cousin couterfeit couterfeit + coutume coutum covenant coven + covenants coven covent covent + coventry coventri cover cover + covered cover covering cover + coverlet coverlet covers cover + covert covert covertly covertli + coverture covertur covet covet + coveted covet coveting covet + covetings covet covetous covet + covetously covet covetousness covet + covets covet cow cow + coward coward cowarded coward + cowardice cowardic cowardly cowardli + cowards coward cowardship cowardship + cowish cowish cowl cowl + cowslip cowslip cowslips cowslip + cox cox coxcomb coxcomb + coxcombs coxcomb coy coi + coystrill coystril coz coz + cozen cozen cozenage cozenag + cozened cozen cozener cozen + cozeners cozen cozening cozen + coziers cozier crab crab + crabbed crab crabs crab + crack crack cracked crack + cracker cracker crackers cracker + cracking crack cracks crack + cradle cradl cradled cradl + cradles cradl craft craft + crafted craft craftied crafti + craftier craftier craftily craftili + crafts craft craftsmen craftsmen + crafty crafti cram cram + cramm cramm cramp cramp + cramps cramp crams cram + cranking crank cranks crank + cranmer cranmer crannied cranni + crannies cranni cranny cranni + crants crant crare crare + crash crash crassus crassu + crav crav crave crave + craved crave craven craven + cravens craven craves crave + craveth craveth craving crave + crawl crawl crawling crawl + crawls crawl craz craz + crazed craze crazy crazi + creaking creak cream cream + create creat created creat + creates creat creating creat + creation creation creator creator + creature creatur creatures creatur + credence credenc credent credent + credible credibl credit credit + creditor creditor creditors creditor + credo credo credulity credul + credulous credul creed creed + creek creek creeks creek + creep creep creeping creep + creeps creep crept crept + crescent crescent crescive cresciv + cressets cresset cressid cressid + cressida cressida cressids cressid + cressy cressi crest crest + crested crest crestfall crestfal + crestless crestless crests crest + cretan cretan crete crete + crevice crevic crew crew + crews crew crib crib + cribb cribb cribs crib + cricket cricket crickets cricket + cried cri criedst criedst + crier crier cries cri + criest criest crieth crieth + crime crime crimeful crime + crimeless crimeless crimes crime + criminal crimin crimson crimson + cringe cring cripple crippl + crisp crisp crisped crisp + crispian crispian crispianus crispianu + crispin crispin critic critic + critical critic critics critic + croak croak croaking croak + croaks croak crocodile crocodil + cromer cromer cromwell cromwel + crone crone crook crook + crookback crookback crooked crook + crooking crook crop crop + cropp cropp crosby crosbi + cross cross crossed cross + crosses cross crossest crossest + crossing cross crossings cross + crossly crossli crossness cross + crost crost crotchets crotchet + crouch crouch crouching crouch + crow crow crowd crowd + crowded crowd crowding crowd + crowds crowd crowflowers crowflow + crowing crow crowkeeper crowkeep + crown crown crowned crown + crowner crowner crownet crownet + crownets crownet crowning crown + crowns crown crows crow + crudy crudi cruel cruel + cruell cruell crueller crueller + cruelly cruelli cruels cruel + cruelty cruelti crum crum + crumble crumbl crumbs crumb + crupper crupper crusadoes crusado + crush crush crushed crush + crushest crushest crushing crush + crust crust crusts crust + crusty crusti crutch crutch + crutches crutch cry cry + crying cry crystal crystal + crystalline crystallin crystals crystal + cub cub cubbert cubbert + cubiculo cubiculo cubit cubit + cubs cub cuckold cuckold + cuckoldly cuckoldli cuckolds cuckold + cuckoo cuckoo cucullus cucullu + cudgel cudgel cudgeled cudgel + cudgell cudgel cudgelling cudgel + cudgels cudgel cue cue + cues cue cuff cuff + cuffs cuff cuique cuiqu + cull cull culling cull + cullion cullion cullionly cullionli + cullions cullion culpable culpabl + culverin culverin cum cum + cumber cumber cumberland cumberland + cunning cun cunningly cunningli + cunnings cun cuore cuor + cup cup cupbearer cupbear + cupboarding cupboard cupid cupid + cupids cupid cuppele cuppel + cups cup cur cur + curan curan curate curat + curb curb curbed curb + curbing curb curbs curb + curd curd curdied curdi + curds curd cure cure + cured cure cureless cureless + curer curer cures cure + curfew curfew curing cure + curio curio curiosity curios + curious curiou curiously curious + curl curl curled curl + curling curl curls curl + currance curranc currants currant + current current currents current + currish currish curry curri + curs cur curse curs + cursed curs curses curs + cursies cursi cursing curs + cursorary cursorari curst curst + curster curster curstest curstest + curstness curst cursy cursi + curtail curtail curtain curtain + curtains curtain curtal curtal + curtis curti curtle curtl + curtsied curtsi curtsies curtsi + curtsy curtsi curvet curvet + curvets curvet cushes cush + cushion cushion cushions cushion + custalorum custalorum custard custard + custody custodi custom custom + customary customari customed custom + customer custom customers custom + customs custom custure custur + cut cut cutler cutler + cutpurse cutpurs cutpurses cutpurs + cuts cut cutter cutter + cutting cut cuttle cuttl + cxsar cxsar cyclops cyclop + cydnus cydnu cygnet cygnet + cygnets cygnet cym cym + cymbals cymbal cymbeline cymbelin + cyme cyme cynic cynic + cynthia cynthia cypress cypress + cypriot cypriot cyprus cypru + cyrus cyru cytherea cytherea + d d dabbled dabbl + dace dace dad dad + daedalus daedalu daemon daemon + daff daff daffed daf + daffest daffest daffodils daffodil + dagger dagger daggers dagger + dagonet dagonet daily daili + daintier daintier dainties dainti + daintiest daintiest daintily daintili + daintiness dainti daintry daintri + dainty dainti daisied daisi + daisies daisi daisy daisi + dale dale dalliance dallianc + dallied dalli dallies dalli + dally dalli dallying dalli + dalmatians dalmatian dam dam + damage damag damascus damascu + damask damask damasked damask + dame dame dames dame + damm damm damn damn + damnable damnabl damnably damnabl + damnation damnat damned damn + damns damn damoiselle damoisel + damon damon damosella damosella + damp damp dams dam + damsel damsel damsons damson + dan dan danc danc + dance danc dancer dancer + dances danc dancing danc + dandle dandl dandy dandi + dane dane dang dang + danger danger dangerous danger + dangerously danger dangers danger + dangling dangl daniel daniel + danish danish dank dank + dankish dankish danskers dansker + daphne daphn dappled dappl + dapples dappl dar dar + dardan dardan dardanian dardanian + dardanius dardaniu dare dare + dared dare dareful dare + dares dare darest darest + daring dare darius dariu + dark dark darken darken + darkening darken darkens darken + darker darker darkest darkest + darkling darkl darkly darkli + darkness dark darling darl + darlings darl darnel darnel + darraign darraign dart dart + darted dart darter darter + dartford dartford darting dart + darts dart dash dash + dashes dash dashing dash + dastard dastard dastards dastard + dat dat datchet datchet + date date dated date + dateless dateless dates date + daub daub daughter daughter + daughters daughter daunt daunt + daunted daunt dauntless dauntless + dauphin dauphin daventry daventri + davy davi daw daw + dawn dawn dawning dawn + daws daw day dai + daylight daylight days dai + dazzle dazzl dazzled dazzl + dazzling dazzl de de + dead dead deadly deadli + deaf deaf deafing deaf + deafness deaf deafs deaf + deal deal dealer dealer + dealers dealer dealest dealest + dealing deal dealings deal + deals deal dealt dealt + dean dean deanery deaneri + dear dear dearer dearer + dearest dearest dearly dearli + dearness dear dears dear + dearth dearth dearths dearth + death death deathbed deathb + deathful death deaths death + deathsman deathsman deathsmen deathsmen + debarred debar debase debas + debate debat debated debat + debatement debat debateth debateth + debating debat debauch debauch + debile debil debility debil + debitor debitor debonair debonair + deborah deborah debosh debosh + debt debt debted debt + debtor debtor debtors debtor + debts debt debuty debuti + decay decai decayed decai + decayer decay decaying decai + decays decai deceas decea + decease deceas deceased deceas + deceit deceit deceitful deceit + deceits deceit deceiv deceiv + deceivable deceiv deceive deceiv + deceived deceiv deceiver deceiv + deceivers deceiv deceives deceiv + deceivest deceivest deceiveth deceiveth + deceiving deceiv december decemb + decent decent deceptious decepti + decerns decern decide decid + decides decid decimation decim + decipher deciph deciphers deciph + decision decis decius deciu + deck deck decking deck + decks deck deckt deckt + declare declar declares declar + declension declens declensions declens + declin declin decline declin + declined declin declines declin + declining declin decoct decoct + decorum decorum decreas decrea + decrease decreas decreasing decreas + decree decre decreed decre + decrees decre decrepit decrepit + dedicate dedic dedicated dedic + dedicates dedic dedication dedic + deed deed deedless deedless + deeds deed deem deem + deemed deem deep deep + deeper deeper deepest deepest + deeply deepli deeps deep + deepvow deepvow deer deer + deesse deess defac defac + deface defac defaced defac + defacer defac defacers defac + defacing defac defam defam + default default defeat defeat + defeated defeat defeats defeat + defeatures defeatur defect defect + defective defect defects defect + defence defenc defences defenc + defend defend defendant defend + defended defend defender defend + defenders defend defending defend + defends defend defense defens + defensible defens defensive defens + defer defer deferr deferr + defiance defianc deficient defici + defied defi defies defi + defil defil defile defil + defiler defil defiles defil + defiling defil define defin + definement defin definite definit + definitive definit definitively definit + deflow deflow deflower deflow + deflowered deflow deform deform + deformed deform deformities deform + deformity deform deftly deftli + defunct defunct defunction defunct + defuse defus defy defi + defying defi degenerate degener + degraded degrad degree degre + degrees degre deified deifi + deifying deifi deign deign + deigned deign deiphobus deiphobu + deities deiti deity deiti + deja deja deject deject + dejected deject delabreth delabreth + delay delai delayed delai + delaying delai delays delai + delectable delect deliberate deliber + delicate delic delicates delic + delicious delici deliciousness delici + delight delight delighted delight + delightful delight delights delight + delinquents delinqu deliv deliv + deliver deliv deliverance deliver + delivered deliv delivering deliv + delivers deliv delivery deliveri + delphos delpho deluded delud + deluding delud deluge delug + delve delv delver delver + delves delv demand demand + demanded demand demanding demand + demands demand demean demean + demeanor demeanor demeanour demeanour + demerits demerit demesnes demesn + demetrius demetriu demi demi + demigod demigod demise demis + demoiselles demoisel demon demon + demonstrable demonstr demonstrate demonstr + demonstrated demonstr demonstrating demonstr + demonstration demonstr demonstrative demonstr + demure demur demurely demur + demuring demur den den + denay denai deni deni + denial denial denials denial + denied deni denier denier + denies deni deniest deniest + denis deni denmark denmark + dennis denni denny denni + denote denot denoted denot + denotement denot denounc denounc + denounce denounc denouncing denounc + dens den denunciation denunci + deny deni denying deni + deo deo depart depart + departed depart departest departest + departing depart departure departur + depeche depech depend depend + dependant depend dependants depend + depended depend dependence depend + dependences depend dependency depend + dependent depend dependents depend + depender depend depending depend + depends depend deplore deplor + deploring deplor depopulate depopul + depos depo depose depos + deposed depos deposing depos + depositaries depositari deprav deprav + depravation deprav deprave deprav + depraved deprav depraves deprav + depress depress depriv depriv + deprive depriv depth depth + depths depth deputation deput + depute deput deputed deput + deputies deputi deputing deput + deputy deputi deracinate deracin + derby derbi dercetas derceta + dere dere derides derid + derision deris deriv deriv + derivation deriv derivative deriv + derive deriv derived deriv + derives deriv derogate derog + derogately derog derogation derog + des de desartless desartless + descant descant descend descend + descended descend descending descend + descends descend descension descens + descent descent descents descent + describe describ described describ + describes describ descried descri + description descript descriptions descript + descry descri desdemon desdemon + desdemona desdemona desert desert + deserts desert deserv deserv + deserve deserv deserved deserv + deservedly deservedli deserver deserv + deservers deserv deserves deserv + deservest deservest deserving deserv + deservings deserv design design + designment design designments design + designs design desir desir + desire desir desired desir + desirers desir desires desir + desirest desirest desiring desir + desirous desir desist desist + desk desk desolate desol + desolation desol desp desp + despair despair despairing despair + despairs despair despatch despatch + desperate desper desperately desper + desperation desper despis despi + despise despis despised despis + despiser despis despiseth despiseth + despising despis despite despit + despiteful despit despoiled despoil + dest dest destin destin + destined destin destinies destini + destiny destini destitute destitut + destroy destroi destroyed destroi + destroyer destroy destroyers destroy + destroying destroi destroys destroi + destruction destruct destructions destruct + det det detain detain + detains detain detect detect + detected detect detecting detect + detection detect detector detector + detects detect detention detent + determin determin determinate determin + determination determin determinations determin + determine determin determined determin + determines determin detest detest + detestable detest detested detest + detesting detest detests detest + detract detract detraction detract + detractions detract deucalion deucalion + deuce deuc deum deum + deux deux devant devant + devesting devest device devic + devices devic devil devil + devilish devilish devils devil + devis devi devise devis + devised devis devises devis + devising devis devoid devoid + devonshire devonshir devote devot + devoted devot devotion devot + devour devour devoured devour + devourers devour devouring devour + devours devour devout devout + devoutly devoutli dew dew + dewberries dewberri dewdrops dewdrop + dewlap dewlap dewlapp dewlapp + dews dew dewy dewi + dexter dexter dexteriously dexteri + dexterity dexter di di + diable diabl diablo diablo + diadem diadem dial dial + dialect dialect dialogue dialogu + dialogued dialogu dials dial + diameter diamet diamond diamond + diamonds diamond dian dian + diana diana diaper diaper + dibble dibbl dic dic + dice dice dicers dicer + dich dich dick dick + dickens dicken dickon dickon + dicky dicki dictator dictat + diction diction dictynna dictynna + did did diddle diddl + didest didest dido dido + didst didst die die + died di diedst diedst + dies di diest diest + diet diet dieted diet + dieter dieter dieu dieu + diff diff differ differ + difference differ differences differ + differency differ different differ + differing differ differs differ + difficile difficil difficult difficult + difficulties difficulti difficulty difficulti + diffidence diffid diffidences diffid + diffus diffu diffused diffus + diffusest diffusest dig dig + digest digest digested digest + digestion digest digestions digest + digg digg digging dig + dighton dighton dignified dignifi + dignifies dignifi dignify dignifi + dignities digniti dignity digniti + digress digress digressing digress + digression digress digs dig + digt digt dilate dilat + dilated dilat dilations dilat + dilatory dilatori dild dild + dildos dildo dilemma dilemma + dilemmas dilemma diligence dilig + diligent dilig diluculo diluculo + dim dim dimension dimens + dimensions dimens diminish diminish + diminishing diminish diminution diminut + diminutive diminut diminutives diminut + dimm dimm dimmed dim + dimming dim dimpled dimpl + dimples dimpl dims dim + din din dine dine + dined dine diner diner + dines dine ding ding + dining dine dinner dinner + dinners dinner dinnertime dinnertim + dint dint diomed diom + diomede diomed diomedes diomed + dion dion dip dip + dipp dipp dipping dip + dips dip dir dir + dire dire direct direct + directed direct directing direct + direction direct directions direct + directitude directitud directive direct + directly directli directs direct + direful dire direness dire + direst direst dirge dirg + dirges dirg dirt dirt + dirty dirti dis di + disability disabl disable disabl + disabled disabl disabling disabl + disadvantage disadvantag disagree disagre + disallow disallow disanimates disanim + disannul disannul disannuls disannul + disappointed disappoint disarm disarm + disarmed disarm disarmeth disarmeth + disarms disarm disaster disast + disasters disast disastrous disastr + disbench disbench disbranch disbranch + disburdened disburden disburs disbur + disburse disburs disbursed disburs + discandy discandi discandying discandi + discard discard discarded discard + discase discas discased discas + discern discern discerner discern + discerning discern discernings discern + discerns discern discharg discharg + discharge discharg discharged discharg + discharging discharg discipled discipl + disciples discipl disciplin disciplin + discipline disciplin disciplined disciplin + disciplines disciplin disclaim disclaim + disclaiming disclaim disclaims disclaim + disclos disclo disclose disclos + disclosed disclos discloses disclos + discolour discolour discoloured discolour + discolours discolour discomfit discomfit + discomfited discomfit discomfiture discomfitur + discomfort discomfort discomfortable discomfort + discommend discommend disconsolate disconsol + discontent discont discontented discont + discontentedly discontentedli discontenting discont + discontents discont discontinue discontinu + discontinued discontinu discord discord + discordant discord discords discord + discourse discours discoursed discours + discourser discours discourses discours + discoursive discours discourtesy discourtesi + discov discov discover discov + discovered discov discoverers discover + discoveries discoveri discovering discov + discovers discov discovery discoveri + discredit discredit discredited discredit + discredits discredit discreet discreet + discreetly discreetli discretion discret + discretions discret discuss discuss + disdain disdain disdained disdain + disdaineth disdaineth disdainful disdain + disdainfully disdainfulli disdaining disdain + disdains disdain disdnguish disdnguish + diseas disea disease diseas + diseased diseas diseases diseas + disedg disedg disembark disembark + disfigure disfigur disfigured disfigur + disfurnish disfurnish disgorge disgorg + disgrac disgrac disgrace disgrac + disgraced disgrac disgraceful disgrac + disgraces disgrac disgracing disgrac + disgracious disgraci disguis disgui + disguise disguis disguised disguis + disguiser disguis disguises disguis + disguising disguis dish dish + dishabited dishabit dishclout dishclout + dishearten dishearten disheartens dishearten + dishes dish dishonest dishonest + dishonestly dishonestli dishonesty dishonesti + dishonor dishonor dishonorable dishonor + dishonors dishonor dishonour dishonour + dishonourable dishonour dishonoured dishonour + dishonours dishonour disinherit disinherit + disinherited disinherit disjoin disjoin + disjoining disjoin disjoins disjoin + disjoint disjoint disjunction disjunct + dislik dislik dislike dislik + disliken disliken dislikes dislik + dislimns dislimn dislocate disloc + dislodg dislodg disloyal disloy + disloyalty disloyalti dismal dismal + dismantle dismantl dismantled dismantl + dismask dismask dismay dismai + dismayed dismai dismemb dismemb + dismember dismemb dismes dism + dismiss dismiss dismissed dismiss + dismissing dismiss dismission dismiss + dismount dismount dismounted dismount + disnatur disnatur disobedience disobedi + disobedient disobedi disobey disobei + disobeys disobei disorb disorb + disorder disord disordered disord + disorderly disorderli disorders disord + disparage disparag disparagement disparag + disparagements disparag dispark dispark + dispatch dispatch dispensation dispens + dispense dispens dispenses dispens + dispers disper disperse dispers + dispersed dispers dispersedly dispersedli + dispersing dispers dispiteous dispit + displac displac displace displac + displaced displac displant displant + displanting displant display displai + displayed displai displeas displea + displease displeas displeased displeas + displeasing displeas displeasure displeasur + displeasures displeasur disponge dispong + disport disport disports disport + dispos dispo dispose dispos + disposed dispos disposer dispos + disposing dispos disposition disposit + dispositions disposit dispossess dispossess + dispossessing dispossess disprais disprai + dispraise disprais dispraising disprais + dispraisingly dispraisingli dispropertied disproperti + disproportion disproport disproportioned disproport + disprov disprov disprove disprov + disproved disprov dispursed dispurs + disputable disput disputation disput + disputations disput dispute disput + disputed disput disputes disput + disputing disput disquantity disquant + disquiet disquiet disquietly disquietli + disrelish disrelish disrobe disrob + disseat disseat dissemble dissembl + dissembled dissembl dissembler dissembl + dissemblers dissembl dissembling dissembl + dissembly dissembl dissension dissens + dissensions dissens dissentious dissenti + dissever dissev dissipation dissip + dissolute dissolut dissolutely dissolut + dissolution dissolut dissolutions dissolut + dissolv dissolv dissolve dissolv + dissolved dissolv dissolves dissolv + dissuade dissuad dissuaded dissuad + distaff distaff distaffs distaff + distain distain distains distain + distance distanc distant distant + distaste distast distasted distast + distasteful distast distemp distemp + distemper distemp distemperature distemperatur + distemperatures distemperatur distempered distemp + distempering distemp distil distil + distill distil distillation distil + distilled distil distills distil + distilment distil distinct distinct + distinction distinct distinctly distinctli + distingue distingu distinguish distinguish + distinguishes distinguish distinguishment distinguish + distract distract distracted distract + distractedly distractedli distraction distract + distractions distract distracts distract + distrain distrain distraught distraught + distress distress distressed distress + distresses distress distressful distress + distribute distribut distributed distribut + distribution distribut distrust distrust + distrustful distrust disturb disturb + disturbed disturb disturbers disturb + disturbing disturb disunite disunit + disvalued disvalu disvouch disvouch + dit dit ditch ditch + ditchers ditcher ditches ditch + dites dite ditties ditti + ditty ditti diurnal diurnal + div div dive dive + diver diver divers diver + diversely divers diversity divers + divert divert diverted divert + diverts divert dives dive + divest divest dividable divid + dividant divid divide divid + divided divid divides divid + divideth divideth divin divin + divination divin divine divin + divinely divin divineness divin + diviner divin divines divin + divinest divinest divining divin + divinity divin division divis + divisions divis divorc divorc + divorce divorc divorced divorc + divorcement divorc divorcing divorc + divulg divulg divulge divulg + divulged divulg divulging divulg + dizy dizi dizzy dizzi + do do doating doat + dobbin dobbin dock dock + docks dock doct doct + doctor doctor doctors doctor + doctrine doctrin document document + dodge dodg doe doe + doer doer doers doer + does doe doest doest + doff doff dog dog + dogberry dogberri dogfish dogfish + dogg dogg dogged dog + dogs dog doigts doigt + doing do doings do + doit doit doits doit + dolabella dolabella dole dole + doleful dole doll doll + dollar dollar dollars dollar + dolor dolor dolorous dolor + dolour dolour dolours dolour + dolphin dolphin dolt dolt + dolts dolt domestic domest + domestics domest dominance domin + dominations domin dominator domin + domine domin domineer domin + domineering domin dominical domin + dominion dominion dominions dominion + domitius domitiu dommelton dommelton + don don donalbain donalbain + donation donat donc donc + doncaster doncast done done + dong dong donn donn + donne donn donner donner + donnerai donnerai doom doom + doomsday doomsdai door door + doorkeeper doorkeep doors door + dorcas dorca doreus doreu + doricles doricl dormouse dormous + dorothy dorothi dorset dorset + dorsetshire dorsetshir dost dost + dotage dotag dotant dotant + dotard dotard dotards dotard + dote dote doted dote + doters doter dotes dote + doteth doteth doth doth + doting dote double doubl + doubled doubl doubleness doubl + doubler doubler doublet doublet + doublets doublet doubling doubl + doubly doubli doubt doubt + doubted doubt doubtful doubt + doubtfully doubtfulli doubting doubt + doubtless doubtless doubts doubt + doug doug dough dough + doughty doughti doughy doughi + douglas dougla dout dout + doute dout douts dout + dove dove dovehouse dovehous + dover dover doves dove + dow dow dowager dowag + dowdy dowdi dower dower + dowerless dowerless dowers dower + dowlas dowla dowle dowl + down down downfall downfal + downright downright downs down + downstairs downstair downtrod downtrod + downward downward downwards downward + downy downi dowries dowri + dowry dowri dowsabel dowsabel + doxy doxi dozed doze + dozen dozen dozens dozen + dozy dozi drab drab + drabbing drab drabs drab + drachma drachma drachmas drachma + draff draff drag drag + dragg dragg dragged drag + dragging drag dragon dragon + dragonish dragonish dragons dragon + drain drain drained drain + drains drain drake drake + dram dram dramatis dramati + drank drank draught draught + draughts draught drave drave + draw draw drawbridge drawbridg + drawer drawer drawers drawer + draweth draweth drawing draw + drawling drawl drawn drawn + draws draw drayman drayman + draymen draymen dread dread + dreaded dread dreadful dread + dreadfully dreadfulli dreading dread + dreads dread dream dream + dreamer dreamer dreamers dreamer + dreaming dream dreams dream + dreamt dreamt drearning drearn + dreary dreari dreg dreg + dregs dreg drench drench + drenched drench dress dress + dressed dress dresser dresser + dressing dress dressings dress + drest drest drew drew + dribbling dribbl dried dri + drier drier dries dri + drift drift drily drili + drink drink drinketh drinketh + drinking drink drinkings drink + drinks drink driv driv + drive drive drivelling drivel + driven driven drives drive + driveth driveth driving drive + drizzle drizzl drizzled drizzl + drizzles drizzl droit droit + drollery drolleri dromio dromio + dromios dromio drone drone + drones drone droop droop + droopeth droopeth drooping droop + droops droop drop drop + dropheir dropheir droplets droplet + dropp dropp dropper dropper + droppeth droppeth dropping drop + droppings drop drops drop + dropsied dropsi dropsies dropsi + dropsy dropsi dropt dropt + dross dross drossy drossi + drought drought drove drove + droven droven drovier drovier + drown drown drowned drown + drowning drown drowns drown + drows drow drowse drows + drowsily drowsili drowsiness drowsi + drowsy drowsi drudge drudg + drudgery drudgeri drudges drudg + drug drug drugg drugg + drugs drug drum drum + drumble drumbl drummer drummer + drumming drum drums drum + drunk drunk drunkard drunkard + drunkards drunkard drunken drunken + drunkenly drunkenli drunkenness drunken + dry dry dryness dryness + dst dst du du + dub dub dubb dubb + ducat ducat ducats ducat + ducdame ducdam duchess duchess + duchies duchi duchy duchi + duck duck ducking duck + ducks duck dudgeon dudgeon + due due duellist duellist + duello duello duer duer + dues due duff duff + dug dug dugs dug + duke duke dukedom dukedom + dukedoms dukedom dukes duke + dulcet dulcet dulche dulch + dull dull dullard dullard + duller duller dullest dullest + dulling dull dullness dull + dulls dull dully dulli + dulness dul duly duli + dumain dumain dumb dumb + dumbe dumb dumbly dumbl + dumbness dumb dump dump + dumps dump dun dun + duncan duncan dung dung + dungeon dungeon dungeons dungeon + dunghill dunghil dunghills dunghil + dungy dungi dunnest dunnest + dunsinane dunsinan dunsmore dunsmor + dunstable dunstabl dupp dupp + durance duranc during dure + durst durst dusky duski + dust dust dusted dust + dusty dusti dutch dutch + dutchman dutchman duteous duteou + duties duti dutiful duti + duty duti dwarf dwarf + dwarfish dwarfish dwell dwell + dwellers dweller dwelling dwell + dwells dwell dwelt dwelt + dwindle dwindl dy dy + dye dye dyed dy + dyer dyer dying dy + e e each each + eager eager eagerly eagerli + eagerness eager eagle eagl + eagles eagl eaning ean + eanlings eanl ear ear + earing ear earl earl + earldom earldom earlier earlier + earliest earliest earliness earli + earls earl early earli + earn earn earned earn + earnest earnest earnestly earnestli + earnestness earnest earns earn + ears ear earth earth + earthen earthen earthlier earthlier + earthly earthli earthquake earthquak + earthquakes earthquak earthy earthi + eas ea ease eas + eased eas easeful eas + eases eas easier easier + easiest easiest easiliest easiliest + easily easili easiness easi + easing eas east east + eastcheap eastcheap easter easter + eastern eastern eastward eastward + easy easi eat eat + eaten eaten eater eater + eaters eater eating eat + eats eat eaux eaux + eaves eav ebb ebb + ebbing eb ebbs ebb + ebon ebon ebony eboni + ebrew ebrew ecce ecc + echapper echapp echo echo + echoes echo eclips eclip + eclipse eclips eclipses eclips + ecolier ecoli ecoutez ecoutez + ecstacy ecstaci ecstasies ecstasi + ecstasy ecstasi ecus ecu + eden eden edg edg + edgar edgar edge edg + edged edg edgeless edgeless + edges edg edict edict + edicts edict edifice edific + edifices edific edified edifi + edifies edifi edition edit + edm edm edmund edmund + edmunds edmund edmundsbury edmundsburi + educate educ educated educ + education educ edward edward + eel eel eels eel + effect effect effected effect + effectless effectless effects effect + effectual effectu effectually effectu + effeminate effemin effigies effigi + effus effu effuse effus + effusion effus eftest eftest + egal egal egally egal + eget eget egeus egeu + egg egg eggs egg + eggshell eggshel eglamour eglamour + eglantine eglantin egma egma + ego ego egregious egregi + egregiously egregi egress egress + egypt egypt egyptian egyptian + egyptians egyptian eie eie + eight eight eighteen eighteen + eighth eighth eightpenny eightpenni + eighty eighti eisel eisel + either either eject eject + eke ek el el + elbe elb elbow elbow + elbows elbow eld eld + elder elder elders elder + eldest eldest eleanor eleanor + elect elect elected elect + election elect elegancy eleg + elegies elegi element element + elements element elephant eleph + elephants eleph elevated elev + eleven eleven eleventh eleventh + elf elf elflocks elflock + eliads eliad elinor elinor + elizabeth elizabeth ell ell + elle ell ellen ellen + elm elm eloquence eloqu + eloquent eloqu else els + elsewhere elsewher elsinore elsinor + eltham eltham elves elv + elvish elvish ely eli + elysium elysium em em + emballing embal embalm embalm + embalms embalm embark embark + embarked embark embarquements embarqu + embassade embassad embassage embassag + embassies embassi embassy embassi + embattailed embattail embattl embattl + embattle embattl embay embai + embellished embellish embers ember + emblaze emblaz emblem emblem + emblems emblem embodied embodi + embold embold emboldens embolden + emboss emboss embossed emboss + embounded embound embowel embowel + embowell embowel embrac embrac + embrace embrac embraced embrac + embracement embrac embracements embrac + embraces embrac embracing embrac + embrasures embrasur embroider embroid + embroidery embroideri emhracing emhrac + emilia emilia eminence emin + eminent emin eminently emin + emmanuel emmanuel emnity emniti + empale empal emperal emper + emperess emperess emperial emperi + emperor emperor empery emperi + emphasis emphasi empire empir + empirics empir empiricutic empiricut + empleached empleach employ emploi + employed emploi employer employ + employment employ employments employ + empoison empoison empress empress + emptied empti emptier emptier + empties empti emptiness empti + empty empti emptying empti + emulate emul emulation emul + emulations emul emulator emul + emulous emul en en + enact enact enacted enact + enacts enact enactures enactur + enamell enamel enamelled enamel + enamour enamour enamoured enamour + enanmour enanmour encamp encamp + encamped encamp encave encav + enceladus enceladu enchaf enchaf + enchafed enchaf enchant enchant + enchanted enchant enchanting enchant + enchantingly enchantingli enchantment enchant + enchantress enchantress enchants enchant + enchas encha encircle encircl + encircled encircl enclos enclo + enclose enclos enclosed enclos + encloses enclos encloseth encloseth + enclosing enclos enclouded encloud + encompass encompass encompassed encompass + encompasseth encompasseth encompassment encompass + encore encor encorporal encorpor + encount encount encounter encount + encountered encount encounters encount + encourage encourag encouraged encourag + encouragement encourag encrimsoned encrimson + encroaching encroach encumb encumb + end end endamage endamag + endamagement endamag endanger endang + endart endart endear endear + endeared endear endeavour endeavour + endeavours endeavour ended end + ender ender ending end + endings end endite endit + endless endless endow endow + endowed endow endowments endow + endows endow ends end + endu endu endue endu + endur endur endurance endur + endure endur endured endur + endures endur enduring endur + endymion endymion eneas enea + enemies enemi enemy enemi + enernies enerni enew enew + enfeebled enfeebl enfeebles enfeebl + enfeoff enfeoff enfetter enfett + enfoldings enfold enforc enforc + enforce enforc enforced enforc + enforcedly enforcedli enforcement enforc + enforces enforc enforcest enforcest + enfranched enfranch enfranchis enfranchi + enfranchise enfranchis enfranchised enfranchis + enfranchisement enfranchis enfreed enfre + enfreedoming enfreedom engag engag + engage engag engaged engag + engagements engag engaging engag + engaol engaol engend engend + engender engend engenders engend + engilds engild engine engin + engineer engin enginer engin + engines engin engirt engirt + england england english english + englishman englishman englishmen englishmen + engluts englut englutted englut + engraffed engraf engraft engraft + engrafted engraft engrav engrav + engrave engrav engross engross + engrossed engross engrossest engrossest + engrossing engross engrossments engross + enguard enguard enigma enigma + enigmatical enigmat enjoin enjoin + enjoined enjoin enjoy enjoi + enjoyed enjoi enjoyer enjoy + enjoying enjoi enjoys enjoi + enkindle enkindl enkindled enkindl + enlard enlard enlarg enlarg + enlarge enlarg enlarged enlarg + enlargement enlarg enlargeth enlargeth + enlighten enlighten enlink enlink + enmesh enmesh enmities enmiti + enmity enmiti ennoble ennobl + ennobled ennobl enobarb enobarb + enobarbus enobarbu enon enon + enormity enorm enormous enorm + enough enough enow enow + enpatron enpatron enpierced enpierc + enquir enquir enquire enquir + enquired enquir enrag enrag + enrage enrag enraged enrag + enrages enrag enrank enrank + enrapt enrapt enrich enrich + enriched enrich enriches enrich + enridged enridg enrings enr + enrob enrob enrobe enrob + enroll enrol enrolled enrol + enrooted enroot enrounded enround + enschedul enschedul ensconce ensconc + ensconcing ensconc enseamed enseam + ensear ensear enseigne enseign + enseignez enseignez ensemble ensembl + enshelter enshelt enshielded enshield + enshrines enshrin ensign ensign + ensigns ensign enskied enski + ensman ensman ensnare ensnar + ensnared ensnar ensnareth ensnareth + ensteep ensteep ensu ensu + ensue ensu ensued ensu + ensues ensu ensuing ensu + enswathed enswath ent ent + entail entail entame entam + entangled entangl entangles entangl + entendre entendr enter enter + entered enter entering enter + enterprise enterpris enterprises enterpris + enters enter entertain entertain + entertained entertain entertainer entertain + entertaining entertain entertainment entertain + entertainments entertain enthrall enthral + enthralled enthral enthron enthron + enthroned enthron entice entic + enticements entic enticing entic + entire entir entirely entir + entitle entitl entitled entitl + entitling entitl entomb entomb + entombed entomb entrails entrail + entrance entranc entrances entranc + entrap entrap entrapp entrapp + entre entr entreat entreat + entreated entreat entreaties entreati + entreating entreat entreatments entreat + entreats entreat entreaty entreati + entrench entrench entry entri + entwist entwist envelop envelop + envenom envenom envenomed envenom + envenoms envenom envied envi + envies envi envious enviou + enviously envious environ environ + environed environ envoy envoi + envy envi envying envi + enwheel enwheel enwombed enwomb + enwraps enwrap ephesian ephesian + ephesians ephesian ephesus ephesu + epicure epicur epicurean epicurean + epicures epicur epicurism epicur + epicurus epicuru epidamnum epidamnum + epidaurus epidauru epigram epigram + epilepsy epilepsi epileptic epilept + epilogue epilogu epilogues epilogu + epistles epistl epistrophus epistrophu + epitaph epitaph epitaphs epitaph + epithet epithet epitheton epitheton + epithets epithet epitome epitom + equal equal equalities equal + equality equal equall equal + equally equal equalness equal + equals equal equinoctial equinocti + equinox equinox equipage equipag + equity equiti equivocal equivoc + equivocate equivoc equivocates equivoc + equivocation equivoc equivocator equivoc + er er erbear erbear + erbearing erbear erbears erbear + erbeat erbeat erblows erblow + erboard erboard erborne erborn + ercame ercam ercast ercast + ercharg ercharg ercharged ercharg + ercharging ercharg ercles ercl + ercome ercom ercover ercov + ercrows ercrow erdoing erdo + ere er erebus erebu + erect erect erected erect + erecting erect erection erect + erects erect erewhile erewhil + erflourish erflourish erflow erflow + erflowing erflow erflows erflow + erfraught erfraught erga erga + ergalled ergal erglanced erglanc + ergo ergo ergone ergon + ergrow ergrow ergrown ergrown + ergrowth ergrowth erhang erhang + erhanging erhang erhasty erhasti + erhear erhear erheard erheard + eringoes eringo erjoy erjoi + erleap erleap erleaps erleap + erleavens erleaven erlook erlook + erlooking erlook ermaster ermast + ermengare ermengar ermount ermount + ern ern ernight ernight + eros ero erpaid erpaid + erparted erpart erpast erpast + erpays erpai erpeer erpeer + erperch erperch erpicturing erpictur + erpingham erpingham erposting erpost + erpow erpow erpress erpress + erpressed erpress err err + errand errand errands errand + errant errant errate errat + erraught erraught erreaches erreach + erred er errest errest + erring er erroneous erron + error error errors error + errs err errule errul + errun errun erset erset + ershade ershad ershades ershad + ershine ershin ershot ershot + ersized ersiz erskip erskip + erslips erslip erspreads erspread + erst erst erstare erstar + erstep erstep erstunk erstunk + ersway erswai ersways erswai + erswell erswel erta erta + ertake ertak erteemed erteem + erthrow erthrow erthrown erthrown + erthrows erthrow ertook ertook + ertop ertop ertopping ertop + ertrip ertrip erturn erturn + erudition erudit eruption erupt + eruptions erupt ervalues ervalu + erwalk erwalk erwatch erwatch + erween erween erweens erween + erweigh erweigh erweighs erweigh + erwhelm erwhelm erwhelmed erwhelm + erworn erworn es es + escalus escalu escap escap + escape escap escaped escap + escapes escap eschew eschew + escoted escot esill esil + especial especi especially especi + esperance esper espials espial + espied espi espies espi + espous espou espouse espous + espy espi esquire esquir + esquires esquir essay essai + essays essai essence essenc + essential essenti essentially essenti + esses ess essex essex + est est establish establish + established establish estate estat + estates estat esteem esteem + esteemed esteem esteemeth esteemeth + esteeming esteem esteems esteem + estimable estim estimate estim + estimation estim estimations estim + estime estim estranged estrang + estridge estridg estridges estridg + et et etc etc + etceteras etcetera ete et + eternal etern eternally etern + eterne etern eternity etern + eterniz eterniz etes et + ethiop ethiop ethiope ethiop + ethiopes ethiop ethiopian ethiopian + etna etna eton eton + etre etr eunuch eunuch + eunuchs eunuch euphrates euphrat + euphronius euphroniu euriphile euriphil + europa europa europe europ + ev ev evade evad + evades evad evans evan + evasion evas evasions evas + eve ev even even + evening even evenly evenli + event event eventful event + events event ever ever + everlasting everlast everlastingly everlastingli + evermore evermor every everi + everyone everyon everything everyth + everywhere everywher evidence evid + evidences evid evident evid + evil evil evilly evilli + evils evil evitate evit + ewe ew ewer ewer + ewers ewer ewes ew + exact exact exacted exact + exactest exactest exacting exact + exaction exact exactions exact + exactly exactli exacts exact + exalt exalt exalted exalt + examin examin examination examin + examinations examin examine examin + examined examin examines examin + exampl exampl example exampl + exampled exampl examples exampl + exasperate exasper exasperates exasper + exceed exce exceeded exceed + exceedeth exceedeth exceeding exceed + exceedingly exceedingli exceeds exce + excel excel excelled excel + excellence excel excellencies excel + excellency excel excellent excel + excellently excel excelling excel + excels excel except except + excepted except excepting except + exception except exceptions except + exceptless exceptless excess excess + excessive excess exchang exchang + exchange exchang exchanged exchang + exchequer exchequ exchequers exchequ + excite excit excited excit + excitements excit excites excit + exclaim exclaim exclaims exclaim + exclamation exclam exclamations exclam + excludes exclud excommunicate excommun + excommunication excommun excrement excrement + excrements excrement excursion excurs + excursions excurs excus excu + excusable excus excuse excus + excused excus excuses excus + excusez excusez excusing excus + execrable execr execrations execr + execute execut executed execut + executing execut execution execut + executioner execution executioners execution + executor executor executors executor + exempt exempt exempted exempt + exequies exequi exercise exercis + exercises exercis exeter exet + exeunt exeunt exhal exhal + exhalation exhal exhalations exhal + exhale exhal exhales exhal + exhaust exhaust exhibit exhibit + exhibiters exhibit exhibition exhibit + exhort exhort exhortation exhort + exigent exig exil exil + exile exil exiled exil + exion exion exist exist + exists exist exit exit + exits exit exorciser exorcis + exorcisms exorc exorcist exorcist + expect expect expectance expect + expectancy expect expectation expect + expectations expect expected expect + expecters expect expecting expect + expects expect expedience expedi + expedient expedi expediently expedi + expedition expedit expeditious expediti + expel expel expell expel + expelling expel expels expel + expend expend expense expens + expenses expens experienc experienc + experience experi experiences experi + experiment experi experimental experiment + experiments experi expert expert + expertness expert expiate expiat + expiation expiat expir expir + expiration expir expire expir + expired expir expires expir + expiring expir explication explic + exploit exploit exploits exploit + expos expo expose expos + exposing expos exposition exposit + expositor expositor expostulate expostul + expostulation expostul exposture expostur + exposure exposur expound expound + expounded expound express express + expressed express expresseth expresseth + expressing express expressive express + expressly expressli expressure expressur + expuls expul expulsion expuls + exquisite exquisit exsufflicate exsuffl + extant extant extemporal extempor + extemporally extempor extempore extempor + extend extend extended extend + extends extend extent extent + extenuate extenu extenuated extenu + extenuates extenu extenuation extenu + exterior exterior exteriorly exteriorli + exteriors exterior extermin extermin + extern extern external extern + extinct extinct extincted extinct + extincture extinctur extinguish extinguish + extirp extirp extirpate extirp + extirped extirp extol extol + extoll extol extolment extol + exton exton extort extort + extorted extort extortion extort + extortions extort extra extra + extract extract extracted extract + extracting extract extraordinarily extraordinarili + extraordinary extraordinari extraught extraught + extravagancy extravag extravagant extravag + extreme extrem extremely extrem + extremes extrem extremest extremest + extremities extrem extremity extrem + exuent exuent exult exult + exultation exult ey ey + eyas eya eyases eyas + eye ey eyeball eyebal + eyeballs eyebal eyebrow eyebrow + eyebrows eyebrow eyed ei + eyeless eyeless eyelid eyelid + eyelids eyelid eyes ey + eyesight eyesight eyestrings eyestr + eying ei eyne eyn + eyrie eyri fa fa + fabian fabian fable fabl + fables fabl fabric fabric + fabulous fabul fac fac + face face faced face + facere facer faces face + faciant faciant facile facil + facility facil facinerious facineri + facing face facit facit + fact fact faction faction + factionary factionari factions faction + factious factiou factor factor + factors factor faculties faculti + faculty faculti fade fade + faded fade fadeth fadeth + fadge fadg fading fade + fadings fade fadom fadom + fadoms fadom fagot fagot + fagots fagot fail fail + failing fail fails fail + fain fain faint faint + fainted faint fainter fainter + fainting faint faintly faintli + faintness faint faints faint + fair fair fairer fairer + fairest fairest fairies fairi + fairing fair fairings fair + fairly fairli fairness fair + fairs fair fairwell fairwel + fairy fairi fais fai + fait fait faites fait + faith faith faithful faith + faithfull faithful faithfully faithfulli + faithless faithless faiths faith + faitors faitor fal fal + falchion falchion falcon falcon + falconbridge falconbridg falconer falcon + falconers falcon fall fall + fallacy fallaci fallen fallen + falleth falleth falliable falliabl + fallible fallibl falling fall + fallow fallow fallows fallow + falls fall fally falli + falorous falor false fals + falsehood falsehood falsely fals + falseness fals falser falser + falsify falsifi falsing fals + falstaff falstaff falstaffs falstaff + falter falter fam fam + fame fame famed fame + familiar familiar familiarity familiar + familiarly familiarli familiars familiar + family famili famine famin + famish famish famished famish + famous famou famoused famous + famously famous fan fan + fanatical fanat fancies fanci + fancy fanci fane fane + fanes fane fang fang + fangled fangl fangless fangless + fangs fang fann fann + fanning fan fans fan + fantasied fantasi fantasies fantasi + fantastic fantast fantastical fantast + fantastically fantast fantasticoes fantastico + fantasy fantasi fap fap + far far farborough farborough + farced farc fardel fardel + fardels fardel fare fare + fares fare farewell farewel + farewells farewel fariner farin + faring fare farm farm + farmer farmer farmhouse farmhous + farms farm farre farr + farrow farrow farther farther + farthest farthest farthing farth + farthingale farthingal farthingales farthingal + farthings farth fartuous fartuou + fas fa fashion fashion + fashionable fashion fashioning fashion + fashions fashion fast fast + fasted fast fasten fasten + fastened fasten faster faster + fastest fastest fasting fast + fastly fastli fastolfe fastolf + fasts fast fat fat + fatal fatal fatally fatal + fate fate fated fate + fates fate father father + fathered father fatherless fatherless + fatherly fatherli fathers father + fathom fathom fathomless fathomless + fathoms fathom fatigate fatig + fatness fat fats fat + fatted fat fatter fatter + fattest fattest fatting fat + fatuus fatuu fauconbridge fauconbridg + faulconbridge faulconbridg fault fault + faultiness faulti faultless faultless + faults fault faulty faulti + fausse fauss fauste faust + faustuses faustus faut faut + favor favor favorable favor + favorably favor favors favor + favour favour favourable favour + favoured favour favouredly favouredli + favourer favour favourers favour + favouring favour favourite favourit + favourites favourit favours favour + favout favout fawn fawn + fawneth fawneth fawning fawn + fawns fawn fay fai + fe fe fealty fealti + fear fear feared fear + fearest fearest fearful fear + fearfull fearful fearfully fearfulli + fearfulness fear fearing fear + fearless fearless fears fear + feast feast feasted feast + feasting feast feasts feast + feat feat feated feat + feater feater feather feather + feathered feather feathers feather + featly featli feats feat + featur featur feature featur + featured featur featureless featureless + features featur february februari + fecks feck fed fed + fedary fedari federary federari + fee fee feeble feebl + feebled feebl feebleness feebl + feebling feebl feebly feebli + feed feed feeder feeder + feeders feeder feedeth feedeth + feeding feed feeds feed + feel feel feeler feeler + feeling feel feelingly feelingli + feels feel fees fee + feet feet fehemently fehement + feign feign feigned feign + feigning feign feil feil + feith feith felicitate felicit + felicity felic fell fell + fellest fellest fellies felli + fellow fellow fellowly fellowli + fellows fellow fellowship fellowship + fellowships fellowship fells fell + felon felon felonious feloni + felony feloni felt felt + female femal females femal + feminine feminin fen fen + fenc fenc fence fenc + fencer fencer fencing fenc + fends fend fennel fennel + fenny fenni fens fen + fenton fenton fer fer + ferdinand ferdinand fere fere + fernseed fernse ferrara ferrara + ferrers ferrer ferret ferret + ferry ferri ferryman ferryman + fertile fertil fertility fertil + fervency fervenc fervour fervour + fery feri fest fest + feste fest fester fester + festinate festin festinately festin + festival festiv festivals festiv + fet fet fetch fetch + fetches fetch fetching fetch + fetlock fetlock fetlocks fetlock + fett fett fetter fetter + fettering fetter fetters fetter + fettle fettl feu feu + feud feud fever fever + feverous fever fevers fever + few few fewer fewer + fewest fewest fewness few + fickle fickl fickleness fickl + fico fico fiction fiction + fiddle fiddl fiddler fiddler + fiddlestick fiddlestick fidele fidel + fidelicet fidelicet fidelity fidel + fidius fidiu fie fie + field field fielded field + fields field fiend fiend + fiends fiend fierce fierc + fiercely fierc fierceness fierc + fiery fieri fife fife + fifes fife fifteen fifteen + fifteens fifteen fifteenth fifteenth + fifth fifth fifty fifti + fiftyfold fiftyfold fig fig + fight fight fighter fighter + fightest fightest fighteth fighteth + fighting fight fights fight + figo figo figs fig + figur figur figure figur + figured figur figures figur + figuring figur fike fike + fil fil filberts filbert + filch filch filches filch + filching filch file file + filed file files file + filial filial filius filiu + fill fill filled fill + fillet fillet filling fill + fillip fillip fills fill + filly filli film film + fils fil filth filth + filths filth filthy filthi + fin fin finally final + finch finch find find + finder finder findeth findeth + finding find findings find + finds find fine fine + fineless fineless finely fine + finem finem fineness fine + finer finer fines fine + finest finest fing fing + finger finger fingering finger + fingers finger fingre fingr + fingres fingr finical finic + finish finish finished finish + finisher finish finless finless + finn finn fins fin + finsbury finsburi fir fir + firago firago fire fire + firebrand firebrand firebrands firebrand + fired fire fires fire + firework firework fireworks firework + firing fire firk firk + firm firm firmament firmament + firmly firmli firmness firm + first first firstlings firstl + fish fish fisher fisher + fishermen fishermen fishers fisher + fishes fish fishified fishifi + fishmonger fishmong fishpond fishpond + fisnomy fisnomi fist fist + fisting fist fists fist + fistula fistula fit fit + fitchew fitchew fitful fit + fitly fitli fitment fitment + fitness fit fits fit + fitted fit fitter fitter + fittest fittest fitteth fitteth + fitting fit fitzwater fitzwat + five five fivepence fivep + fives five fix fix + fixed fix fixes fix + fixeth fixeth fixing fix + fixture fixtur fl fl + flag flag flagging flag + flagon flagon flagons flagon + flags flag flail flail + flakes flake flaky flaki + flam flam flame flame + flamen flamen flamens flamen + flames flame flaming flame + flaminius flaminiu flanders flander + flannel flannel flap flap + flaring flare flash flash + flashes flash flashing flash + flask flask flat flat + flatly flatli flatness flat + flats flat flatt flatt + flatter flatter flattered flatter + flatterer flatter flatterers flatter + flatterest flatterest flatteries flatteri + flattering flatter flatters flatter + flattery flatteri flaunts flaunt + flavio flavio flavius flaviu + flaw flaw flaws flaw + flax flax flaxen flaxen + flay flai flaying flai + flea flea fleance fleanc + fleas flea flecked fleck + fled fled fledge fledg + flee flee fleec fleec + fleece fleec fleeces fleec + fleer fleer fleering fleer + fleers fleer fleet fleet + fleeter fleeter fleeting fleet + fleming fleme flemish flemish + flesh flesh fleshes flesh + fleshly fleshli fleshment fleshment + fleshmonger fleshmong flew flew + flexible flexibl flexure flexur + flibbertigibbet flibbertigibbet flickering flicker + flidge flidg fliers flier + flies fli flieth flieth + flight flight flights flight + flighty flighti flinch flinch + fling fling flint flint + flints flint flinty flinti + flirt flirt float float + floated float floating float + flock flock flocks flock + flood flood floodgates floodgat + floods flood floor floor + flora flora florence florenc + florentine florentin florentines florentin + florentius florentiu florizel florizel + flote flote floulish floulish + flour flour flourish flourish + flourishes flourish flourisheth flourisheth + flourishing flourish flout flout + flouted flout flouting flout + flouts flout flow flow + flowed flow flower flower + flowerets floweret flowers flower + flowing flow flown flown + flows flow fluellen fluellen + fluent fluent flung flung + flush flush flushing flush + fluster fluster flute flute + flutes flute flutter flutter + flux flux fluxive fluxiv + fly fly flying fly + fo fo foal foal + foals foal foam foam + foamed foam foaming foam + foams foam foamy foami + fob fob focative foc + fodder fodder foe foe + foeman foeman foemen foemen + foes foe fog fog + foggy foggi fogs fog + foh foh foi foi + foil foil foiled foil + foils foil foin foin + foining foin foins foin + fois foi foison foison + foisons foison foist foist + foix foix fold fold + folded fold folds fold + folio folio folk folk + folks folk follies folli + follow follow followed follow + follower follow followers follow + followest followest following follow + follows follow folly folli + fond fond fonder fonder + fondly fondli fondness fond + font font fontibell fontibel + food food fool fool + fooleries fooleri foolery fooleri + foolhardy foolhardi fooling fool + foolish foolish foolishly foolishli + foolishness foolish fools fool + foot foot football footbal + footboy footboi footboys footboi + footed foot footfall footfal + footing foot footman footman + footmen footmen footpath footpath + footsteps footstep footstool footstool + fopp fopp fopped fop + foppery fopperi foppish foppish + fops fop for for + forage forag foragers forag + forbade forbad forbear forbear + forbearance forbear forbears forbear + forbid forbid forbidden forbidden + forbiddenly forbiddenli forbids forbid + forbod forbod forborne forborn + forc forc force forc + forced forc forceful forc + forceless forceless forces forc + forcible forcibl forcibly forcibl + forcing forc ford ford + fordid fordid fordo fordo + fordoes fordo fordone fordon + fore fore forecast forecast + forefather forefath forefathers forefath + forefinger forefing forego forego + foregone foregon forehand forehand + forehead forehead foreheads forehead + forehorse forehors foreign foreign + foreigner foreign foreigners foreign + foreknowing foreknow foreknowledge foreknowledg + foremost foremost forenamed forenam + forenoon forenoon forerun forerun + forerunner forerunn forerunning forerun + foreruns forerun foresaid foresaid + foresaw foresaw foresay foresai + foresee forese foreseeing forese + foresees forese foreshow foreshow + foreskirt foreskirt forespent foresp + forest forest forestall forestal + forestalled forestal forester forest + foresters forest forests forest + foretell foretel foretelling foretel + foretells foretel forethink forethink + forethought forethought foretold foretold + forever forev foreward foreward + forewarn forewarn forewarned forewarn + forewarning forewarn forfeit forfeit + forfeited forfeit forfeiters forfeit + forfeiting forfeit forfeits forfeit + forfeiture forfeitur forfeitures forfeitur + forfend forfend forfended forfend + forg forg forgave forgav + forge forg forged forg + forgeries forgeri forgery forgeri + forges forg forget forget + forgetful forget forgetfulness forget + forgetive forget forgets forget + forgetting forget forgive forgiv + forgiven forgiven forgiveness forgiv + forgo forgo forgoing forgo + forgone forgon forgot forgot + forgotten forgotten fork fork + forked fork forks fork + forlorn forlorn form form + formal formal formally formal + formed form former former + formerly formerli formless formless + forms form fornication fornic + fornications fornic fornicatress fornicatress + forres forr forrest forrest + forsake forsak forsaken forsaken + forsaketh forsaketh forslow forslow + forsook forsook forsooth forsooth + forspent forspent forspoke forspok + forswear forswear forswearing forswear + forswore forswor forsworn forsworn + fort fort forted fort + forth forth forthcoming forthcom + forthlight forthlight forthright forthright + forthwith forthwith fortification fortif + fortifications fortif fortified fortifi + fortifies fortifi fortify fortifi + fortinbras fortinbra fortitude fortitud + fortnight fortnight fortress fortress + fortresses fortress forts fort + fortun fortun fortuna fortuna + fortunate fortun fortunately fortun + fortune fortun fortuned fortun + fortunes fortun fortward fortward + forty forti forum forum + forward forward forwarding forward + forwardness forward forwards forward + forwearied forweari fosset fosset + fost fost foster foster + fostered foster fought fought + foughten foughten foul foul + fouler fouler foulest foulest + foully foulli foulness foul + found found foundation foundat + foundations foundat founded found + founder founder fount fount + fountain fountain fountains fountain + founts fount four four + fourscore fourscor fourteen fourteen + fourth fourth foutra foutra + fowl fowl fowler fowler + fowling fowl fowls fowl + fox fox foxes fox + foxship foxship fracted fract + fraction fraction fractions fraction + fragile fragil fragment fragment + fragments fragment fragrant fragrant + frail frail frailer frailer + frailties frailti frailty frailti + fram fram frame frame + framed frame frames frame + frampold frampold fran fran + francais francai france franc + frances franc franchise franchis + franchised franchis franchisement franchis + franchises franchis franciae francia + francis franci francisca francisca + franciscan franciscan francisco francisco + frank frank franker franker + frankfort frankfort franklin franklin + franklins franklin frankly frankli + frankness frank frantic frantic + franticly franticli frateretto frateretto + fratrum fratrum fraud fraud + fraudful fraud fraught fraught + fraughtage fraughtag fraughting fraught + fray frai frays frai + freckl freckl freckled freckl + freckles freckl frederick frederick + free free freed freed + freedom freedom freedoms freedom + freehearted freeheart freelier freelier + freely freeli freeman freeman + freemen freemen freeness freeness + freer freer frees free + freestone freeston freetown freetown + freeze freez freezes freez + freezing freez freezings freez + french french frenchman frenchman + frenchmen frenchmen frenchwoman frenchwoman + frenzy frenzi frequent frequent + frequents frequent fresh fresh + fresher fresher freshes fresh + freshest freshest freshly freshli + freshness fresh fret fret + fretful fret frets fret + fretted fret fretten fretten + fretting fret friar friar + friars friar friday fridai + fridays fridai friend friend + friended friend friending friend + friendless friendless friendliness friendli + friendly friendli friends friend + friendship friendship friendships friendship + frieze friez fright fright + frighted fright frightened frighten + frightful fright frighting fright + frights fright fringe fring + fringed fring frippery fripperi + frisk frisk fritters fritter + frivolous frivol fro fro + frock frock frog frog + frogmore frogmor froissart froissart + frolic frolic from from + front front fronted front + frontier frontier frontiers frontier + fronting front frontlet frontlet + fronts front frost frost + frosts frost frosty frosti + froth froth froward froward + frown frown frowning frown + frowningly frowningli frowns frown + froze froze frozen frozen + fructify fructifi frugal frugal + fruit fruit fruiterer fruiter + fruitful fruit fruitfully fruitfulli + fruitfulness fruit fruition fruition + fruitless fruitless fruits fruit + frush frush frustrate frustrat + frutify frutifi fry fry + fubb fubb fuel fuel + fugitive fugit fulfil fulfil + fulfill fulfil fulfilling fulfil + fulfils fulfil full full + fullam fullam fuller fuller + fullers fuller fullest fullest + fullness full fully fulli + fulness ful fulsome fulsom + fulvia fulvia fum fum + fumble fumbl fumbles fumbl + fumblest fumblest fumbling fumbl + fume fume fumes fume + fuming fume fumiter fumit + fumitory fumitori fun fun + function function functions function + fundamental fundament funeral funer + funerals funer fur fur + furbish furbish furies furi + furious furiou furlongs furlong + furnace furnac furnaces furnac + furnish furnish furnished furnish + furnishings furnish furniture furnitur + furnival furniv furor furor + furr furr furrow furrow + furrowed furrow furrows furrow + furth furth further further + furtherance further furtherer further + furthermore furthermor furthest furthest + fury furi furze furz + furzes furz fust fust + fustian fustian fustilarian fustilarian + fusty fusti fut fut + future futur futurity futur + g g gabble gabbl + gaberdine gaberdin gabriel gabriel + gad gad gadding gad + gads gad gadshill gadshil + gag gag gage gage + gaged gage gagg gagg + gaging gage gagne gagn + gain gain gained gain + gainer gainer gaingiving gaingiv + gains gain gainsaid gainsaid + gainsay gainsai gainsaying gainsai + gainsays gainsai gainst gainst + gait gait gaited gait + galathe galath gale gale + galen galen gales gale + gall gall gallant gallant + gallantly gallantli gallantry gallantri + gallants gallant galled gall + gallery galleri galley gallei + galleys gallei gallia gallia + gallian gallian galliard galliard + galliasses galliass gallimaufry gallimaufri + galling gall gallons gallon + gallop gallop galloping gallop + gallops gallop gallow gallow + galloway gallowai gallowglasses gallowglass + gallows gallow gallowses gallows + galls gall gallus gallu + gam gam gambol gambol + gambold gambold gambols gambol + gamboys gamboi game game + gamers gamer games game + gamesome gamesom gamester gamest + gaming game gammon gammon + gamut gamut gan gan + gangren gangren ganymede ganymed + gaol gaol gaoler gaoler + gaolers gaoler gaols gaol + gap gap gape gape + gapes gape gaping gape + gar gar garb garb + garbage garbag garboils garboil + garcon garcon gard gard + garde gard garden garden + gardener garden gardeners garden + gardens garden gardez gardez + gardiner gardin gardon gardon + gargantua gargantua gargrave gargrav + garish garish garland garland + garlands garland garlic garlic + garment garment garments garment + garmet garmet garner garner + garners garner garnish garnish + garnished garnish garret garret + garrison garrison garrisons garrison + gart gart garter garter + garterd garterd gartering garter + garters garter gascony gasconi + gash gash gashes gash + gaskins gaskin gasp gasp + gasping gasp gasted gast + gastness gast gat gat + gate gate gated gate + gates gate gath gath + gather gather gathered gather + gathering gather gathers gather + gatories gatori gatory gatori + gaud gaud gaudeo gaudeo + gaudy gaudi gauge gaug + gaul gaul gaultree gaultre + gaunt gaunt gauntlet gauntlet + gauntlets gauntlet gav gav + gave gave gavest gavest + gawded gawd gawds gawd + gawsey gawsei gay gai + gayness gay gaz gaz + gaze gaze gazed gaze + gazer gazer gazers gazer + gazes gaze gazeth gazeth + gazing gaze gear gear + geck geck geese gees + geffrey geffrei geld geld + gelded geld gelding geld + gelida gelida gelidus gelidu + gelt gelt gem gem + geminy gemini gems gem + gen gen gender gender + genders gender general gener + generally gener generals gener + generation gener generations gener + generative gener generosity generos + generous gener genitive genit + genitivo genitivo genius geniu + gennets gennet genoa genoa + genoux genoux gens gen + gent gent gentilhomme gentilhomm + gentility gentil gentle gentl + gentlefolks gentlefolk gentleman gentleman + gentlemanlike gentlemanlik gentlemen gentlemen + gentleness gentl gentler gentler + gentles gentl gentlest gentlest + gentlewoman gentlewoman gentlewomen gentlewomen + gently gentli gentry gentri + george georg gerard gerard + germaines germain germains germain + german german germane german + germans german germany germani + gertrude gertrud gest gest + gests gest gesture gestur + gestures gestur get get + getrude getrud gets get + getter getter getting get + ghastly ghastli ghost ghost + ghosted ghost ghostly ghostli + ghosts ghost gi gi + giant giant giantess giantess + giantlike giantlik giants giant + gib gib gibber gibber + gibbet gibbet gibbets gibbet + gibe gibe giber giber + gibes gibe gibing gibe + gibingly gibingli giddily giddili + giddiness giddi giddy giddi + gift gift gifts gift + gig gig giglets giglet + giglot giglot gilbert gilbert + gild gild gilded gild + gilding gild gilliams gilliam + gillian gillian gills gill + gillyvors gillyvor gilt gilt + gimmal gimmal gimmers gimmer + gin gin ging ging + ginger ginger gingerbread gingerbread + gingerly gingerli ginn ginn + gins gin gioucestershire gioucestershir + gipes gipe gipsies gipsi + gipsy gipsi gird gird + girded gird girdle girdl + girdled girdl girdles girdl + girdling girdl girl girl + girls girl girt girt + girth girth gis gi + giv giv give give + given given giver giver + givers giver gives give + givest givest giveth giveth + giving give givings give + glad glad gladded glad + gladding glad gladly gladli + gladness glad glamis glami + glanc glanc glance glanc + glanced glanc glances glanc + glancing glanc glanders glander + glansdale glansdal glare glare + glares glare glass glass + glasses glass glassy glassi + glaz glaz glazed glaze + gleams gleam glean glean + gleaned glean gleaning glean + gleeful gleeful gleek gleek + gleeking gleek gleeks gleek + glend glend glendower glendow + glib glib glide glide + glided glide glides glide + glideth glideth gliding glide + glimmer glimmer glimmering glimmer + glimmers glimmer glimpse glimps + glimpses glimps glist glist + glistening glisten glister glister + glistering glister glisters glister + glitt glitt glittering glitter + globe globe globes globe + glooming gloom gloomy gloomi + glories glori glorified glorifi + glorify glorifi glorious gloriou + gloriously glorious glory glori + glose glose gloss gloss + glosses gloss glou glou + glouceste gloucest gloucester gloucest + gloucestershire gloucestershir glove glove + glover glover gloves glove + glow glow glowed glow + glowing glow glowworm glowworm + gloz gloz gloze gloze + glozes gloze glu glu + glue glue glued glu + glues glue glut glut + glutt glutt glutted glut + glutton glutton gluttoning glutton + gluttony gluttoni gnarled gnarl + gnarling gnarl gnat gnat + gnats gnat gnaw gnaw + gnawing gnaw gnawn gnawn + gnaws gnaw go go + goad goad goaded goad + goads goad goal goal + goat goat goatish goatish + goats goat gobbets gobbet + gobbo gobbo goblet goblet + goblets goblet goblin goblin + goblins goblin god god + godded god godden godden + goddess goddess goddesses goddess + goddild goddild godfather godfath + godfathers godfath godhead godhead + godlike godlik godliness godli + godly godli godmother godmoth + gods god godson godson + goer goer goers goer + goes goe goest goest + goeth goeth goffe goff + gogs gog going go + gold gold golden golden + goldenly goldenli goldsmith goldsmith + goldsmiths goldsmith golgotha golgotha + goliases golias goliath goliath + gon gon gondola gondola + gondolier gondoli gone gone + goneril goneril gong gong + gonzago gonzago gonzalo gonzalo + good good goodfellow goodfellow + goodlier goodlier goodliest goodliest + goodly goodli goodman goodman + goodness good goodnight goodnight + goodrig goodrig goods good + goodwife goodwif goodwill goodwil + goodwin goodwin goodwins goodwin + goodyear goodyear goodyears goodyear + goose goos gooseberry gooseberri + goosequills goosequil goot goot + gor gor gorbellied gorbelli + gorboduc gorboduc gordian gordian + gore gore gored gore + gorg gorg gorge gorg + gorgeous gorgeou gorget gorget + gorging gorg gorgon gorgon + gormandize gormand gormandizing gormand + gory gori gosling gosl + gospel gospel gospels gospel + goss goss gossamer gossam + gossip gossip gossiping gossip + gossiplike gossiplik gossips gossip + got got goth goth + goths goth gotten gotten + gourd gourd gout gout + gouts gout gouty gouti + govern govern governance govern + governed govern governess gover + government govern governor governor + governors governor governs govern + gower gower gown gown + gowns gown grac grac + grace grace graced grace + graceful grace gracefully gracefulli + graceless graceless graces grace + gracing grace gracious graciou + graciously gracious gradation gradat + graff graff graffing graf + graft graft grafted graft + grafters grafter grain grain + grained grain grains grain + gramercies gramerci gramercy gramerci + grammar grammar grand grand + grandam grandam grandame grandam + grandchild grandchild grande grand + grandeur grandeur grandfather grandfath + grandjurors grandjuror grandmother grandmoth + grandpre grandpr grandsir grandsir + grandsire grandsir grandsires grandsir + grange grang grant grant + granted grant granting grant + grants grant grape grape + grapes grape grapple grappl + grapples grappl grappling grappl + grasp grasp grasped grasp + grasps grasp grass grass + grasshoppers grasshopp grassy grassi + grate grate grated grate + grateful grate grates grate + gratiano gratiano gratify gratifi + gratii gratii gratillity gratil + grating grate gratis grati + gratitude gratitud gratulate gratul + grav grav grave grave + gravediggers gravedigg gravel gravel + graveless graveless gravell gravel + gravely grave graven graven + graveness grave graver graver + graves grave gravest gravest + gravestone graveston gravities graviti + gravity graviti gravy gravi + gray grai graymalkin graymalkin + graz graz graze graze + grazed graze grazing graze + grease greas greases greas + greasily greasili greasy greasi + great great greater greater + greatest greatest greatly greatli + greatness great grecian grecian + grecians grecian gree gree + greece greec greed greed + greedily greedili greediness greedi + greedy greedi greeing gree + greek greek greekish greekish + greeks greek green green + greener greener greenly greenli + greens green greensleeves greensleev + greenwich greenwich greenwood greenwood + greet greet greeted greet + greeting greet greetings greet + greets greet greg greg + gregory gregori gremio gremio + grew grew grey grei + greybeard greybeard greybeards greybeard + greyhound greyhound greyhounds greyhound + grief grief griefs grief + griev griev grievance grievanc + grievances grievanc grieve griev + grieved griev grieves griev + grievest grievest grieving griev + grievingly grievingli grievous grievou + grievously grievous griffin griffin + griffith griffith grim grim + grime grime grimly grimli + grin grin grind grind + grinding grind grindstone grindston + grinning grin grip grip + gripe gripe gripes gripe + griping gripe grise grise + grisly grisli grissel grissel + grize grize grizzle grizzl + grizzled grizzl groan groan + groaning groan groans groan + groat groat groats groat + groin groin groom groom + grooms groom grop grop + groping grope gros gro + gross gross grosser grosser + grossly grossli grossness gross + ground ground grounded ground + groundlings groundl grounds ground + grove grove grovel grovel + grovelling grovel groves grove + grow grow groweth groweth + growing grow grown grown + grows grow growth growth + grub grub grubb grubb + grubs grub grudge grudg + grudged grudg grudges grudg + grudging grudg gruel gruel + grumble grumbl grumblest grumblest + grumbling grumbl grumblings grumbl + grumio grumio grund grund + grunt grunt gualtier gualtier + guard guard guardage guardag + guardant guardant guarded guard + guardian guardian guardians guardian + guards guard guardsman guardsman + gud gud gudgeon gudgeon + guerdon guerdon guerra guerra + guess guess guesses guess + guessingly guessingli guest guest + guests guest guiana guiana + guichard guichard guide guid + guided guid guider guider + guiderius guideriu guides guid + guiding guid guidon guidon + guienne guienn guil guil + guildenstern guildenstern guilders guilder + guildford guildford guildhall guildhal + guile guil guiled guil + guileful guil guilfords guilford + guilt guilt guiltian guiltian + guiltier guiltier guiltily guiltili + guiltiness guilti guiltless guiltless + guilts guilt guilty guilti + guinea guinea guinever guinev + guise guis gul gul + gules gule gulf gulf + gulfs gulf gull gull + gulls gull gum gum + gumm gumm gums gum + gun gun gunner gunner + gunpowder gunpowd guns gun + gurnet gurnet gurney gurnei + gust gust gusts gust + gusty gusti guts gut + gutter gutter guy gui + guynes guyn guysors guysor + gypsy gypsi gyve gyve + gyved gyve gyves gyve + h h ha ha + haberdasher haberdash habiliment habili + habiliments habili habit habit + habitation habit habited habit + habits habit habitude habitud + hack hack hacket hacket + hackney hacknei hacks hack + had had hadst hadst + haec haec haeres haer + hag hag hagar hagar + haggard haggard haggards haggard + haggish haggish haggled haggl + hags hag hail hail + hailed hail hailstone hailston + hailstones hailston hair hair + hairless hairless hairs hair + hairy hairi hal hal + halberd halberd halberds halberd + halcyon halcyon hale hale + haled hale hales hale + half half halfcan halfcan + halfpence halfpenc halfpenny halfpenni + halfpennyworth halfpennyworth halfway halfwai + halidom halidom hall hall + halloa halloa halloing hallo + hallond hallond halloo halloo + hallooing halloo hallow hallow + hallowed hallow hallowmas hallowma + hallown hallown hals hal + halt halt halter halter + halters halter halting halt + halts halt halves halv + ham ham hames hame + hamlet hamlet hammer hammer + hammered hammer hammering hammer + hammers hammer hamper hamper + hampton hampton hams ham + hamstring hamstr hand hand + handed hand handful hand + handicraft handicraft handicraftsmen handicraftsmen + handing hand handiwork handiwork + handkercher handkerch handkerchers handkerch + handkerchief handkerchief handle handl + handled handl handles handl + handless handless handlest handlest + handling handl handmaid handmaid + handmaids handmaid hands hand + handsaw handsaw handsome handsom + handsomely handsom handsomeness handsom + handwriting handwrit handy handi + hang hang hanged hang + hangers hanger hangeth hangeth + hanging hang hangings hang + hangman hangman hangmen hangmen + hangs hang hannibal hannib + hap hap hapless hapless + haply hapli happ happ + happen happen happened happen + happier happier happies happi + happiest happiest happily happili + happiness happi happy happi + haps hap harbinger harbing + harbingers harbing harbor harbor + harbour harbour harbourage harbourag + harbouring harbour harbours harbour + harcourt harcourt hard hard + harder harder hardest hardest + hardiest hardiest hardiment hardiment + hardiness hardi hardly hardli + hardness hard hardocks hardock + hardy hardi hare hare + harelip harelip hares hare + harfleur harfleur hark hark + harlot harlot harlotry harlotri + harlots harlot harm harm + harmed harm harmful harm + harming harm harmless harmless + harmonious harmoni harmony harmoni + harms harm harness har + harp harp harper harper + harpier harpier harping harp + harpy harpi harried harri + harrow harrow harrows harrow + harry harri harsh harsh + harshly harshli harshness harsh + hart hart harts hart + harum harum harvest harvest + has ha hast hast + haste hast hasted hast + hasten hasten hastes hast + hastily hastili hasting hast + hastings hast hasty hasti + hat hat hatch hatch + hatches hatch hatchet hatchet + hatching hatch hatchment hatchment + hate hate hated hate + hateful hate hater hater + haters hater hates hate + hateth hateth hatfield hatfield + hath hath hating hate + hatred hatr hats hat + haud haud hauf hauf + haught haught haughtiness haughti + haughty haughti haunch haunch + haunches haunch haunt haunt + haunted haunt haunting haunt + haunts haunt hautboy hautboi + hautboys hautboi have have + haven haven havens haven + haver haver having have + havings have havior havior + haviour haviour havoc havoc + hawk hawk hawking hawk + hawks hawk hawthorn hawthorn + hawthorns hawthorn hay hai + hazard hazard hazarded hazard + hazards hazard hazel hazel + hazelnut hazelnut he he + head head headborough headborough + headed head headier headier + heading head headland headland + headless headless headlong headlong + heads head headsman headsman + headstrong headstrong heady headi + heal heal healed heal + healing heal heals heal + health health healthful health + healths health healthsome healthsom + healthy healthi heap heap + heaping heap heaps heap + hear hear heard heard + hearer hearer hearers hearer + hearest hearest heareth heareth + hearing hear hearings hear + heark heark hearken hearken + hearkens hearken hears hear + hearsay hearsai hearse hears + hearsed hears hearst hearst + heart heart heartache heartach + heartbreak heartbreak heartbreaking heartbreak + hearted heart hearten hearten + hearth hearth hearths hearth + heartily heartili heartiness hearti + heartless heartless heartlings heartl + heartly heartli hearts heart + heartsick heartsick heartstrings heartstr + hearty hearti heat heat + heated heat heath heath + heathen heathen heathenish heathenish + heating heat heats heat + heauties heauti heav heav + heave heav heaved heav + heaven heaven heavenly heavenli + heavens heaven heaves heav + heavier heavier heaviest heaviest + heavily heavili heaviness heavi + heaving heav heavings heav + heavy heavi hebona hebona + hebrew hebrew hecate hecat + hectic hectic hector hector + hectors hector hecuba hecuba + hedg hedg hedge hedg + hedgehog hedgehog hedgehogs hedgehog + hedges hedg heed heed + heeded heed heedful heed + heedfull heedful heedfully heedfulli + heedless heedless heel heel + heels heel hefted heft + hefts heft heifer heifer + heifers heifer heigh heigh + height height heighten heighten + heinous heinou heinously heinous + heir heir heiress heiress + heirless heirless heirs heir + held held helen helen + helena helena helenus helenu + helias helia helicons helicon + hell hell hellespont hellespont + hellfire hellfir hellish hellish + helm helm helmed helm + helmet helmet helmets helmet + helms helm help help + helper helper helpers helper + helpful help helping help + helpless helpless helps help + helter helter hem hem + heme heme hemlock hemlock + hemm hemm hemp hemp + hempen hempen hems hem + hen hen hence henc + henceforth henceforth henceforward henceforward + henchman henchman henri henri + henricus henricu henry henri + hens hen hent hent + henton henton her her + herald herald heraldry heraldri + heralds herald herb herb + herbert herbert herblets herblet + herbs herb herculean herculean + hercules hercul herd herd + herds herd herdsman herdsman + herdsmen herdsmen here here + hereabout hereabout hereabouts hereabout + hereafter hereaft hereby herebi + hereditary hereditari hereford hereford + herefordshire herefordshir herein herein + hereof hereof heresies heresi + heresy heresi heretic heret + heretics heret hereto hereto + hereupon hereupon heritage heritag + heritier heriti hermes herm + hermia hermia hermione hermion + hermit hermit hermitage hermitag + hermits hermit herne hern + hero hero herod herod + herods herod heroes hero + heroic heroic heroical heroic + herring her herrings her + hers her herself herself + hesperides hesperid hesperus hesperu + hest hest hests hest + heure heur heureux heureux + hew hew hewgh hewgh + hewing hew hewn hewn + hews hew hey hei + heyday heydai hibocrates hibocr + hic hic hiccups hiccup + hick hick hid hid + hidden hidden hide hide + hideous hideou hideously hideous + hideousness hideous hides hide + hidest hidest hiding hide + hie hie hied hi + hiems hiem hies hi + hig hig high high + higher higher highest highest + highly highli highmost highmost + highness high hight hight + highway highwai highways highwai + hilding hild hildings hild + hill hill hillo hillo + hilloa hilloa hills hill + hilt hilt hilts hilt + hily hili him him + himself himself hinc hinc + hinckley hincklei hind hind + hinder hinder hindered hinder + hinders hinder hindmost hindmost + hinds hind hing hing + hinge hing hinges hing + hint hint hip hip + hipp hipp hipparchus hipparchu + hippolyta hippolyta hips hip + hir hir hire hire + hired hire hiren hiren + hirtius hirtiu his hi + hisperia hisperia hiss hiss + hisses hiss hissing hiss + hist hist historical histor + history histori hit hit + hither hither hitherto hitherto + hitherward hitherward hitherwards hitherward + hits hit hitting hit + hive hive hives hive + hizzing hizz ho ho + hoa hoa hoar hoar + hoard hoard hoarded hoard + hoarding hoard hoars hoar + hoarse hoars hoary hoari + hob hob hobbididence hobbidid + hobby hobbi hobbyhorse hobbyhors + hobgoblin hobgoblin hobnails hobnail + hoc hoc hod hod + hodge hodg hog hog + hogs hog hogshead hogshead + hogsheads hogshead hois hoi + hoise hois hoist hoist + hoisted hoist hoists hoist + holborn holborn hold hold + holden holden holder holder + holdeth holdeth holdfast holdfast + holding hold holds hold + hole hole holes hole + holidam holidam holidame holidam + holiday holidai holidays holidai + holier holier holiest holiest + holily holili holiness holi + holla holla holland holland + hollander holland hollanders holland + holloa holloa holloaing holloa + hollow hollow hollowly hollowli + hollowness hollow holly holli + holmedon holmedon holofernes holofern + holp holp holy holi + homage homag homager homag + home home homely home + homes home homespuns homespun + homeward homeward homewards homeward + homicide homicid homicides homicid + homily homili hominem hominem + hommes homm homo homo + honest honest honester honest + honestest honestest honestly honestli + honesty honesti honey honei + honeycomb honeycomb honeying honei + honeyless honeyless honeysuckle honeysuckl + honeysuckles honeysuckl honi honi + honneur honneur honor honor + honorable honor honorably honor + honorato honorato honorificabilitudinitatibus honorificabilitudinitatibu + honors honor honour honour + honourable honour honourably honour + honoured honour honourest honourest + honourible honour honouring honour + honours honour hoo hoo + hood hood hooded hood + hoodman hoodman hoods hood + hoodwink hoodwink hoof hoof + hoofs hoof hook hook + hooking hook hooks hook + hoop hoop hoops hoop + hoot hoot hooted hoot + hooting hoot hoots hoot + hop hop hope hope + hopeful hope hopeless hopeless + hopes hope hopest hopest + hoping hope hopkins hopkin + hoppedance hopped hor hor + horace horac horatio horatio + horizon horizon horn horn + hornbook hornbook horned horn + horner horner horning horn + hornpipes hornpip horns horn + horologe horolog horrible horribl + horribly horribl horrid horrid + horrider horrid horridly horridli + horror horror horrors horror + hors hor horse hors + horseback horseback horsed hors + horsehairs horsehair horseman horseman + horsemanship horsemanship horsemen horsemen + horses hors horseway horsewai + horsing hors hortensio hortensio + hortensius hortensiu horum horum + hose hose hospitable hospit + hospital hospit hospitality hospit + host host hostage hostag + hostages hostag hostess hostess + hostile hostil hostility hostil + hostilius hostiliu hosts host + hot hot hotly hotli + hotspur hotspur hotter hotter + hottest hottest hound hound + hounds hound hour hour + hourly hourli hours hour + hous hou house hous + household household householder household + householders household households household + housekeeper housekeep housekeepers housekeep + housekeeping housekeep houseless houseless + houses hous housewife housewif + housewifery housewiferi housewives housew + hovel hovel hover hover + hovered hover hovering hover + hovers hover how how + howbeit howbeit howe how + howeer howeer however howev + howl howl howled howl + howlet howlet howling howl + howls howl howsoe howso + howsoever howsoev howsome howsom + hoxes hox hoy hoi + hoyday hoydai hubert hubert + huddled huddl huddling huddl + hue hue hued hu + hues hue hug hug + huge huge hugely huge + hugeness huge hugg hugg + hugger hugger hugh hugh + hugs hug hujus huju + hulk hulk hulks hulk + hull hull hulling hull + hullo hullo hum hum + human human humane human + humanely human humanity human + humble humbl humbled humbl + humbleness humbl humbler humbler + humbles humbl humblest humblest + humbling humbl humbly humbl + hume hume humh humh + humidity humid humility humil + humming hum humor humor + humorous humor humors humor + humour humour humourists humourist + humours humour humphrey humphrei + humphry humphri hums hum + hundred hundr hundreds hundr + hundredth hundredth hung hung + hungarian hungarian hungary hungari + hunger hunger hungerford hungerford + hungerly hungerli hungry hungri + hunt hunt hunted hunt + hunter hunter hunters hunter + hunteth hunteth hunting hunt + huntington huntington huntress huntress + hunts hunt huntsman huntsman + huntsmen huntsmen hurdle hurdl + hurl hurl hurling hurl + hurls hurl hurly hurli + hurlyburly hurlyburli hurricano hurricano + hurricanoes hurricano hurried hurri + hurries hurri hurry hurri + hurt hurt hurting hurt + hurtled hurtl hurtless hurtless + hurtling hurtl hurts hurt + husband husband husbanded husband + husbandless husbandless husbandry husbandri + husbands husband hush hush + hushes hush husht husht + husks husk huswife huswif + huswifes huswif hutch hutch + hybla hybla hydra hydra + hyen hyen hymen hymen + hymenaeus hymenaeu hymn hymn + hymns hymn hyperboles hyperbol + hyperbolical hyperbol hyperion hyperion + hypocrisy hypocrisi hypocrite hypocrit + hypocrites hypocrit hyrcan hyrcan + hyrcania hyrcania hyrcanian hyrcanian + hyssop hyssop hysterica hysterica + i i iachimo iachimo + iaculis iaculi iago iago + iament iament ibat ibat + icarus icaru ice ic + iceland iceland ici ici + icicle icicl icicles icicl + icy ici idea idea + ideas idea idem idem + iden iden ides id + idiot idiot idiots idiot + idle idl idleness idl + idles idl idly idli + idol idol idolatrous idolatr + idolatry idolatri ield ield + if if ifs if + ignis igni ignoble ignobl + ignobly ignobl ignominious ignomini + ignominy ignomini ignomy ignomi + ignorance ignor ignorant ignor + ii ii iii iii + iiii iiii il il + ilbow ilbow ild ild + ilion ilion ilium ilium + ill ill illegitimate illegitim + illiterate illiter illness ill + illo illo ills ill + illume illum illumin illumin + illuminate illumin illumineth illumineth + illusion illus illusions illus + illustrate illustr illustrated illustr + illustrious illustri illyria illyria + illyrian illyrian ils il + im im image imag + imagery imageri images imag + imagin imagin imaginary imaginari + imagination imagin imaginations imagin + imagine imagin imagining imagin + imaginings imagin imbar imbar + imbecility imbecil imbrue imbru + imitari imitari imitate imit + imitated imit imitation imit + imitations imit immaculate immacul + immanity imman immask immask + immaterial immateri immediacy immediaci + immediate immedi immediately immedi + imminence immin imminent immin + immoderate immoder immoderately immoder + immodest immodest immoment immoment + immortal immort immortaliz immortaliz + immortally immort immur immur + immured immur immures immur + imogen imogen imp imp + impaint impaint impair impair + impairing impair impale impal + impaled impal impanelled impanel + impart impart imparted impart + impartial imparti impartment impart + imparts impart impasted impast + impatience impati impatient impati + impatiently impati impawn impawn + impeach impeach impeached impeach + impeachment impeach impeachments impeach + impedes imped impediment impedi + impediments impedi impenetrable impenetr + imperator imper imperceiverant imperceiver + imperfect imperfect imperfection imperfect + imperfections imperfect imperfectly imperfectli + imperial imperi imperious imperi + imperiously imperi impertinency impertin + impertinent impertin impeticos impetico + impetuosity impetuos impetuous impetu + impieties impieti impiety impieti + impious impiou implacable implac + implements implement implies impli + implor implor implorators implor + implore implor implored implor + imploring implor impon impon + import import importance import + importancy import important import + importantly importantli imported import + importeth importeth importing import + importless importless imports import + importun importun importunacy importunaci + importunate importun importune importun + importunes importun importunity importun + impos impo impose impos + imposed impos imposition imposit + impositions imposit impossibilities imposs + impossibility imposs impossible imposs + imposthume imposthum impostor impostor + impostors impostor impotence impot + impotent impot impounded impound + impregnable impregn imprese impres + impress impress impressed impress + impressest impressest impression impress + impressure impressur imprimendum imprimendum + imprimis imprimi imprint imprint + imprinted imprint imprison imprison + imprisoned imprison imprisoning imprison + imprisonment imprison improbable improb + improper improp improve improv + improvident improvid impudence impud + impudency impud impudent impud + impudently impud impudique impudiqu + impugn impugn impugns impugn + impure impur imputation imput + impute imput in in + inaccessible inaccess inaidable inaid + inaudible inaud inauspicious inauspici + incaged incag incantations incant + incapable incap incardinate incardin + incarnadine incarnadin incarnate incarn + incarnation incarn incens incen + incense incens incensed incens + incensement incens incenses incens + incensing incens incertain incertain + incertainties incertainti incertainty incertainti + incessant incess incessantly incessantli + incest incest incestuous incestu + inch inch incharitable incharit + inches inch incidency incid + incident incid incision incis + incite incit incites incit + incivil incivil incivility incivil + inclin inclin inclinable inclin + inclination inclin incline inclin + inclined inclin inclines inclin + inclining inclin inclips inclip + include includ included includ + includes includ inclusive inclus + incomparable incompar incomprehensible incomprehens + inconsiderate inconsider inconstancy inconst + inconstant inconst incontinency incontin + incontinent incontin incontinently incontin + inconvenience inconveni inconveniences inconveni + inconvenient inconveni incony inconi + incorporate incorpor incorps incorp + incorrect incorrect increas increa + increase increas increases increas + increaseth increaseth increasing increas + incredible incred incredulous incredul + incur incur incurable incur + incurr incurr incurred incur + incursions incurs ind ind + inde ind indebted indebt + indeed inde indent indent + indented indent indenture indentur + indentures indentur index index + indexes index india india + indian indian indict indict + indicted indict indictment indict + indies indi indifferency indiffer + indifferent indiffer indifferently indiffer + indigent indig indigest indigest + indigested indigest indign indign + indignation indign indignations indign + indigne indign indignities indign + indignity indign indirect indirect + indirection indirect indirections indirect + indirectly indirectli indiscreet indiscreet + indiscretion indiscret indispos indispo + indisposition indisposit indissoluble indissolubl + indistinct indistinct indistinguish indistinguish + indistinguishable indistinguish indited indit + individable individ indrench indrench + indu indu indubitate indubit + induc induc induce induc + induced induc inducement induc + induction induct inductions induct + indue indu indued indu + indues indu indulgence indulg + indulgences indulg indulgent indulg + indurance indur industrious industri + industriously industri industry industri + inequality inequ inestimable inestim + inevitable inevit inexecrable inexecr + inexorable inexor inexplicable inexplic + infallible infal infallibly infal + infamonize infamon infamous infam + infamy infami infancy infanc + infant infant infants infant + infect infect infected infect + infecting infect infection infect + infections infect infectious infecti + infectiously infecti infects infect + infer infer inference infer + inferior inferior inferiors inferior + infernal infern inferr inferr + inferreth inferreth inferring infer + infest infest infidel infidel + infidels infidel infinite infinit + infinitely infinit infinitive infinit + infirm infirm infirmities infirm + infirmity infirm infixed infix + infixing infix inflam inflam + inflame inflam inflaming inflam + inflammation inflamm inflict inflict + infliction inflict influence influenc + influences influenc infold infold + inform inform informal inform + information inform informations inform + informed inform informer inform + informs inform infortunate infortun + infring infr infringe infring + infringed infring infus infu + infuse infus infused infus + infusing infus infusion infus + ingener ingen ingenious ingeni + ingeniously ingeni inglorious inglori + ingots ingot ingraffed ingraf + ingraft ingraft ingrate ingrat + ingrated ingrat ingrateful ingrat + ingratitude ingratitud ingratitudes ingratitud + ingredient ingredi ingredients ingredi + ingross ingross inhabit inhabit + inhabitable inhabit inhabitants inhabit + inhabited inhabit inhabits inhabit + inhearse inhears inhearsed inhears + inherent inher inherit inherit + inheritance inherit inherited inherit + inheriting inherit inheritor inheritor + inheritors inheritor inheritrix inheritrix + inherits inherit inhibited inhibit + inhibition inhibit inhoop inhoop + inhuman inhuman iniquities iniqu + iniquity iniqu initiate initi + injointed injoint injunction injunct + injunctions injunct injur injur + injure injur injurer injur + injuries injuri injurious injuri + injury injuri injustice injustic + ink ink inkhorn inkhorn + inkle inkl inkles inkl + inkling inkl inky inki + inlaid inlaid inland inland + inlay inlai inly inli + inmost inmost inn inn + inner inner innkeeper innkeep + innocence innoc innocency innoc + innocent innoc innocents innoc + innovation innov innovator innov + inns inn innumerable innumer + inoculate inocul inordinate inordin + inprimis inprimi inquir inquir + inquire inquir inquiry inquiri + inquisition inquisit inquisitive inquisit + inroads inroad insane insan + insanie insani insatiate insati + insconce insconc inscrib inscrib + inscription inscript inscriptions inscript + inscroll inscrol inscrutable inscrut + insculp insculp insculpture insculptur + insensible insens inseparable insepar + inseparate insepar insert insert + inserted insert inset inset + inshell inshel inshipp inshipp + inside insid insinewed insinew + insinuate insinu insinuateth insinuateth + insinuating insinu insinuation insinu + insisted insist insisting insist + insisture insistur insociable insoci + insolence insol insolent insol + insomuch insomuch inspir inspir + inspiration inspir inspirations inspir + inspire inspir inspired inspir + install instal installed instal + instalment instal instance instanc + instances instanc instant instant + instantly instantli instate instat + instead instead insteeped insteep + instigate instig instigated instig + instigation instig instigations instig + instigator instig instinct instinct + instinctively instinct institute institut + institutions institut instruct instruct + instructed instruct instruction instruct + instructions instruct instructs instruct + instrument instrument instrumental instrument + instruments instrument insubstantial insubstanti + insufficience insuffici insufficiency insuffici + insult insult insulted insult + insulting insult insultment insult + insults insult insupportable insupport + insuppressive insuppress insurrection insurrect + insurrections insurrect int int + integer integ integritas integrita + integrity integr intellect intellect + intellects intellect intellectual intellectu + intelligence intellig intelligencer intelligenc + intelligencing intelligenc intelligent intellig + intelligis intelligi intelligo intelligo + intemperance intemper intemperate intemper + intend intend intended intend + intendeth intendeth intending intend + intendment intend intends intend + intenible inten intent intent + intention intent intentively intent + intents intent inter inter + intercept intercept intercepted intercept + intercepter intercept interception intercept + intercepts intercept intercession intercess + intercessors intercessor interchained interchain + interchang interchang interchange interchang + interchangeably interchang interchangement interchang + interchanging interchang interdiction interdict + interest interest interim interim + interims interim interior interior + interjections interject interjoin interjoin + interlude interlud intermingle intermingl + intermission intermiss intermissive intermiss + intermit intermit intermix intermix + intermixed intermix interpose interpos + interposer interpos interposes interpos + interpret interpret interpretation interpret + interpreted interpret interpreter interpret + interpreters interpret interprets interpret + interr interr interred inter + interrogatories interrogatori interrupt interrupt + interrupted interrupt interrupter interrupt + interruptest interruptest interruption interrupt + interrupts interrupt intertissued intertissu + intervallums intervallum interview interview + intestate intest intestine intestin + intil intil intimate intim + intimation intim intitled intitl + intituled intitul into into + intolerable intoler intoxicates intox + intreasured intreasur intreat intreat + intrench intrench intrenchant intrench + intricate intric intrinse intrins + intrinsicate intrins intrude intrud + intruder intrud intruding intrud + intrusion intrus inundation inund + inure inur inurn inurn + invade invad invades invad + invasion invas invasive invas + invectively invect invectives invect + inveigled inveigl invent invent + invented invent invention invent + inventions invent inventor inventor + inventorially inventori inventoried inventori + inventors inventor inventory inventori + inverness inver invert invert + invest invest invested invest + investing invest investments invest + inveterate inveter invincible invinc + inviolable inviol invised invis + invisible invis invitation invit + invite invit invited invit + invites invit inviting invit + invitis inviti invocate invoc + invocation invoc invoke invok + invoked invok invulnerable invulner + inward inward inwardly inwardli + inwardness inward inwards inward + ionia ionia ionian ionian + ipse ips ipswich ipswich + ira ira irae ira + iras ira ire ir + ireful ir ireland ireland + iris iri irish irish + irishman irishman irishmen irishmen + irks irk irksome irksom + iron iron irons iron + irreconcil irreconcil irrecoverable irrecover + irregular irregular irregulous irregul + irreligious irreligi irremovable irremov + irreparable irrepar irresolute irresolut + irrevocable irrevoc is is + isabel isabel isabella isabella + isbel isbel isbels isbel + iscariot iscariot ise is + ish ish isidore isidor + isis isi island island + islander island islanders island + islands island isle isl + isles isl israel israel + issu issu issue issu + issued issu issueless issueless + issues issu issuing issu + ist ist ista ista + it it italian italian + italy itali itch itch + itches itch itching itch + item item items item + iteration iter ithaca ithaca + its it itself itself + itshall itshal iv iv + ivory ivori ivy ivi + iwis iwi ix ix + j j jacet jacet + jack jack jackanapes jackanap + jacks jack jacksauce jacksauc + jackslave jackslav jacob jacob + jade jade jaded jade + jades jade jail jail + jakes jake jamany jamani + james jame jamy jami + jane jane jangled jangl + jangling jangl january januari + janus janu japhet japhet + jaquenetta jaquenetta jaques jaqu + jar jar jarring jar + jars jar jarteer jarteer + jasons jason jaunce jaunc + jauncing jaunc jaundice jaundic + jaundies jaundi jaw jaw + jawbone jawbon jaws jaw + jay jai jays jai + jc jc je je + jealous jealou jealousies jealousi + jealousy jealousi jeer jeer + jeering jeer jelly jelli + jenny jenni jeopardy jeopardi + jephtha jephtha jephthah jephthah + jerkin jerkin jerkins jerkin + jerks jerk jeronimy jeronimi + jerusalem jerusalem jeshu jeshu + jesses jess jessica jessica + jest jest jested jest + jester jester jesters jester + jesting jest jests jest + jesu jesu jesus jesu + jet jet jets jet + jew jew jewel jewel + jeweller jewel jewels jewel + jewess jewess jewish jewish + jewry jewri jews jew + jezebel jezebel jig jig + jigging jig jill jill + jills jill jingling jingl + joan joan job job + jockey jockei jocund jocund + jog jog jogging jog + john john johns john + join join joinder joinder + joined join joiner joiner + joineth joineth joins join + joint joint jointed joint + jointing joint jointly jointli + jointress jointress joints joint + jointure jointur jollity jolliti + jolly jolli jolt jolt + joltheads jolthead jordan jordan + joseph joseph joshua joshua + jot jot jour jour + jourdain jourdain journal journal + journey journei journeying journei + journeyman journeyman journeymen journeymen + journeys journei jove jove + jovem jovem jovial jovial + jowl jowl jowls jowl + joy joi joyed joi + joyful joy joyfully joyfulli + joyless joyless joyous joyou + joys joi juan juan + jud jud judas juda + judases judas jude jude + judg judg judge judg + judged judg judgement judgement + judges judg judgest judgest + judging judg judgment judgment + judgments judgment judicious judici + jug jug juggle juggl + juggled juggl juggler juggler + jugglers juggler juggling juggl + jugs jug juice juic + juiced juic jul jul + jule jule julia julia + juliet juliet julietta julietta + julio julio julius juliu + july juli jump jump + jumpeth jumpeth jumping jump + jumps jump june june + junes june junior junior + junius juniu junkets junket + juno juno jupiter jupit + jure jure jurement jurement + jurisdiction jurisdict juror juror + jurors juror jury juri + jurymen jurymen just just + justeius justeiu justest justest + justice justic justicer justic + justicers justic justices justic + justification justif justified justifi + justify justifi justle justl + justled justl justles justl + justling justl justly justli + justness just justs just + jutting jut jutty jutti + juvenal juven kam kam + kate kate kated kate + kates kate katharine katharin + katherina katherina katherine katherin + kecksies kecksi keech keech + keel keel keels keel + keen keen keenness keen + keep keep keepdown keepdown + keeper keeper keepers keeper + keepest keepest keeping keep + keeps keep keiser keiser + ken ken kendal kendal + kennel kennel kent kent + kentish kentish kentishman kentishman + kentishmen kentishmen kept kept + kerchief kerchief kerely kere + kern kern kernal kernal + kernel kernel kernels kernel + kerns kern kersey kersei + kettle kettl kettledrum kettledrum + kettledrums kettledrum key kei + keys kei kibe kibe + kibes kibe kick kick + kicked kick kickshaws kickshaw + kickshawses kickshaws kicky kicki + kid kid kidney kidnei + kikely kike kildare kildar + kill kill killed kill + killer killer killeth killeth + killing kill killingworth killingworth + kills kill kiln kiln + kimbolton kimbolton kin kin + kind kind kinder kinder + kindest kindest kindle kindl + kindled kindl kindless kindless + kindlier kindlier kindling kindl + kindly kindli kindness kind + kindnesses kind kindred kindr + kindreds kindr kinds kind + kine kine king king + kingdom kingdom kingdoms kingdom + kingly kingli kings king + kinred kinr kins kin + kinsman kinsman kinsmen kinsmen + kinswoman kinswoman kirtle kirtl + kirtles kirtl kiss kiss + kissed kiss kisses kiss + kissing kiss kitchen kitchen + kitchens kitchen kite kite + kites kite kitten kitten + kj kj kl kl + klll klll knack knack + knacks knack knapp knapp + knav knav knave knave + knaveries knaveri knavery knaveri + knaves knave knavish knavish + knead knead kneaded knead + kneading knead knee knee + kneel kneel kneeling kneel + kneels kneel knees knee + knell knell knew knew + knewest knewest knife knife + knight knight knighted knight + knighthood knighthood knighthoods knighthood + knightly knightli knights knight + knit knit knits knit + knitters knitter knitteth knitteth + knives knive knobs knob + knock knock knocking knock + knocks knock knog knog + knoll knoll knot knot + knots knot knotted knot + knotty knotti know know + knower knower knowest knowest + knowing know knowingly knowingli + knowings know knowledge knowledg + known known knows know + l l la la + laban laban label label + labell label labienus labienu + labio labio labor labor + laboring labor labors labor + labour labour laboured labour + labourer labour labourers labour + labouring labour labours labour + laboursome laboursom labras labra + labyrinth labyrinth lac lac + lace lace laced lace + lacedaemon lacedaemon laces lace + lacies laci lack lack + lackbeard lackbeard lacked lack + lackey lackei lackeying lackei + lackeys lackei lacking lack + lacks lack lad lad + ladder ladder ladders ladder + lade lade laden laden + ladies ladi lading lade + lads lad lady ladi + ladybird ladybird ladyship ladyship + ladyships ladyship laer laer + laertes laert lafeu lafeu + lag lag lagging lag + laid laid lain lain + laissez laissez lake lake + lakes lake lakin lakin + lam lam lamb lamb + lambert lambert lambkin lambkin + lambkins lambkin lambs lamb + lame lame lamely lame + lameness lame lament lament + lamentable lament lamentably lament + lamentation lament lamentations lament + lamented lament lamenting lament + lamentings lament laments lament + lames lame laming lame + lammas lamma lammastide lammastid + lamound lamound lamp lamp + lampass lampass lamps lamp + lanc lanc lancaster lancast + lance lanc lances lanc + lanceth lanceth lanch lanch + land land landed land + landing land landless landless + landlord landlord landmen landmen + lands land lane lane + lanes lane langage langag + langley langlei langton langton + language languag languageless languageless + languages languag langues langu + languish languish languished languish + languishes languish languishing languish + languishings languish languishment languish + languor languor lank lank + lantern lantern lanterns lantern + lanthorn lanthorn lap lap + lapis lapi lapland lapland + lapp lapp laps lap + lapse laps lapsed laps + lapsing laps lapwing lapw + laquais laquai larded lard + larder larder larding lard + lards lard large larg + largely larg largeness larg + larger larger largess largess + largest largest lark lark + larks lark larron larron + lartius lartiu larum larum + larums larum las la + lascivious lascivi lash lash + lass lass lasses lass + last last lasted last + lasting last lastly lastli + lasts last latch latch + latches latch late late + lated late lately late + later later latest latest + lath lath latin latin + latten latten latter latter + lattice lattic laud laud + laudable laudabl laudis laudi + laugh laugh laughable laughabl + laughed laugh laugher laugher + laughest laughest laughing laugh + laughs laugh laughter laughter + launce launc launcelot launcelot + launces launc launch launch + laund laund laundress laundress + laundry laundri laur laur + laura laura laurel laurel + laurels laurel laurence laurenc + laus lau lavache lavach + lave lave lavee lave + lavender lavend lavina lavina + lavinia lavinia lavish lavish + lavishly lavishli lavolt lavolt + lavoltas lavolta law law + lawful law lawfully lawfulli + lawless lawless lawlessly lawlessli + lawn lawn lawns lawn + lawrence lawrenc laws law + lawyer lawyer lawyers lawyer + lay lai layer layer + layest layest laying lai + lays lai lazar lazar + lazars lazar lazarus lazaru + lazy lazi lc lc + ld ld ldst ldst + le le lead lead + leaden leaden leader leader + leaders leader leadest leadest + leading lead leads lead + leaf leaf leagu leagu + league leagu leagued leagu + leaguer leaguer leagues leagu + leah leah leak leak + leaky leaki lean lean + leander leander leaner leaner + leaning lean leanness lean + leans lean leap leap + leaped leap leaping leap + leaps leap leapt leapt + lear lear learn learn + learned learn learnedly learnedli + learning learn learnings learn + learns learn learnt learnt + leas lea lease leas + leases leas leash leash + leasing leas least least + leather leather leathern leathern + leav leav leave leav + leaven leaven leavening leaven + leaver leaver leaves leav + leaving leav leavy leavi + lecher lecher lecherous lecher + lechers lecher lechery lecheri + lecon lecon lecture lectur + lectures lectur led led + leda leda leech leech + leeches leech leek leek + leeks leek leer leer + leers leer lees lee + leese lees leet leet + leets leet left left + leg leg legacies legaci + legacy legaci legate legat + legatine legatin lege lege + legerity leger leges lege + legg legg legion legion + legions legion legitimate legitim + legitimation legitim legs leg + leicester leicest leicestershire leicestershir + leiger leiger leigers leiger + leisure leisur leisurely leisur + leisures leisur leman leman + lemon lemon lena lena + lend lend lender lender + lending lend lendings lend + lends lend length length + lengthen lengthen lengthens lengthen + lengths length lenity leniti + lennox lennox lent lent + lenten lenten lentus lentu + leo leo leon leon + leonardo leonardo leonati leonati + leonato leonato leonatus leonatu + leontes leont leopard leopard + leopards leopard leper leper + leperous leper lepidus lepidu + leprosy leprosi lequel lequel + lers ler les le + less less lessen lessen + lessens lessen lesser lesser + lesson lesson lessoned lesson + lessons lesson lest lest + lestrake lestrak let let + lethargied lethargi lethargies lethargi + lethargy lethargi lethe leth + lets let lett lett + letter letter letters letter + letting let lettuce lettuc + leur leur leve leve + level level levell level + levelled level levels level + leven leven levers lever + leviathan leviathan leviathans leviathan + levied levi levies levi + levity leviti levy levi + levying levi lewd lewd + lewdly lewdli lewdness lewd + lewdsters lewdster lewis lewi + liable liabl liar liar + liars liar libbard libbard + libelling libel libels libel + liberal liber liberality liber + liberte libert liberties liberti + libertine libertin libertines libertin + liberty liberti library librari + libya libya licence licenc + licens licen license licens + licentious licenti lichas licha + licio licio lick lick + licked lick licker licker + lictors lictor lid lid + lids lid lie lie + lied li lief lief + liefest liefest liege lieg + liegeman liegeman liegemen liegemen + lien lien lies li + liest liest lieth lieth + lieu lieu lieutenant lieuten + lieutenantry lieutenantri lieutenants lieuten + lieve liev life life + lifeblood lifeblood lifeless lifeless + lifelings lifel lift lift + lifted lift lifter lifter + lifteth lifteth lifting lift + lifts lift lig lig + ligarius ligariu liggens liggen + light light lighted light + lighten lighten lightens lighten + lighter lighter lightest lightest + lightly lightli lightness light + lightning lightn lightnings lightn + lights light lik lik + like like liked like + likeliest likeliest likelihood likelihood + likelihoods likelihood likely like + likeness like liker liker + likes like likest likest + likewise likewis liking like + likings like lilies lili + lily lili lim lim + limander limand limb limb + limbeck limbeck limbecks limbeck + limber limber limbo limbo + limbs limb lime lime + limed lime limehouse limehous + limekilns limekiln limit limit + limitation limit limited limit + limits limit limn limn + limp limp limping limp + limps limp lin lin + lincoln lincoln lincolnshire lincolnshir + line line lineal lineal + lineally lineal lineament lineament + lineaments lineament lined line + linen linen linens linen + lines line ling ling + lingare lingar linger linger + lingered linger lingers linger + linguist linguist lining line + link link links link + linsey linsei linstock linstock + linta linta lion lion + lionel lionel lioness lioness + lions lion lip lip + lipp lipp lips lip + lipsbury lipsburi liquid liquid + liquor liquor liquorish liquorish + liquors liquor lirra lirra + lisbon lisbon lisp lisp + lisping lisp list list + listen listen listening listen + lists list literatured literatur + lither lither litter litter + little littl littlest littlest + liv liv live live + lived live livelier liveli + livelihood livelihood livelong livelong + lively live liver liver + liveries liveri livers liver + livery liveri lives live + livest livest liveth liveth + livia livia living live + livings live lizard lizard + lizards lizard ll ll + lll lll llous llou + lnd lnd lo lo + loa loa loach loach + load load loaden loaden + loading load loads load + loaf loaf loam loam + loan loan loath loath + loathe loath loathed loath + loather loather loathes loath + loathing loath loathly loathli + loathness loath loathsome loathsom + loathsomeness loathsom loathsomest loathsomest + loaves loav lob lob + lobbies lobbi lobby lobbi + local local lochaber lochab + lock lock locked lock + locking lock lockram lockram + locks lock locusts locust + lode lode lodg lodg + lodge lodg lodged lodg + lodgers lodger lodges lodg + lodging lodg lodgings lodg + lodovico lodovico lodowick lodowick + lofty lofti log log + logger logger loggerhead loggerhead + loggerheads loggerhead loggets logget + logic logic logs log + loins loin loiter loiter + loiterer loiter loiterers loiter + loitering loiter lolling loll + lolls loll lombardy lombardi + london london londoners london + lone lone loneliness loneli + lonely lone long long + longaville longavil longboat longboat + longed long longer longer + longest longest longeth longeth + longing long longings long + longly longli longs long + longtail longtail loo loo + loof loof look look + looked look looker looker + lookers looker lookest lookest + looking look looks look + loon loon loop loop + loos loo loose loos + loosed loos loosely loos + loosen loosen loosing loos + lop lop lopp lopp + loquitur loquitur lord lord + lorded lord lording lord + lordings lord lordliness lordli + lordly lordli lords lord + lordship lordship lordships lordship + lorenzo lorenzo lorn lorn + lorraine lorrain lorship lorship + los lo lose lose + loser loser losers loser + loses lose losest losest + loseth loseth losing lose + loss loss losses loss + lost lost lot lot + lots lot lott lott + lottery lotteri loud loud + louder louder loudly loudli + lour lour loureth loureth + louring lour louse lous + louses lous lousy lousi + lout lout louted lout + louts lout louvre louvr + lov lov love love + loved love lovedst lovedst + lovel lovel lovelier loveli + loveliness loveli lovell lovel + lovely love lover lover + lovered lover lovers lover + loves love lovest lovest + loveth loveth loving love + lovingly lovingli low low + lowe low lower lower + lowest lowest lowing low + lowliness lowli lowly lowli + lown lown lowness low + loyal loyal loyally loyal + loyalties loyalti loyalty loyalti + lozel lozel lt lt + lubber lubber lubberly lubberli + luc luc luccicos luccico + luce luce lucentio lucentio + luces luce lucetta lucetta + luciana luciana lucianus lucianu + lucifer lucif lucifier lucifi + lucilius luciliu lucina lucina + lucio lucio lucius luciu + luck luck luckier luckier + luckiest luckiest luckily luckili + luckless luckless lucky lucki + lucre lucr lucrece lucrec + lucretia lucretia lucullius luculliu + lucullus lucullu lucy luci + lud lud ludlow ludlow + lug lug lugg lugg + luggage luggag luke luke + lukewarm lukewarm lull lull + lulla lulla lullaby lullabi + lulls lull lumbert lumbert + lump lump lumpish lumpish + luna luna lunacies lunaci + lunacy lunaci lunatic lunat + lunatics lunat lunes lune + lungs lung lupercal luperc + lurch lurch lure lure + lurk lurk lurketh lurketh + lurking lurk lurks lurk + luscious lusciou lush lush + lust lust lusted lust + luster luster lustful lust + lustier lustier lustiest lustiest + lustig lustig lustihood lustihood + lustily lustili lustre lustr + lustrous lustrou lusts lust + lusty lusti lute lute + lutes lute lutestring lutestr + lutheran lutheran luxurious luxuri + luxuriously luxuri luxury luxuri + ly ly lycaonia lycaonia + lycurguses lycurgus lydia lydia + lye lye lyen lyen + lying ly lym lym + lymoges lymog lynn lynn + lysander lysand m m + ma ma maan maan + mab mab macbeth macbeth + maccabaeus maccabaeu macdonwald macdonwald + macduff macduff mace mace + macedon macedon maces mace + machiavel machiavel machination machin + machinations machin machine machin + mack mack macmorris macmorri + maculate macul maculation macul + mad mad madam madam + madame madam madams madam + madcap madcap madded mad + madding mad made made + madeira madeira madly madli + madman madman madmen madmen + madness mad madonna madonna + madrigals madrig mads mad + maecenas maecena maggot maggot + maggots maggot magic magic + magical magic magician magician + magistrate magistr magistrates magistr + magnanimity magnanim magnanimous magnanim + magni magni magnifi magnifi + magnificence magnific magnificent magnific + magnifico magnifico magnificoes magnifico + magnus magnu mahomet mahomet + mahu mahu maid maid + maiden maiden maidenhead maidenhead + maidenheads maidenhead maidenhood maidenhood + maidenhoods maidenhood maidenliest maidenliest + maidenly maidenli maidens maiden + maidhood maidhood maids maid + mail mail mailed mail + mails mail maim maim + maimed maim maims maim + main main maincourse maincours + maine main mainly mainli + mainmast mainmast mains main + maintain maintain maintained maintain + maintains maintain maintenance mainten + mais mai maison maison + majestas majesta majestee majeste + majestic majest majestical majest + majestically majest majesties majesti + majesty majesti major major + majority major mak mak + make make makeless makeless + maker maker makers maker + makes make makest makest + maketh maketh making make + makings make mal mal + mala mala maladies maladi + malady maladi malapert malapert + malcolm malcolm malcontent malcont + malcontents malcont male male + maledictions maledict malefactions malefact + malefactor malefactor malefactors malefactor + males male malevolence malevol + malevolent malevol malhecho malhecho + malice malic malicious malici + maliciously malici malign malign + malignancy malign malignant malign + malignantly malignantli malkin malkin + mall mall mallard mallard + mallet mallet mallows mallow + malmsey malmsei malt malt + maltworms maltworm malvolio malvolio + mamillius mamilliu mammering mammer + mammet mammet mammets mammet + mammock mammock man man + manacle manacl manacles manacl + manage manag managed manag + manager manag managing manag + manakin manakin manchus manchu + mandate mandat mandragora mandragora + mandrake mandrak mandrakes mandrak + mane mane manent manent + manes mane manet manet + manfully manfulli mangle mangl + mangled mangl mangles mangl + mangling mangl mangy mangi + manhood manhood manhoods manhood + manifest manifest manifested manifest + manifests manifest manifold manifold + manifoldly manifoldli manka manka + mankind mankind manlike manlik + manly manli mann mann + manna manna manner manner + mannerly mannerli manners manner + manningtree manningtre mannish mannish + manor manor manors manor + mans man mansion mansion + mansionry mansionri mansions mansion + manslaughter manslaught mantle mantl + mantled mantl mantles mantl + mantua mantua mantuan mantuan + manual manual manure manur + manured manur manus manu + many mani map map + mapp mapp maps map + mar mar marble marbl + marbled marbl marcade marcad + marcellus marcellu march march + marches march marcheth marcheth + marching march marchioness marchio + marchpane marchpan marcians marcian + marcius marciu marcus marcu + mardian mardian mare mare + mares mare marg marg + margarelon margarelon margaret margaret + marge marg margent margent + margery margeri maria maria + marian marian mariana mariana + maries mari marigold marigold + mariner marin mariners marin + maritime maritim marjoram marjoram + mark mark marked mark + market market marketable market + marketplace marketplac markets market + marking mark markman markman + marks mark marl marl + marle marl marmoset marmoset + marquess marquess marquis marqui + marr marr marriage marriag + marriages marriag married marri + marries marri marring mar + marrow marrow marrowless marrowless + marrows marrow marry marri + marrying marri mars mar + marseilles marseil marsh marsh + marshal marshal marshalsea marshalsea + marshalship marshalship mart mart + marted mart martem martem + martext martext martial martial + martin martin martino martino + martius martiu martlemas martlema + martlet martlet marts mart + martyr martyr martyrs martyr + marullus marullu marv marv + marvel marvel marvell marvel + marvellous marvel marvellously marvel + marvels marvel mary mari + mas ma masculine masculin + masham masham mask mask + masked mask masker masker + maskers masker masking mask + masks mask mason mason + masonry masonri masons mason + masque masqu masquers masquer + masques masqu masquing masqu + mass mass massacre massacr + massacres massacr masses mass + massy massi mast mast + mastcr mastcr master master + masterdom masterdom masterest masterest + masterless masterless masterly masterli + masterpiece masterpiec masters master + mastership mastership mastic mastic + mastiff mastiff mastiffs mastiff + masts mast match match + matches match matcheth matcheth + matching match matchless matchless + mate mate mated mate + mater mater material materi + mates mate mathematics mathemat + matin matin matron matron + matrons matron matter matter + matters matter matthew matthew + mattock mattock mattress mattress + mature matur maturity matur + maud maud maudlin maudlin + maugre maugr maul maul + maund maund mauri mauri + mauritania mauritania mauvais mauvai + maw maw maws maw + maxim maxim may mai + mayday maydai mayest mayest + mayor mayor maypole maypol + mayst mayst maz maz + maze maze mazed maze + mazes maze mazzard mazzard + me me meacock meacock + mead mead meadow meadow + meadows meadow meads mead + meagre meagr meal meal + meals meal mealy meali + mean mean meanders meander + meaner meaner meanest meanest + meaneth meaneth meaning mean + meanings mean meanly meanli + means mean meant meant + meantime meantim meanwhile meanwhil + measles measl measur measur + measurable measur measure measur + measured measur measureless measureless + measures measur measuring measur + meat meat meats meat + mechanic mechan mechanical mechan + mechanicals mechan mechanics mechan + mechante mechant med med + medal medal meddle meddl + meddler meddler meddling meddl + mede mede medea medea + media media mediation mediat + mediators mediat medice medic + medicinal medicin medicine medicin + medicines medicin meditate medit + meditates medit meditating medit + meditation medit meditations medit + mediterranean mediterranean mediterraneum mediterraneum + medlar medlar medlars medlar + meed meed meeds meed + meek meek meekly meekli + meekness meek meet meet + meeter meeter meetest meetest + meeting meet meetings meet + meetly meetli meetness meet + meets meet meg meg + mehercle mehercl meilleur meilleur + meiny meini meisen meisen + melancholies melancholi melancholy melancholi + melford melford mell mell + mellifluous melliflu mellow mellow + mellowing mellow melodious melodi + melody melodi melt melt + melted melt melteth melteth + melting melt melts melt + melun melun member member + members member memento memento + memorable memor memorandums memorandum + memorial memori memorials memori + memories memori memoriz memoriz + memorize memor memory memori + memphis memphi men men + menac menac menace menac + menaces menac menaphon menaphon + menas mena mend mend + mended mend mender mender + mending mend mends mend + menecrates menecr menelaus menelau + menenius meneniu mental mental + menteith menteith mention mention + mentis menti menton menton + mephostophilus mephostophilu mer mer + mercatante mercatant mercatio mercatio + mercenaries mercenari mercenary mercenari + mercer mercer merchandise merchandis + merchandized merchand merchant merchant + merchants merchant mercies merci + merciful merci mercifully mercifulli + merciless merciless mercurial mercuri + mercuries mercuri mercury mercuri + mercutio mercutio mercy merci + mere mere mered mere + merely mere merest merest + meridian meridian merit merit + merited merit meritorious meritori + merits merit merlin merlin + mermaid mermaid mermaids mermaid + merops merop merrier merrier + merriest merriest merrily merrili + merriman merriman merriment merriment + merriments merriment merriness merri + merry merri mervailous mervail + mes me mesh mesh + meshes mesh mesopotamia mesopotamia + mess mess message messag + messages messag messala messala + messaline messalin messenger messeng + messengers messeng messes mess + messina messina met met + metal metal metals metal + metamorphis metamorphi metamorphoses metamorphos + metaphor metaphor metaphysical metaphys + metaphysics metaphys mete mete + metellus metellu meteor meteor + meteors meteor meteyard meteyard + metheglin metheglin metheglins metheglin + methink methink methinks methink + method method methods method + methought methought methoughts methought + metre metr metres metr + metropolis metropoli mette mett + mettle mettl mettled mettl + meus meu mew mew + mewed mew mewling mewl + mexico mexico mi mi + mice mice michael michael + michaelmas michaelma micher micher + miching mich mickle mickl + microcosm microcosm mid mid + midas mida middest middest + middle middl middleham middleham + midnight midnight midriff midriff + midst midst midsummer midsumm + midway midwai midwife midwif + midwives midwiv mienne mienn + might might mightful might + mightier mightier mightiest mightiest + mightily mightili mightiness mighti + mightst mightst mighty mighti + milan milan milch milch + mild mild milder milder + mildest mildest mildew mildew + mildews mildew mildly mildli + mildness mild mile mile + miles mile milford milford + militarist militarist military militari + milk milk milking milk + milkmaid milkmaid milks milk + milksops milksop milky milki + mill mill mille mill + miller miller milliner millin + million million millioned million + millions million mills mill + millstones millston milo milo + mimic mimic minc minc + mince minc minces minc + mincing minc mind mind + minded mind minding mind + mindless mindless minds mind + mine mine mineral miner + minerals miner minerva minerva + mines mine mingle mingl + mingled mingl mingling mingl + minikin minikin minim minim + minime minim minimo minimo + minimus minimu mining mine + minion minion minions minion + minist minist minister minist + ministers minist ministration ministr + minnow minnow minnows minnow + minola minola minority minor + minos mino minotaurs minotaur + minstrel minstrel minstrels minstrel + minstrelsy minstrelsi mint mint + mints mint minute minut + minutely minut minutes minut + minx minx mio mio + mir mir mirable mirabl + miracle miracl miracles miracl + miraculous miracul miranda miranda + mire mire mirror mirror + mirrors mirror mirth mirth + mirthful mirth miry miri + mis mi misadventur misadventur + misadventure misadventur misanthropos misanthropo + misapplied misappli misbecame misbecam + misbecom misbecom misbecome misbecom + misbegot misbegot misbegotten misbegotten + misbeliever misbeliev misbelieving misbeliev + misbhav misbhav miscall miscal + miscalled miscal miscarried miscarri + miscarries miscarri miscarry miscarri + miscarrying miscarri mischance mischanc + mischances mischanc mischief mischief + mischiefs mischief mischievous mischiev + misconceived misconceiv misconst misconst + misconster misconst misconstruction misconstruct + misconstrued misconstru misconstrues misconstru + miscreant miscreant miscreate miscreat + misdeed misde misdeeds misde + misdemean misdemean misdemeanours misdemeanour + misdoubt misdoubt misdoubteth misdoubteth + misdoubts misdoubt misenum misenum + miser miser miserable miser + miserably miser misericorde misericord + miseries miseri misers miser + misery miseri misfortune misfortun + misfortunes misfortun misgive misgiv + misgives misgiv misgiving misgiv + misgoverned misgovern misgovernment misgovern + misgraffed misgraf misguide misguid + mishap mishap mishaps mishap + misheard misheard misinterpret misinterpret + mislead mislead misleader mislead + misleaders mislead misleading mislead + misled misl mislike mislik + misord misord misplac misplac + misplaced misplac misplaces misplac + mispris mispri misprised mispris + misprision mispris misprizing mispriz + misproud misproud misquote misquot + misreport misreport miss miss + missed miss misses miss + misshap misshap misshapen misshapen + missheathed missheath missing miss + missingly missingli missions mission + missive missiv missives missiv + misspoke misspok mist mist + mista mista mistak mistak + mistake mistak mistaken mistaken + mistakes mistak mistaketh mistaketh + mistaking mistak mistakings mistak + mistemp mistemp mistempered mistemp + misterm misterm mistful mist + misthink misthink misthought misthought + mistletoe mistleto mistook mistook + mistreadings mistread mistress mistress + mistresses mistress mistresss mistresss + mistriship mistriship mistrust mistrust + mistrusted mistrust mistrustful mistrust + mistrusting mistrust mists mist + misty misti misus misu + misuse misus misused misus + misuses misus mites mite + mithridates mithrid mitigate mitig + mitigation mitig mix mix + mixed mix mixture mixtur + mixtures mixtur mm mm + mnd mnd moan moan + moans moan moat moat + moated moat mobled mobl + mock mock mockable mockabl + mocker mocker mockeries mockeri + mockers mocker mockery mockeri + mocking mock mocks mock + mockvater mockvat mockwater mockwat + model model modena modena + moderate moder moderately moder + moderation moder modern modern + modest modest modesties modesti + modestly modestli modesty modesti + modicums modicum modo modo + module modul moe moe + moi moi moiety moieti + moist moist moisten moisten + moisture moistur moldwarp moldwarp + mole mole molehill molehil + moles mole molest molest + molestation molest mollification mollif + mollis molli molten molten + molto molto mome mome + moment moment momentary momentari + moming mome mon mon + monachum monachum monarch monarch + monarchies monarchi monarchize monarch + monarcho monarcho monarchs monarch + monarchy monarchi monast monast + monastery monasteri monastic monast + monday mondai monde mond + money monei moneys monei + mong mong monger monger + mongers monger monging mong + mongrel mongrel mongrels mongrel + mongst mongst monk monk + monkey monkei monkeys monkei + monks monk monmouth monmouth + monopoly monopoli mons mon + monsieur monsieur monsieurs monsieur + monster monster monsters monster + monstrous monstrou monstrously monstrous + monstrousness monstrous monstruosity monstruos + montacute montacut montage montag + montague montagu montagues montagu + montano montano montant montant + montez montez montferrat montferrat + montgomery montgomeri month month + monthly monthli months month + montjoy montjoi monument monument + monumental monument monuments monument + mood mood moods mood + moody moodi moon moon + moonbeams moonbeam moonish moonish + moonlight moonlight moons moon + moonshine moonshin moonshines moonshin + moor moor moorfields moorfield + moors moor moorship moorship + mop mop mope mope + moping mope mopping mop + mopsa mopsa moral moral + moraler moral morality moral + moralize moral mordake mordak + more more moreover moreov + mores more morgan morgan + mori mori morisco morisco + morn morn morning morn + mornings morn morocco morocco + morris morri morrow morrow + morrows morrow morsel morsel + morsels morsel mort mort + mortal mortal mortality mortal + mortally mortal mortals mortal + mortar mortar mortgaged mortgag + mortified mortifi mortifying mortifi + mortimer mortim mortimers mortim + mortis morti mortise mortis + morton morton mose mose + moss moss mossgrown mossgrown + most most mote mote + moth moth mother mother + mothers mother moths moth + motion motion motionless motionless + motions motion motive motiv + motives motiv motley motlei + mots mot mought mought + mould mould moulded mould + mouldeth mouldeth moulds mould + mouldy mouldi moult moult + moulten moulten mounch mounch + mounseur mounseur mounsieur mounsieur + mount mount mountain mountain + mountaineer mountain mountaineers mountain + mountainous mountain mountains mountain + mountant mountant mountanto mountanto + mountebank mountebank mountebanks mountebank + mounted mount mounteth mounteth + mounting mount mounts mount + mourn mourn mourned mourn + mourner mourner mourners mourner + mournful mourn mournfully mournfulli + mourning mourn mourningly mourningli + mournings mourn mourns mourn + mous mou mouse mous + mousetrap mousetrap mousing mous + mouth mouth mouthed mouth + mouths mouth mov mov + movables movabl move move + moveable moveabl moveables moveabl + moved move mover mover + movers mover moves move + moveth moveth moving move + movingly movingli movousus movousu + mow mow mowbray mowbrai + mower mower mowing mow + mows mow moy moi + moys moi moyses moys + mrs mr much much + muck muck mud mud + mudded mud muddied muddi + muddy muddi muffins muffin + muffl muffl muffle muffl + muffled muffl muffler muffler + muffling muffl mugger mugger + mugs mug mulberries mulberri + mulberry mulberri mule mule + mules mule muleteers mulet + mulier mulier mulieres mulier + muliteus muliteu mull mull + mulmutius mulmutiu multiplied multipli + multiply multipli multiplying multipli + multipotent multipot multitude multitud + multitudes multitud multitudinous multitudin + mum mum mumble mumbl + mumbling mumbl mummers mummer + mummy mummi mun mun + munch munch muniments muniment + munition munit murd murd + murder murder murdered murder + murderer murder murderers murder + murdering murder murderous murder + murders murder mure mure + murk murk murkiest murkiest + murky murki murmur murmur + murmurers murmur murmuring murmur + murrain murrain murray murrai + murrion murrion murther murther + murtherer murther murtherers murther + murthering murther murtherous murther + murthers murther mus mu + muscadel muscadel muscovites muscovit + muscovits muscovit muscovy muscovi + muse muse muses muse + mush mush mushrooms mushroom + music music musical music + musician musician musicians musician + musics music musing muse + musings muse musk musk + musket musket muskets musket + muskos musko muss muss + mussel mussel mussels mussel + must must mustachio mustachio + mustard mustard mustardseed mustardse + muster muster mustering muster + musters muster musty musti + mutability mutabl mutable mutabl + mutation mutat mutations mutat + mute mute mutes mute + mutest mutest mutine mutin + mutineer mutin mutineers mutin + mutines mutin mutinies mutini + mutinous mutin mutiny mutini + mutius mutiu mutter mutter + muttered mutter mutton mutton + muttons mutton mutual mutual + mutualities mutual mutually mutual + muzzl muzzl muzzle muzzl + muzzled muzzl mv mv + mww mww my my + mynheers mynheer myrmidon myrmidon + myrmidons myrmidon myrtle myrtl + myself myself myst myst + mysteries mysteri mystery mysteri + n n nag nag + nage nage nags nag + naiads naiad nail nail + nails nail nak nak + naked nake nakedness naked + nal nal nam nam + name name named name + nameless nameless namely name + names name namest namest + naming name nan nan + nance nanc nap nap + nape nape napes nape + napkin napkin napkins napkin + naples napl napless napless + napping nap naps nap + narbon narbon narcissus narcissu + narines narin narrow narrow + narrowly narrowli naso naso + nasty nasti nathaniel nathaniel + natifs natif nation nation + nations nation native nativ + nativity nativ natur natur + natural natur naturalize natur + naturally natur nature natur + natured natur natures natur + natus natu naught naught + naughtily naughtili naughty naughti + navarre navarr nave nave + navel navel navigation navig + navy navi nay nai + nayward nayward nayword nayword + nazarite nazarit ne ne + neaf neaf neamnoins neamnoin + neanmoins neanmoin neapolitan neapolitan + neapolitans neapolitan near near + nearer nearer nearest nearest + nearly nearli nearness near + neat neat neatly neatli + neb neb nebour nebour + nebuchadnezzar nebuchadnezzar nec nec + necessaries necessari necessarily necessarili + necessary necessari necessitied necess + necessities necess necessity necess + neck neck necklace necklac + necks neck nectar nectar + ned ned nedar nedar + need need needed need + needer needer needful need + needfull needful needing need + needle needl needles needl + needless needless needly needli + needs need needy needi + neer neer neeze neez + nefas nefa negation negat + negative neg negatives neg + neglect neglect neglected neglect + neglecting neglect neglectingly neglectingli + neglection neglect negligence neglig + negligent neglig negotiate negoti + negotiations negoti negro negro + neigh neigh neighbors neighbor + neighbour neighbour neighbourhood neighbourhood + neighbouring neighbour neighbourly neighbourli + neighbours neighbour neighing neigh + neighs neigh neither neither + nell nell nemean nemean + nemesis nemesi neoptolemus neoptolemu + nephew nephew nephews nephew + neptune neptun ner ner + nereides nereid nerissa nerissa + nero nero neroes nero + ners ner nerve nerv + nerves nerv nervii nervii + nervy nervi nessus nessu + nest nest nestor nestor + nests nest net net + nether nether netherlands netherland + nets net nettle nettl + nettled nettl nettles nettl + neuter neuter neutral neutral + nev nev never never + nevil nevil nevils nevil + new new newborn newborn + newer newer newest newest + newgate newgat newly newli + newness new news new + newsmongers newsmong newt newt + newts newt next next + nibbling nibbl nicanor nicanor + nice nice nicely nice + niceness nice nicer nicer + nicety niceti nicholas nichola + nick nick nickname nicknam + nicks nick niece niec + nieces niec niggard niggard + niggarding niggard niggardly niggardli + nigh nigh night night + nightcap nightcap nightcaps nightcap + nighted night nightgown nightgown + nightingale nightingal nightingales nightingal + nightly nightli nightmare nightmar + nights night nightwork nightwork + nihil nihil nile nile + nill nill nilus nilu + nimble nimbl nimbleness nimbl + nimbler nimbler nimbly nimbl + nine nine nineteen nineteen + ning ning ningly ningli + ninny ninni ninth ninth + ninus ninu niobe niob + niobes niob nip nip + nipp nipp nipping nip + nipple nippl nips nip + nit nit nly nly + nnight nnight nnights nnight + no no noah noah + nob nob nobility nobil + nobis nobi noble nobl + nobleman nobleman noblemen noblemen + nobleness nobl nobler nobler + nobles nobl noblesse nobless + noblest noblest nobly nobli + nobody nobodi noces noce + nod nod nodded nod + nodding nod noddle noddl + noddles noddl noddy noddi + nods nod noes noe + nointed noint nois noi + noise nois noiseless noiseless + noisemaker noisemak noises nois + noisome noisom nole nole + nominate nomin nominated nomin + nomination nomin nominativo nominativo + non non nonage nonag + nonce nonc none none + nonino nonino nonny nonni + nonpareil nonpareil nonsuits nonsuit + nony noni nook nook + nooks nook noon noon + noonday noondai noontide noontid + nor nor norbery norberi + norfolk norfolk norman norman + normandy normandi normans norman + north north northampton northampton + northamptonshire northamptonshir northerly northerli + northern northern northgate northgat + northumberland northumberland northumberlands northumberland + northward northward norway norwai + norways norwai norwegian norwegian + norweyan norweyan nos no + nose nose nosegays nosegai + noseless noseless noses nose + noster noster nostra nostra + nostril nostril nostrils nostril + not not notable notabl + notably notabl notary notari + notch notch note note + notebook notebook noted note + notedly notedli notes note + notest notest noteworthy noteworthi + nothing noth nothings noth + notice notic notify notifi + noting note notion notion + notorious notori notoriously notori + notre notr notwithstanding notwithstand + nought nought noun noun + nouns noun nourish nourish + nourished nourish nourisher nourish + nourishes nourish nourisheth nourisheth + nourishing nourish nourishment nourish + nous nou novel novel + novelties novelti novelty novelti + noverbs noverb novi novi + novice novic novices novic + novum novum now now + nowhere nowher noyance noyanc + ns ns nt nt + nubibus nubibu numa numa + numb numb number number + numbered number numbering number + numberless numberless numbers number + numbness numb nun nun + nuncio nuncio nuncle nuncl + nunnery nunneri nuns nun + nuntius nuntiu nuptial nuptial + nurs nur nurse nurs + nursed nurs nurser nurser + nursery nurseri nurses nurs + nurseth nurseth nursh nursh + nursing nurs nurtur nurtur + nurture nurtur nut nut + nuthook nuthook nutmeg nutmeg + nutmegs nutmeg nutriment nutriment + nuts nut nutshell nutshel + ny ny nym nym + nymph nymph nymphs nymph + o o oak oak + oaken oaken oaks oak + oared oar oars oar + oatcake oatcak oaten oaten + oath oath oathable oathabl + oaths oath oats oat + ob ob obduracy obduraci + obdurate obdur obedience obedi + obedient obedi obeisance obeis + oberon oberon obey obei + obeyed obei obeying obei + obeys obei obidicut obidicut + object object objected object + objections object objects object + oblation oblat oblations oblat + obligation oblig obligations oblig + obliged oblig oblique obliqu + oblivion oblivion oblivious oblivi + obloquy obloqui obscene obscen + obscenely obscen obscur obscur + obscure obscur obscured obscur + obscurely obscur obscures obscur + obscuring obscur obscurity obscur + obsequies obsequi obsequious obsequi + obsequiously obsequi observ observ + observance observ observances observ + observancy observ observant observ + observants observ observation observ + observe observ observed observ + observer observ observers observ + observing observ observingly observingli + obsque obsqu obstacle obstacl + obstacles obstacl obstinacy obstinaci + obstinate obstin obstinately obstin + obstruct obstruct obstruction obstruct + obstructions obstruct obtain obtain + obtained obtain obtaining obtain + occasion occas occasions occas + occident occid occidental occident + occulted occult occupat occupat + occupation occup occupations occup + occupied occupi occupies occupi + occupy occupi occurrence occurr + occurrences occurr occurrents occurr + ocean ocean oceans ocean + octavia octavia octavius octaviu + ocular ocular od od + odd odd oddest oddest + oddly oddli odds odd + ode od odes od + odious odiou odoriferous odorifer + odorous odor odour odour + odours odour ods od + oeillades oeillad oes oe + oeuvres oeuvr of of + ofephesus ofephesu off off + offal offal offence offenc + offenceful offenc offences offenc + offend offend offended offend + offendendo offendendo offender offend + offenders offend offendeth offendeth + offending offend offendress offendress + offends offend offense offens + offenseless offenseless offenses offens + offensive offens offer offer + offered offer offering offer + offerings offer offers offer + offert offert offic offic + office offic officed offic + officer offic officers offic + offices offic official offici + officious offici offspring offspr + oft oft often often + oftener often oftentimes oftentim + oh oh oil oil + oils oil oily oili + old old oldcastle oldcastl + olden olden older older + oldest oldest oldness old + olive oliv oliver oliv + olivers oliv olives oliv + olivia olivia olympian olympian + olympus olympu oman oman + omans oman omen omen + ominous omin omission omiss + omit omit omittance omitt + omitted omit omitting omit + omne omn omnes omn + omnipotent omnipot on on + once onc one on + ones on oneyers oney + ongles ongl onion onion + onions onion only onli + onset onset onward onward + onwards onward oo oo + ooze ooz oozes ooz + oozy oozi op op + opal opal ope op + open open opener open + opening open openly openli + openness open opens open + operant oper operate oper + operation oper operations oper + operative oper opes op + oph oph ophelia ophelia + opinion opinion opinions opinion + opportune opportun opportunities opportun + opportunity opportun oppos oppo + oppose oppos opposed oppos + opposeless opposeless opposer oppos + opposers oppos opposes oppos + opposing oppos opposite opposit + opposites opposit opposition opposit + oppositions opposit oppress oppress + oppressed oppress oppresses oppress + oppresseth oppresseth oppressing oppress + oppression oppress oppressor oppressor + opprest opprest opprobriously opprobri + oppugnancy oppugn opulency opul + opulent opul or or + oracle oracl oracles oracl + orange orang oration orat + orator orat orators orat + oratory oratori orb orb + orbed orb orbs orb + orchard orchard orchards orchard + ord ord ordain ordain + ordained ordain ordaining ordain + order order ordered order + ordering order orderless orderless + orderly orderli orders order + ordinance ordin ordinant ordin + ordinaries ordinari ordinary ordinari + ordnance ordnanc ords ord + ordure ordur ore or + organ organ organs organ + orgillous orgil orient orient + orifex orifex origin origin + original origin orisons orison + ork ork orlando orlando + orld orld orleans orlean + ornament ornament ornaments ornament + orodes orod orphan orphan + orphans orphan orpheus orpheu + orsino orsino ort ort + orthography orthographi orts ort + oscorbidulchos oscorbidulcho osier osier + osiers osier osprey osprei + osr osr osric osric + ossa ossa ost ost + ostent ostent ostentare ostentar + ostentation ostent ostents ostent + ostler ostler ostlers ostler + ostrich ostrich osw osw + oswald oswald othello othello + other other othergates otherg + others other otherwhere otherwher + otherwhiles otherwhil otherwise otherwis + otter otter ottoman ottoman + ottomites ottomit oublie oubli + ouches ouch ought ought + oui oui ounce ounc + ounces ounc ouphes ouph + our our ours our + ourself ourself ourselves ourselv + ousel ousel out out + outbids outbid outbrave outbrav + outbraves outbrav outbreak outbreak + outcast outcast outcries outcri + outcry outcri outdar outdar + outdare outdar outdares outdar + outdone outdon outfac outfac + outface outfac outfaced outfac + outfacing outfac outfly outfli + outfrown outfrown outgo outgo + outgoes outgo outgrown outgrown + outjest outjest outlaw outlaw + outlawry outlawri outlaws outlaw + outliv outliv outlive outliv + outlives outliv outliving outliv + outlook outlook outlustres outlustr + outpriz outpriz outrage outrag + outrageous outrag outrages outrag + outran outran outright outright + outroar outroar outrun outrun + outrunning outrun outruns outrun + outscold outscold outscorn outscorn + outsell outsel outsells outsel + outside outsid outsides outsid + outspeaks outspeak outsport outsport + outstare outstar outstay outstai + outstood outstood outstretch outstretch + outstretched outstretch outstrike outstrik + outstrip outstrip outstripped outstrip + outswear outswear outvenoms outvenom + outward outward outwardly outwardli + outwards outward outwear outwear + outweighs outweigh outwent outwent + outworn outworn outworths outworth + oven oven over over + overawe overaw overbear overbear + overblown overblown overboard overboard + overbold overbold overborne overborn + overbulk overbulk overbuys overbui + overcame overcam overcast overcast + overcharg overcharg overcharged overcharg + overcome overcom overcomes overcom + overdone overdon overearnest overearnest + overfar overfar overflow overflow + overflown overflown overglance overgl + overgo overgo overgone overgon + overgorg overgorg overgrown overgrown + overhead overhead overhear overhear + overheard overheard overhold overhold + overjoyed overjoi overkind overkind + overland overland overleather overleath + overlive overl overlook overlook + overlooking overlook overlooks overlook + overmaster overmast overmounting overmount + overmuch overmuch overpass overpass + overpeer overp overpeering overp + overplus overplu overrul overrul + overrun overrun overscutch overscutch + overset overset overshades overshad + overshine overshin overshines overshin + overshot overshot oversights oversight + overspread overspread overstain overstain + overswear overswear overt overt + overta overta overtake overtak + overtaketh overtaketh overthrow overthrow + overthrown overthrown overthrows overthrow + overtook overtook overtopp overtopp + overture overtur overturn overturn + overwatch overwatch overween overween + overweening overween overweigh overweigh + overwhelm overwhelm overwhelming overwhelm + overworn overworn ovid ovid + ovidius ovidiu ow ow + owe ow owed ow + owedst owedst owen owen + owes ow owest owest + oweth oweth owing ow + owl owl owls owl + own own owner owner + owners owner owning own + owns own owy owi + ox ox oxen oxen + oxford oxford oxfordshire oxfordshir + oxlips oxlip oyes oy + oyster oyster p p + pabble pabbl pabylon pabylon + pac pac pace pace + paced pace paces pace + pacified pacifi pacify pacifi + pacing pace pack pack + packet packet packets packet + packhorses packhors packing pack + packings pack packs pack + packthread packthread pacorus pacoru + paction paction pad pad + paddle paddl paddling paddl + paddock paddock padua padua + pagan pagan pagans pagan + page page pageant pageant + pageants pageant pages page + pah pah paid paid + pail pail pailfuls pail + pails pail pain pain + pained pain painful pain + painfully painfulli pains pain + paint paint painted paint + painter painter painting paint + paintings paint paints paint + pair pair paired pair + pairs pair pajock pajock + pal pal palabras palabra + palace palac palaces palac + palamedes palamed palate palat + palates palat palatine palatin + palating palat pale pale + paled pale paleness pale + paler paler pales pale + palestine palestin palfrey palfrei + palfreys palfrei palisadoes palisado + pall pall pallabris pallabri + pallas palla pallets pallet + palm palm palmer palmer + palmers palmer palms palm + palmy palmi palpable palpabl + palsied palsi palsies palsi + palsy palsi palt palt + palter palter paltry paltri + paly pali pamp pamp + pamper pamper pamphlets pamphlet + pan pan pancackes pancack + pancake pancak pancakes pancak + pandar pandar pandars pandar + pandarus pandaru pander pander + panderly panderli panders pander + pandulph pandulph panel panel + pang pang panging pang + pangs pang pannier pannier + pannonians pannonian pansa pansa + pansies pansi pant pant + pantaloon pantaloon panted pant + pantheon pantheon panther panther + panthino panthino panting pant + pantingly pantingli pantler pantler + pantry pantri pants pant + pap pap papal papal + paper paper papers paper + paphlagonia paphlagonia paphos papho + papist papist paps pap + par par parable parabl + paracelsus paracelsu paradise paradis + paradox paradox paradoxes paradox + paragon paragon paragons paragon + parallel parallel parallels parallel + paramour paramour paramours paramour + parapets parapet paraquito paraquito + parasite parasit parasites parasit + parca parca parcel parcel + parcell parcel parcels parcel + parch parch parched parch + parching parch parchment parchment + pard pard pardon pardon + pardona pardona pardoned pardon + pardoner pardon pardoning pardon + pardonne pardonn pardonner pardonn + pardonnez pardonnez pardons pardon + pare pare pared pare + parel parel parent parent + parentage parentag parents parent + parfect parfect paring pare + parings pare paris pari + parish parish parishioners parishion + parisians parisian paritors paritor + park park parks park + parle parl parler parler + parles parl parley parlei + parlez parlez parliament parliament + parlors parlor parlour parlour + parlous parlou parmacity parmac + parolles parol parricide parricid + parricides parricid parrot parrot + parrots parrot parsley parslei + parson parson part part + partake partak partaken partaken + partaker partak partakers partak + parted part parthia parthia + parthian parthian parthians parthian + parti parti partial partial + partialize partial partially partial + participate particip participation particip + particle particl particular particular + particularities particular particularize particular + particularly particularli particulars particular + parties parti parting part + partisan partisan partisans partisan + partition partit partizan partizan + partlet partlet partly partli + partner partner partners partner + partridge partridg parts part + party parti pas pa + pash pash pashed pash + pashful pash pass pass + passable passabl passado passado + passage passag passages passag + passant passant passed pass + passenger passeng passengers passeng + passes pass passeth passeth + passing pass passio passio + passion passion passionate passion + passioning passion passions passion + passive passiv passport passport + passy passi past past + paste past pasterns pastern + pasties pasti pastime pastim + pastimes pastim pastoral pastor + pastorals pastor pastors pastor + pastry pastri pasture pastur + pastures pastur pasty pasti + pat pat patay patai + patch patch patchery patcheri + patches patch pate pate + pated pate patent patent + patents patent paternal patern + pates pate path path + pathetical pathet paths path + pathway pathwai pathways pathwai + patience patienc patient patient + patiently patient patients patient + patines patin patrician patrician + patricians patrician patrick patrick + patrimony patrimoni patroclus patroclu + patron patron patronage patronag + patroness patro patrons patron + patrum patrum patter patter + pattern pattern patterns pattern + pattle pattl pauca pauca + paucas pauca paul paul + paulina paulina paunch paunch + paunches paunch pause paus + pauser pauser pauses paus + pausingly pausingli pauvres pauvr + pav pav paved pave + pavement pavement pavilion pavilion + pavilions pavilion pavin pavin + paw paw pawn pawn + pawns pawn paws paw + pax pax pay pai + payest payest paying pai + payment payment payments payment + pays pai paysan paysan + paysans paysan pe pe + peace peac peaceable peaceabl + peaceably peaceabl peaceful peac + peacemakers peacemak peaces peac + peach peach peaches peach + peacock peacock peacocks peacock + peak peak peaking peak + peal peal peals peal + pear pear peard peard + pearl pearl pearls pearl + pears pear peas pea + peasant peasant peasantry peasantri + peasants peasant peascod peascod + pease peas peaseblossom peaseblossom + peat peat peaten peaten + peating peat pebble pebbl + pebbled pebbl pebbles pebbl + peck peck pecks peck + peculiar peculiar pecus pecu + pedant pedant pedantical pedant + pedascule pedascul pede pede + pedestal pedest pedigree pedigre + pedlar pedlar pedlars pedlar + pedro pedro peds ped + peel peel peep peep + peeped peep peeping peep + peeps peep peer peer + peereth peereth peering peer + peerless peerless peers peer + peesel peesel peevish peevish + peevishly peevishli peflur peflur + peg peg pegasus pegasu + pegs peg peise peis + peised peis peize peiz + pelf pelf pelican pelican + pelion pelion pell pell + pella pella pelleted pellet + peloponnesus peloponnesu pelt pelt + pelting pelt pembroke pembrok + pen pen penalties penalti + penalty penalti penance penanc + pence penc pencil pencil + pencill pencil pencils pencil + pendant pendant pendent pendent + pendragon pendragon pendulous pendul + penelope penelop penetrable penetr + penetrate penetr penetrative penetr + penitence penit penitent penit + penitential penitenti penitently penit + penitents penit penker penker + penknife penknif penn penn + penned pen penning pen + pennons pennon penny penni + pennyworth pennyworth pennyworths pennyworth + pens pen pense pens + pension pension pensioners pension + pensive pensiv pensived pensiv + pensively pensiv pent pent + pentecost pentecost penthesilea penthesilea + penthouse penthous penurious penuri + penury penuri peopl peopl + people peopl peopled peopl + peoples peopl pepin pepin + pepper pepper peppercorn peppercorn + peppered pepper per per + peradventure peradventur peradventures peradventur + perceiv perceiv perceive perceiv + perceived perceiv perceives perceiv + perceiveth perceiveth perch perch + perchance perchanc percies perci + percussion percuss percy perci + perdie perdi perdita perdita + perdition perdit perdonato perdonato + perdu perdu perdurable perdur + perdurably perdur perdy perdi + pere pere peregrinate peregrin + peremptorily peremptorili peremptory peremptori + perfect perfect perfected perfect + perfecter perfect perfectest perfectest + perfection perfect perfections perfect + perfectly perfectli perfectness perfect + perfidious perfidi perfidiously perfidi + perforce perforc perform perform + performance perform performances perform + performed perform performer perform + performers perform performing perform + performs perform perfum perfum + perfume perfum perfumed perfum + perfumer perfum perfumes perfum + perge perg perhaps perhap + periapts periapt perigort perigort + perigouna perigouna peril peril + perilous peril perils peril + period period periods period + perish perish perished perish + perishest perishest perisheth perisheth + perishing perish periwig periwig + perjur perjur perjure perjur + perjured perjur perjuries perjuri + perjury perjuri perk perk + perkes perk permafoy permafoi + permanent perman permission permiss + permissive permiss permit permit + permitted permit pernicious pernici + perniciously pernici peroration peror + perpend perpend perpendicular perpendicular + perpendicularly perpendicularli perpetual perpetu + perpetually perpetu perpetuity perpetu + perplex perplex perplexed perplex + perplexity perplex pers per + persecuted persecut persecutions persecut + persecutor persecutor perseus perseu + persever persev perseverance persever + persevers persev persia persia + persian persian persist persist + persisted persist persistency persist + persistive persist persists persist + person person personae persona + personage personag personages personag + personal person personally person + personate person personated person + personates person personating person + persons person perspective perspect + perspectively perspect perspectives perspect + perspicuous perspicu persuade persuad + persuaded persuad persuades persuad + persuading persuad persuasion persuas + persuasions persuas pert pert + pertain pertain pertaining pertain + pertains pertain pertaunt pertaunt + pertinent pertin pertly pertli + perturb perturb perturbation perturb + perturbations perturb perturbed perturb + perus peru perusal perus + peruse perus perused perus + perusing perus perverse pervers + perversely pervers perverseness pervers + pervert pervert perverted pervert + peseech peseech pest pest + pester pester pestiferous pestifer + pestilence pestil pestilent pestil + pet pet petar petar + peter peter petit petit + petition petit petitionary petitionari + petitioner petition petitioners petition + petitions petit peto peto + petrarch petrarch petruchio petruchio + petter petter petticoat petticoat + petticoats petticoat pettiness petti + pettish pettish pettitoes pettito + petty petti peu peu + pew pew pewter pewter + pewterer pewter phaethon phaethon + phaeton phaeton phantasime phantasim + phantasimes phantasim phantasma phantasma + pharamond pharamond pharaoh pharaoh + pharsalia pharsalia pheasant pheasant + pheazar pheazar phebe phebe + phebes phebe pheebus pheebu + pheeze pheez phibbus phibbu + philadelphos philadelpho philario philario + philarmonus philarmonu philemon philemon + philip philip philippan philippan + philippe philipp philippi philippi + phillida phillida philo philo + philomel philomel philomela philomela + philosopher philosoph philosophers philosoph + philosophical philosoph philosophy philosophi + philostrate philostr philotus philotu + phlegmatic phlegmat phoebe phoeb + phoebus phoebu phoenicia phoenicia + phoenicians phoenician phoenix phoenix + phorbus phorbu photinus photinu + phrase phrase phraseless phraseless + phrases phrase phrygia phrygia + phrygian phrygian phrynia phrynia + physic physic physical physic + physician physician physicians physician + physics physic pia pia + pibble pibbl pible pibl + picardy picardi pick pick + pickaxe pickax pickaxes pickax + pickbone pickbon picked pick + pickers picker picking pick + pickle pickl picklock picklock + pickpurse pickpurs picks pick + pickt pickt pickthanks pickthank + pictur pictur picture pictur + pictured pictur pictures pictur + pid pid pie pie + piec piec piece piec + pieces piec piecing piec + pied pi piedness pied + pier pier pierc pierc + pierce pierc pierced pierc + pierces pierc pierceth pierceth + piercing pierc piercy pierci + piers pier pies pi + piety pieti pig pig + pigeon pigeon pigeons pigeon + pight pight pigmy pigmi + pigrogromitus pigrogromitu pike pike + pikes pike pil pil + pilate pilat pilates pilat + pilchers pilcher pile pile + piles pile pilf pilf + pilfering pilfer pilgrim pilgrim + pilgrimage pilgrimag pilgrims pilgrim + pill pill pillage pillag + pillagers pillag pillar pillar + pillars pillar pillicock pillicock + pillory pillori pillow pillow + pillows pillow pills pill + pilot pilot pilots pilot + pimpernell pimpernel pin pin + pinch pinch pinched pinch + pinches pinch pinching pinch + pindarus pindaru pine pine + pined pine pines pine + pinfold pinfold pining pine + pinion pinion pink pink + pinn pinn pinnace pinnac + pins pin pinse pins + pint pint pintpot pintpot + pioned pion pioneers pioneer + pioner pioner pioners pioner + pious piou pip pip + pipe pipe piper piper + pipers piper pipes pipe + piping pipe pippin pippin + pippins pippin pirate pirat + pirates pirat pisa pisa + pisanio pisanio pish pish + pismires pismir piss piss + pissing piss pistol pistol + pistols pistol pit pit + pitch pitch pitched pitch + pitcher pitcher pitchers pitcher + pitchy pitchi piteous piteou + piteously piteous pitfall pitfal + pith pith pithless pithless + pithy pithi pitie piti + pitied piti pities piti + pitiful piti pitifully pitifulli + pitiless pitiless pits pit + pittance pittanc pittie pitti + pittikins pittikin pity piti + pitying piti pius piu + plac plac place place + placed place placentio placentio + places place placeth placeth + placid placid placing place + plack plack placket placket + plackets placket plagu plagu + plague plagu plagued plagu + plagues plagu plaguing plagu + plaguy plagui plain plain + plainer plainer plainest plainest + plaining plain plainings plain + plainly plainli plainness plain + plains plain plainsong plainsong + plaintful plaint plaintiff plaintiff + plaintiffs plaintiff plaints plaint + planched planch planet planet + planetary planetari planets planet + planks plank plant plant + plantage plantag plantagenet plantagenet + plantagenets plantagenet plantain plantain + plantation plantat planted plant + planteth planteth plants plant + plash plash plashy plashi + plast plast plaster plaster + plasterer plaster plat plat + plate plate plated plate + plates plate platform platform + platforms platform plats plat + platted plat plausible plausibl + plausive plausiv plautus plautu + play plai played plai + player player players player + playeth playeth playfellow playfellow + playfellows playfellow playhouse playhous + playing plai plays plai + plea plea pleach pleach + pleached pleach plead plead + pleaded plead pleader pleader + pleaders pleader pleading plead + pleads plead pleas plea + pleasance pleasanc pleasant pleasant + pleasantly pleasantli please pleas + pleased pleas pleaser pleaser + pleasers pleaser pleases pleas + pleasest pleasest pleaseth pleaseth + pleasing pleas pleasure pleasur + pleasures pleasur plebeians plebeian + plebeii plebeii plebs pleb + pledge pledg pledges pledg + pleines plein plenitude plenitud + plenteous plenteou plenteously plenteous + plenties plenti plentiful plenti + plentifully plentifulli plenty plenti + pless pless plessed pless + plessing pless pliant pliant + plied pli plies pli + plight plight plighted plight + plighter plighter plod plod + plodded plod plodders plodder + plodding plod plods plod + plood plood ploody ploodi + plot plot plots plot + plotted plot plotter plotter + plough plough ploughed plough + ploughman ploughman ploughmen ploughmen + plow plow plows plow + pluck pluck plucked pluck + plucker plucker plucking pluck + plucks pluck plue plue + plum plum plume plume + plumed plume plumes plume + plummet plummet plump plump + plumpy plumpi plums plum + plung plung plunge plung + plunged plung plural plural + plurisy plurisi plus plu + pluto pluto plutus plutu + ply ply po po + pocket pocket pocketing pocket + pockets pocket pocky pocki + pody podi poem poem + poesy poesi poet poet + poetical poetic poetry poetri + poets poet poictiers poictier + poinards poinard poins poin + point point pointblank pointblank + pointed point pointing point + points point pois poi + poise pois poising pois + poison poison poisoned poison + poisoner poison poisoning poison + poisonous poison poisons poison + poke poke poking poke + pol pol polack polack + polacks polack poland poland + pold pold pole pole + poleaxe poleax polecat polecat + polecats polecat polemon polemon + poles pole poli poli + policies polici policy polici + polish polish polished polish + politic polit politician politician + politicians politician politicly politicli + polixenes polixen poll poll + polluted pollut pollution pollut + polonius poloniu poltroons poltroon + polusion polus polydamus polydamu + polydore polydor polyxena polyxena + pomander pomand pomegranate pomegran + pomewater pomewat pomfret pomfret + pomgarnet pomgarnet pommel pommel + pomp pomp pompeius pompeiu + pompey pompei pompion pompion + pompous pompou pomps pomp + pond pond ponder ponder + ponderous ponder ponds pond + poniard poniard poniards poniard + pont pont pontic pontic + pontifical pontif ponton ponton + pooh pooh pool pool + poole pool poop poop + poor poor poorer poorer + poorest poorest poorly poorli + pop pop pope pope + popedom popedom popilius popiliu + popingay popingai popish popish + popp popp poppy poppi + pops pop popular popular + popularity popular populous popul + porch porch porches porch + pore pore poring pore + pork pork porn porn + porpentine porpentin porridge porridg + porringer porring port port + portable portabl portage portag + portal portal portance portanc + portcullis portculli portend portend + portends portend portent portent + portentous portent portents portent + porter porter porters porter + portia portia portion portion + portly portli portotartarossa portotartarossa + portrait portrait portraiture portraitur + ports port portugal portug + pose pose posied posi + posies posi position posit + positive posit positively posit + posse poss possess possess + possessed possess possesses possess + possesseth possesseth possessing possess + possession possess possessions possess + possessor possessor posset posset + possets posset possibilities possibl + possibility possibl possible possibl + possibly possibl possitable possit + post post poste post + posted post posterior posterior + posteriors posterior posterity poster + postern postern posterns postern + posters poster posthorse posthors + posthorses posthors posthumus posthumu + posting post postmaster postmast + posts post postscript postscript + posture postur postures postur + posy posi pot pot + potable potabl potations potat + potato potato potatoes potato + potch potch potency potenc + potent potent potentates potent + potential potenti potently potent + potents potent pothecary pothecari + pother pother potion potion + potions potion potpan potpan + pots pot potter potter + potting pot pottle pottl + pouch pouch poulter poulter + poultice poultic poultney poultnei + pouncet pouncet pound pound + pounds pound pour pour + pourest pourest pouring pour + pourquoi pourquoi pours pour + pout pout poverty poverti + pow pow powd powd + powder powder power power + powerful power powerfully powerfulli + powerless powerless powers power + pox pox poys poi + poysam poysam prabbles prabbl + practic practic practice practic + practiced practic practicer practic + practices practic practicing practic + practis practi practisants practis + practise practis practiser practis + practisers practis practises practis + practising practis praeclarissimus praeclarissimu + praemunire praemunir praetor praetor + praetors praetor pragging prag + prague pragu prain prain + prains prain prais prai + praise prais praised prais + praises prais praisest praisest + praiseworthy praiseworthi praising prais + prancing pranc prank prank + pranks prank prat prat + prate prate prated prate + prater prater prating prate + prattle prattl prattler prattler + prattling prattl prave prave + prawls prawl prawns prawn + pray prai prayer prayer + prayers prayer praying prai + prays prai pre pre + preach preach preached preach + preachers preacher preaches preach + preaching preach preachment preachment + pread pread preambulate preambul + precedence preced precedent preced + preceding preced precept precept + preceptial precepti precepts precept + precinct precinct precious preciou + preciously precious precipice precipic + precipitating precipit precipitation precipit + precise precis precisely precis + preciseness precis precisian precisian + precor precor precurse precurs + precursors precursor predeceased predeceas + predecessor predecessor predecessors predecessor + predestinate predestin predicament predica + predict predict prediction predict + predictions predict predominance predomin + predominant predomin predominate predomin + preeches preech preeminence preemin + preface prefac prefer prefer + preferment prefer preferments prefer + preferr preferr preferreth preferreth + preferring prefer prefers prefer + prefiguring prefigur prefix prefix + prefixed prefix preformed preform + pregnancy pregnanc pregnant pregnant + pregnantly pregnantli prejudicates prejud + prejudice prejudic prejudicial prejudici + prelate prelat premeditated premedit + premeditation premedit premised premis + premises premis prenez prenez + prenominate prenomin prentice prentic + prentices prentic preordinance preordin + prepar prepar preparation prepar + preparations prepar prepare prepar + prepared prepar preparedly preparedli + prepares prepar preparing prepar + prepost prepost preposterous preposter + preposterously preposter prerogatifes prerogatif + prerogative prerog prerogatived prerogativ + presage presag presagers presag + presages presag presageth presageth + presaging presag prescience prescienc + prescribe prescrib prescript prescript + prescription prescript prescriptions prescript + prescripts prescript presence presenc + presences presenc present present + presentation present presented present + presenter present presenters present + presenteth presenteth presenting present + presently present presentment present + presents present preserv preserv + preservation preserv preservative preserv + preserve preserv preserved preserv + preserver preserv preservers preserv + preserving preserv president presid + press press pressed press + presser presser presses press + pressing press pressure pressur + pressures pressur prest prest + prester prester presume presum + presumes presum presuming presum + presumption presumpt presumptuous presumptu + presuppos presuppo pret pret + pretence pretenc pretences pretenc + pretend pretend pretended pretend + pretending pretend pretense pretens + pretext pretext pretia pretia + prettier prettier prettiest prettiest + prettily prettili prettiness pretti + pretty pretti prevail prevail + prevailed prevail prevaileth prevaileth + prevailing prevail prevailment prevail + prevails prevail prevent prevent + prevented prevent prevention prevent + preventions prevent prevents prevent + prey prei preyful prey + preys prei priam priam + priami priami priamus priamu + pribbles pribbl price price + prick prick pricked prick + pricket pricket pricking prick + pricks prick pricksong pricksong + pride pride prides pride + pridge pridg prie prie + pried pri prief prief + pries pri priest priest + priesthood priesthood priests priest + prig prig primal primal + prime prime primer primer + primero primero primest primest + primitive primit primo primo + primogenity primogen primrose primros + primroses primros primy primi + prince princ princely princ + princes princ princess princess + principal princip principalities princip + principality princip principle principl + principles principl princox princox + prings pring print print + printed print printing print + printless printless prints print + prioress prioress priories priori + priority prioriti priory priori + priscian priscian prison prison + prisoner prison prisoners prison + prisonment prison prisonnier prisonni + prisons prison pristine pristin + prithe prith prithee prithe + privacy privaci private privat + privately privat privates privat + privilage privilag privileg privileg + privilege privileg privileged privileg + privileges privileg privilegio privilegio + privily privili privity priviti + privy privi priz priz + prize prize prized prize + prizer prizer prizes prize + prizest prizest prizing prize + pro pro probable probabl + probal probal probation probat + proceed proce proceeded proceed + proceeders proceed proceeding proceed + proceedings proceed proceeds proce + process process procession process + proclaim proclaim proclaimed proclaim + proclaimeth proclaimeth proclaims proclaim + proclamation proclam proclamations proclam + proconsul proconsul procrastinate procrastin + procreant procreant procreants procreant + procreation procreat procrus procru + proculeius proculeiu procur procur + procurator procur procure procur + procured procur procures procur + procuring procur prodigal prodig + prodigality prodig prodigally prodig + prodigals prodig prodigies prodigi + prodigious prodigi prodigiously prodigi + prodigy prodigi proditor proditor + produc produc produce produc + produced produc produces produc + producing produc proface profac + profan profan profanation profan + profane profan profaned profan + profanely profan profaneness profan + profaners profan profaning profan + profess profess professed profess + professes profess profession profess + professions profess professors professor + proffer proffer proffered proffer + profferer proffer proffers proffer + proficient profici profit profit + profitable profit profitably profit + profited profit profiting profit + profitless profitless profits profit + profound profound profoundest profoundest + profoundly profoundli progenitors progenitor + progeny progeni progne progn + prognosticate prognost prognostication prognost + progress progress progression progress + prohibit prohibit prohibition prohibit + project project projection project + projects project prolixious prolixi + prolixity prolix prologue prologu + prologues prologu prolong prolong + prolongs prolong promethean promethean + prometheus prometheu promis promi + promise promis promised promis + promises promis promiseth promiseth + promising promis promontory promontori + promotion promot promotions promot + prompt prompt prompted prompt + promptement promptement prompter prompter + prompting prompt prompts prompt + prompture promptur promulgate promulg + prone prone prononcer prononc + prononcez prononcez pronoun pronoun + pronounc pronounc pronounce pronounc + pronounced pronounc pronouncing pronounc + pronouns pronoun proof proof + proofs proof prop prop + propagate propag propagation propag + propend propend propension propens + proper proper properer proper + properly properli propertied properti + properties properti property properti + prophecies propheci prophecy propheci + prophesied prophesi prophesier prophesi + prophesy prophesi prophesying prophesi + prophet prophet prophetess prophetess + prophetic prophet prophetically prophet + prophets prophet propinquity propinqu + propontic propont proportion proport + proportionable proportion proportions proport + propos propo propose propos + proposed propos proposer propos + proposes propos proposing propos + proposition proposit propositions proposit + propounded propound propp propp + propre propr propriety proprieti + props prop propugnation propugn + prorogue prorogu prorogued prorogu + proscription proscript proscriptions proscript + prose prose prosecute prosecut + prosecution prosecut proselytes proselyt + proserpina proserpina prosp prosp + prospect prospect prosper prosper + prosperity prosper prospero prospero + prosperous prosper prosperously prosper + prospers prosper prostitute prostitut + prostrate prostrat protect protect + protected protect protection protect + protector protector protectors protector + protectorship protectorship protectress protectress + protects protect protest protest + protestation protest protestations protest + protested protest protester protest + protesting protest protests protest + proteus proteu protheus protheu + protract protract protractive protract + proud proud prouder prouder + proudest proudest proudlier proudlier + proudly proudli prouds proud + prov prov provand provand + prove prove proved prove + provender provend proverb proverb + proverbs proverb proves prove + proveth proveth provide provid + provided provid providence provid + provident provid providently provid + provider provid provides provid + province provinc provinces provinc + provincial provinci proving prove + provision provis proviso proviso + provocation provoc provok provok + provoke provok provoked provok + provoker provok provokes provok + provoketh provoketh provoking provok + provost provost prowess prowess + prudence prudenc prudent prudent + prun prun prune prune + prunes prune pruning prune + pry pry prying pry + psalm psalm psalmist psalmist + psalms psalm psalteries psalteri + ptolemies ptolemi ptolemy ptolemi + public public publican publican + publication public publicly publicli + publicola publicola publish publish + published publish publisher publish + publishing publish publius publiu + pucelle pucel puck puck + pudder pudder pudding pud + puddings pud puddle puddl + puddled puddl pudency pudenc + pueritia pueritia puff puff + puffing puf puffs puff + pugging pug puis pui + puissance puissanc puissant puissant + puke puke puking puke + pulcher pulcher puling pule + pull pull puller puller + pullet pullet pulling pull + pulls pull pulpit pulpit + pulpiter pulpit pulpits pulpit + pulse puls pulsidge pulsidg + pump pump pumpion pumpion + pumps pump pun pun + punched punch punish punish + punished punish punishes punish + punishment punish punishments punish + punk punk punto punto + puny puni pupil pupil + pupils pupil puppet puppet + puppets puppet puppies puppi + puppy puppi pur pur + purblind purblind purchas purcha + purchase purchas purchased purchas + purchases purchas purchaseth purchaseth + purchasing purchas pure pure + purely pure purer purer + purest purest purg purg + purgation purgat purgative purg + purgatory purgatori purge purg + purged purg purgers purger + purging purg purifies purifi + purifying purifi puritan puritan + purity puriti purlieus purlieu + purple purpl purpled purpl + purples purpl purport purport + purpos purpo purpose purpos + purposed purpos purposely purpos + purposes purpos purposeth purposeth + purposing purpos purr purr + purs pur purse purs + pursents pursent purses purs + pursu pursu pursue pursu + pursued pursu pursuers pursuer + pursues pursu pursuest pursuest + pursueth pursueth pursuing pursu + pursuit pursuit pursuivant pursuiv + pursuivants pursuiv pursy pursi + purus puru purveyor purveyor + push push pushes push + pusillanimity pusillanim put put + putrefy putrefi putrified putrifi + puts put putter putter + putting put puttock puttock + puzzel puzzel puzzle puzzl + puzzled puzzl puzzles puzzl + py py pygmalion pygmalion + pygmies pygmi pygmy pygmi + pyramid pyramid pyramides pyramid + pyramids pyramid pyramis pyrami + pyramises pyramis pyramus pyramu + pyrenean pyrenean pyrrhus pyrrhu + pythagoras pythagora qu qu + quadrangle quadrangl quae quae + quaff quaff quaffing quaf + quagmire quagmir quail quail + quailing quail quails quail + quaint quaint quaintly quaintli + quak quak quake quak + quakes quak qualification qualif + qualified qualifi qualifies qualifi + qualify qualifi qualifying qualifi + qualite qualit qualities qualiti + quality qualiti qualm qualm + qualmish qualmish quam quam + quand quand quando quando + quantities quantiti quantity quantiti + quare quar quarrel quarrel + quarrell quarrel quarreller quarrel + quarrelling quarrel quarrelous quarrel + quarrels quarrel quarrelsome quarrelsom + quarries quarri quarry quarri + quart quart quarter quarter + quartered quarter quartering quarter + quarters quarter quarts quart + quasi quasi quat quat + quatch quatch quay quai + que que quean quean + queas quea queasiness queasi + queasy queasi queen queen + queens queen quell quell + queller queller quench quench + quenched quench quenching quench + quenchless quenchless quern quern + quest quest questant questant + question question questionable question + questioned question questioning question + questionless questionless questions question + questrists questrist quests quest + queubus queubu qui qui + quick quick quicken quicken + quickens quicken quicker quicker + quicklier quicklier quickly quickli + quickness quick quicksand quicksand + quicksands quicksand quicksilverr quicksilverr + quid quid quiddities quidditi + quiddits quiddit quier quier + quiet quiet quieter quieter + quietly quietli quietness quiet + quietus quietu quill quill + quillets quillet quills quill + quilt quilt quinapalus quinapalu + quince quinc quinces quinc + quintain quintain quintessence quintess + quintus quintu quip quip + quips quip quire quir + quiring quir quirk quirk + quirks quirk quis qui + quit quit quite quit + quits quit quittance quittanc + quitted quit quitting quit + quiver quiver quivering quiver + quivers quiver quo quo + quod quod quoifs quoif + quoint quoint quoit quoit + quoits quoit quondam quondam + quoniam quoniam quote quot + quoted quot quotes quot + quoth quoth quotidian quotidian + r r rabbit rabbit + rabble rabbl rabblement rabblement + race race rack rack + rackers racker racket racket + rackets racket racking rack + racks rack radiance radianc + radiant radiant radish radish + rafe rafe raft raft + rag rag rage rage + rages rage rageth rageth + ragg ragg ragged rag + raggedness ragged raging rage + ragozine ragozin rags rag + rah rah rail rail + railed rail railer railer + railest railest raileth raileth + railing rail rails rail + raiment raiment rain rain + rainbow rainbow raineth raineth + raining rain rainold rainold + rains rain rainy raini + rais rai raise rais + raised rais raises rais + raising rais raisins raisin + rak rak rake rake + rakers raker rakes rake + ral ral rald rald + ralph ralph ram ram + rambures rambur ramm ramm + rampallian rampallian rampant rampant + ramping ramp rampir rampir + ramps ramp rams ram + ramsey ramsei ramston ramston + ran ran rance ranc + rancorous rancor rancors rancor + rancour rancour random random + rang rang range rang + ranged rang rangers ranger + ranges rang ranging rang + rank rank ranker ranker + rankest rankest ranking rank + rankle rankl rankly rankli + rankness rank ranks rank + ransack ransack ransacking ransack + ransom ransom ransomed ransom + ransoming ransom ransomless ransomless + ransoms ransom rant rant + ranting rant rap rap + rape rape rapes rape + rapier rapier rapiers rapier + rapine rapin raps rap + rapt rapt rapture raptur + raptures raptur rar rar + rare rare rarely rare + rareness rare rarer rarer + rarest rarest rarities rariti + rarity rariti rascal rascal + rascalliest rascalliest rascally rascal + rascals rascal rased rase + rash rash rasher rasher + rashly rashli rashness rash + rat rat ratcatcher ratcatch + ratcliff ratcliff rate rate + rated rate rately rate + rates rate rather rather + ratherest ratherest ratified ratifi + ratifiers ratifi ratify ratifi + rating rate rational ration + ratolorum ratolorum rats rat + ratsbane ratsban rattle rattl + rattles rattl rattling rattl + rature ratur raught raught + rav rav rave rave + ravel ravel raven raven + ravening raven ravenous raven + ravens raven ravenspurgh ravenspurgh + raves rave ravin ravin + raving rave ravish ravish + ravished ravish ravisher ravish + ravishing ravish ravishments ravish + raw raw rawer rawer + rawly rawli rawness raw + ray rai rayed rai + rays rai raz raz + raze raze razed raze + razes raze razeth razeth + razing raze razor razor + razorable razor razors razor + razure razur re re + reach reach reaches reach + reacheth reacheth reaching reach + read read reader reader + readiest readiest readily readili + readiness readi reading read + readins readin reads read + ready readi real real + really realli realm realm + realms realm reap reap + reapers reaper reaping reap + reaps reap rear rear + rears rear rearward rearward + reason reason reasonable reason + reasonably reason reasoned reason + reasoning reason reasonless reasonless + reasons reason reave reav + rebate rebat rebato rebato + rebeck rebeck rebel rebel + rebell rebel rebelling rebel + rebellion rebellion rebellious rebelli + rebels rebel rebound rebound + rebuk rebuk rebuke rebuk + rebukeable rebuk rebuked rebuk + rebukes rebuk rebus rebu + recall recal recant recant + recantation recant recanter recant + recanting recant receipt receipt + receipts receipt receiv receiv + receive receiv received receiv + receiver receiv receives receiv + receivest receivest receiveth receiveth + receiving receiv receptacle receptacl + rechate rechat reciprocal reciproc + reciprocally reciproc recite recit + recited recit reciterai reciterai + reck reck recking reck + reckless reckless reckon reckon + reckoned reckon reckoning reckon + reckonings reckon recks reck + reclaim reclaim reclaims reclaim + reclusive reclus recognizance recogniz + recognizances recogniz recoil recoil + recoiling recoil recollected recollect + recomforted recomfort recomforture recomfortur + recommend recommend recommended recommend + recommends recommend recompens recompen + recompense recompens reconcil reconcil + reconcile reconcil reconciled reconcil + reconcilement reconcil reconciler reconcil + reconciles reconcil reconciliation reconcili + record record recordation record + recorded record recorder record + recorders record records record + recount recount recounted recount + recounting recount recountments recount + recounts recount recourse recours + recov recov recover recov + recoverable recover recovered recov + recoveries recoveri recovers recov + recovery recoveri recreant recreant + recreants recreant recreate recreat + recreation recreat rectify rectifi + rector rector rectorship rectorship + recure recur recured recur + red red redbreast redbreast + redder redder reddest reddest + rede rede redeem redeem + redeemed redeem redeemer redeem + redeeming redeem redeems redeem + redeliver redeliv redemption redempt + redime redim redness red + redoubled redoubl redoubted redoubt + redound redound redress redress + redressed redress redresses redress + reduce reduc reechy reechi + reed reed reeds reed + reek reek reeking reek + reeks reek reeky reeki + reel reel reeleth reeleth + reeling reel reels reel + refell refel refer refer + reference refer referr referr + referred refer refigured refigur + refin refin refined refin + reflect reflect reflecting reflect + reflection reflect reflex reflex + reform reform reformation reform + reformed reform refractory refractori + refrain refrain refresh refresh + refreshing refresh reft reft + refts reft refuge refug + refus refu refusal refus + refuse refus refused refus + refusest refusest refusing refus + reg reg regal regal + regalia regalia regan regan + regard regard regardance regard + regarded regard regardfully regardfulli + regarding regard regards regard + regenerate regener regent regent + regentship regentship regia regia + regiment regiment regiments regiment + regina regina region region + regions region regist regist + register regist registers regist + regreet regreet regreets regreet + regress regress reguerdon reguerdon + regular regular rehears rehear + rehearsal rehears rehearse rehears + reign reign reigned reign + reignier reignier reigning reign + reigns reign rein rein + reinforc reinforc reinforce reinforc + reinforcement reinforc reins rein + reiterate reiter reject reject + rejected reject rejoic rejoic + rejoice rejoic rejoices rejoic + rejoiceth rejoiceth rejoicing rejoic + rejoicingly rejoicingli rejoindure rejoindur + rejourn rejourn rel rel + relapse relaps relate relat + relates relat relation relat + relations relat relative rel + releas relea release releas + released releas releasing releas + relent relent relenting relent + relents relent reliances relianc + relics relic relief relief + reliev reliev relieve reliev + relieved reliev relieves reliev + relieving reliev religion religion + religions religion religious religi + religiously religi relinquish relinquish + reliques reliqu reliquit reliquit + relish relish relume relum + rely reli relying reli + remain remain remainder remaind + remainders remaind remained remain + remaineth remaineth remaining remain + remains remain remark remark + remarkable remark remediate remedi + remedied remedi remedies remedi + remedy remedi rememb rememb + remember rememb remembered rememb + remembers rememb remembrance remembr + remembrancer remembranc remembrances remembr + remercimens remercimen remiss remiss + remission remiss remissness remiss + remit remit remnant remnant + remnants remnant remonstrance remonstr + remorse remors remorseful remors + remorseless remorseless remote remot + remotion remot remov remov + remove remov removed remov + removedness removed remover remov + removes remov removing remov + remunerate remuner remuneration remuner + rence renc rend rend + render render rendered render + renders render rendezvous rendezv + renegado renegado renege reneg + reneges reneg renew renew + renewed renew renewest renewest + renounce renounc renouncement renounc + renouncing renounc renowmed renowm + renown renown renowned renown + rent rent rents rent + repaid repaid repair repair + repaired repair repairing repair + repairs repair repass repass + repast repast repasture repastur + repay repai repaying repai + repays repai repeal repeal + repealing repeal repeals repeal + repeat repeat repeated repeat + repeating repeat repeats repeat + repel repel repent repent + repentance repent repentant repent + repented repent repenting repent + repents repent repetition repetit + repetitions repetit repin repin + repine repin repining repin + replant replant replenish replenish + replenished replenish replete replet + replication replic replied repli + replies repli repliest repliest + reply repli replying repli + report report reported report + reporter report reportest reportest + reporting report reportingly reportingli + reports report reposal repos + repose repos reposeth reposeth + reposing repos repossess repossess + reprehend reprehend reprehended reprehend + reprehending reprehend represent repres + representing repres reprieve repriev + reprieves repriev reprisal repris + reproach reproach reproaches reproach + reproachful reproach reproachfully reproachfulli + reprobate reprob reprobation reprob + reproof reproof reprov reprov + reprove reprov reproveable reprov + reproves reprov reproving reprov + repugn repugn repugnancy repugn + repugnant repugn repulse repuls + repulsed repuls repurchas repurcha + repured repur reputation reput + repute reput reputed reput + reputeless reputeless reputes reput + reputing reput request request + requested request requesting request + requests request requiem requiem + requir requir require requir + required requir requires requir + requireth requireth requiring requir + requisite requisit requisites requisit + requit requit requital requit + requite requit requited requit + requites requit rer rer + rere rere rers rer + rescu rescu rescue rescu + rescued rescu rescues rescu + rescuing rescu resemblance resembl + resemble resembl resembled resembl + resembles resembl resembleth resembleth + resembling resembl reserv reserv + reservation reserv reserve reserv + reserved reserv reserves reserv + reside resid residence resid + resident resid resides resid + residing resid residue residu + resign resign resignation resign + resist resist resistance resist + resisted resist resisting resist + resists resist resolute resolut + resolutely resolut resolutes resolut + resolution resolut resolv resolv + resolve resolv resolved resolv + resolvedly resolvedli resolves resolv + resolveth resolveth resort resort + resorted resort resounding resound + resounds resound respeaking respeak + respect respect respected respect + respecting respect respective respect + respectively respect respects respect + respice respic respite respit + respites respit responsive respons + respose respos ress ress + rest rest rested rest + resteth resteth restful rest + resting rest restitution restitut + restless restless restor restor + restoration restor restorative restor + restore restor restored restor + restores restor restoring restor + restrain restrain restrained restrain + restraining restrain restrains restrain + restraint restraint rests rest + resty resti resum resum + resume resum resumes resum + resurrections resurrect retail retail + retails retail retain retain + retainers retain retaining retain + retell retel retention retent + retentive retent retinue retinu + retir retir retire retir + retired retir retirement retir + retires retir retiring retir + retold retold retort retort + retorts retort retourne retourn + retract retract retreat retreat + retrograde retrograd rets ret + return return returned return + returnest returnest returneth returneth + returning return returns return + revania revania reveal reveal + reveals reveal revel revel + reveler revel revell revel + reveller revel revellers revel + revelling revel revelry revelri + revels revel reveng reveng + revenge reveng revenged reveng + revengeful reveng revengement reveng + revenger reveng revengers reveng + revenges reveng revenging reveng + revengingly revengingli revenue revenu + revenues revenu reverb reverb + reverberate reverber reverbs reverb + reverenc reverenc reverence rever + reverend reverend reverent rever + reverently rever revers rever + reverse revers reversion revers + reverted revert review review + reviewest reviewest revil revil + revile revil revisits revisit + reviv reviv revive reviv + revives reviv reviving reviv + revok revok revoke revok + revokement revok revolt revolt + revolted revolt revolting revolt + revolts revolt revolution revolut + revolutions revolut revolve revolv + revolving revolv reward reward + rewarded reward rewarder reward + rewarding reward rewards reward + reword reword reworded reword + rex rex rey rei + reynaldo reynaldo rford rford + rful rful rfull rfull + rhapsody rhapsodi rheims rheim + rhenish rhenish rhesus rhesu + rhetoric rhetor rheum rheum + rheumatic rheumat rheums rheum + rheumy rheumi rhinoceros rhinocero + rhodes rhode rhodope rhodop + rhubarb rhubarb rhym rhym + rhyme rhyme rhymers rhymer + rhymes rhyme rhyming rhyme + rialto rialto rib rib + ribald ribald riband riband + ribands riband ribaudred ribaudr + ribb ribb ribbed rib + ribbon ribbon ribbons ribbon + ribs rib rice rice + rich rich richard richard + richer richer riches rich + richest richest richly richli + richmond richmond richmonds richmond + rid rid riddance riddanc + ridden ridden riddle riddl + riddles riddl riddling riddl + ride ride rider rider + riders rider rides ride + ridest ridest rideth rideth + ridge ridg ridges ridg + ridiculous ridicul riding ride + rids rid rien rien + ries ri rifle rifl + rift rift rifted rift + rig rig rigg rigg + riggish riggish right right + righteous righteou righteously righteous + rightful right rightfully rightfulli + rightly rightli rights right + rigol rigol rigorous rigor + rigorously rigor rigour rigour + ril ril rim rim + rin rin rinaldo rinaldo + rind rind ring ring + ringing ring ringleader ringlead + ringlets ringlet rings ring + ringwood ringwood riot riot + rioter rioter rioting riot + riotous riotou riots riot + rip rip ripe ripe + ripely ripe ripen ripen + ripened ripen ripeness ripe + ripening ripen ripens ripen + riper riper ripest ripest + riping ripe ripp ripp + ripping rip rise rise + risen risen rises rise + riseth riseth rish rish + rising rise rite rite + rites rite rivage rivag + rival rival rivality rival + rivall rival rivals rival + rive rive rived rive + rivelled rivel river river + rivers river rivet rivet + riveted rivet rivets rivet + rivo rivo rj rj + rless rless road road + roads road roam roam + roaming roam roan roan + roar roar roared roar + roarers roarer roaring roar + roars roar roast roast + roasted roast rob rob + roba roba robas roba + robb robb robbed rob + robber robber robbers robber + robbery robberi robbing rob + robe robe robed robe + robert robert robes robe + robin robin robs rob + robustious robusti rochester rochest + rochford rochford rock rock + rocks rock rocky rocki + rod rod rode rode + roderigo roderigo rods rod + roe roe roes roe + roger roger rogero rogero + rogue rogu roguery rogueri + rogues rogu roguish roguish + roi roi roisting roist + roll roll rolled roll + rolling roll rolls roll + rom rom romage romag + roman roman romano romano + romanos romano romans roman + rome rome romeo romeo + romish romish rondure rondur + ronyon ronyon rood rood + roof roof roofs roof + rook rook rooks rook + rooky rooki room room + rooms room root root + rooted root rootedly rootedli + rooteth rooteth rooting root + roots root rope rope + ropery roperi ropes rope + roping rope ros ro + rosalind rosalind rosalinda rosalinda + rosalinde rosalind rosaline rosalin + roscius rosciu rose rose + rosed rose rosemary rosemari + rosencrantz rosencrantz roses rose + ross ross rosy rosi + rot rot rote rote + roted rote rother rother + rotherham rotherham rots rot + rotted rot rotten rotten + rottenness rotten rotting rot + rotundity rotund rouen rouen + rough rough rougher rougher + roughest roughest roughly roughli + roughness rough round round + rounded round roundel roundel + rounder rounder roundest roundest + rounding round roundly roundli + rounds round roundure roundur + rous rou rouse rous + roused rous rousillon rousillon + rously rousli roussi roussi + rout rout routed rout + routs rout rove rove + rover rover row row + rowel rowel rowland rowland + rowlands rowland roy roi + royal royal royalize royal + royally royal royalties royalti + royalty royalti roynish roynish + rs rs rt rt + rub rub rubb rubb + rubbing rub rubbish rubbish + rubies rubi rubious rubiou + rubs rub ruby rubi + rud rud rudand rudand + rudder rudder ruddiness ruddi + ruddock ruddock ruddy ruddi + rude rude rudely rude + rudeness rude ruder ruder + rudesby rudesbi rudest rudest + rudiments rudiment rue rue + rued ru ruff ruff + ruffian ruffian ruffians ruffian + ruffle ruffl ruffling ruffl + ruffs ruff rug rug + rugby rugbi rugemount rugemount + rugged rug ruin ruin + ruinate ruinat ruined ruin + ruining ruin ruinous ruinou + ruins ruin rul rul + rule rule ruled rule + ruler ruler rulers ruler + rules rule ruling rule + rumble rumbl ruminaies ruminai + ruminat ruminat ruminate rumin + ruminated rumin ruminates rumin + rumination rumin rumor rumor + rumour rumour rumourer rumour + rumours rumour rump rump + run run runagate runag + runagates runag runaway runawai + runaways runawai rung rung + runn runn runner runner + runners runner running run + runs run rupture ruptur + ruptures ruptur rural rural + rush rush rushes rush + rushing rush rushling rushl + rushy rushi russet russet + russia russia russian russian + russians russian rust rust + rusted rust rustic rustic + rustically rustic rustics rustic + rustle rustl rustling rustl + rusts rust rusty rusti + rut rut ruth ruth + ruthful ruth ruthless ruthless + rutland rutland ruttish ruttish + ry ry rye rye + rything ryth s s + sa sa saba saba + sabbath sabbath sable sabl + sables sabl sack sack + sackbuts sackbut sackcloth sackcloth + sacked sack sackerson sackerson + sacks sack sacrament sacrament + sacred sacr sacrific sacrif + sacrifice sacrific sacrificers sacrific + sacrifices sacrific sacrificial sacrifici + sacrificing sacrif sacrilegious sacrilegi + sacring sacr sad sad + sadder sadder saddest saddest + saddle saddl saddler saddler + saddles saddl sadly sadli + sadness sad saf saf + safe safe safeguard safeguard + safely safe safer safer + safest safest safeties safeti + safety safeti saffron saffron + sag sag sage sage + sagittary sagittari said said + saidst saidst sail sail + sailing sail sailmaker sailmak + sailor sailor sailors sailor + sails sail sain sain + saint saint sainted saint + saintlike saintlik saints saint + saith saith sake sake + sakes sake sala sala + salad salad salamander salamand + salary salari sale sale + salerio salerio salicam salicam + salique saliqu salisbury salisburi + sall sall sallet sallet + sallets sallet sallies salli + sallow sallow sally salli + salmon salmon salmons salmon + salt salt salter salter + saltiers saltier saltness salt + saltpetre saltpetr salutation salut + salutations salut salute salut + saluted salut salutes salut + saluteth saluteth salv salv + salvation salvat salve salv + salving salv same same + samingo samingo samp samp + sampire sampir sample sampl + sampler sampler sampson sampson + samson samson samsons samson + sancta sancta sanctified sanctifi + sanctifies sanctifi sanctify sanctifi + sanctimonies sanctimoni sanctimonious sanctimoni + sanctimony sanctimoni sanctities sanctiti + sanctity sanctiti sanctuarize sanctuar + sanctuary sanctuari sand sand + sandal sandal sandbag sandbag + sanded sand sands sand + sandy sandi sandys sandi + sang sang sanguine sanguin + sanguis sangui sanity saniti + sans san santrailles santrail + sap sap sapient sapient + sapit sapit sapless sapless + sapling sapl sapphire sapphir + sapphires sapphir saracens saracen + sarcenet sarcenet sard sard + sardians sardian sardinia sardinia + sardis sardi sarum sarum + sat sat satan satan + satchel satchel sate sate + sated sate satiate satiat + satiety satieti satin satin + satire satir satirical satir + satis sati satisfaction satisfact + satisfied satisfi satisfies satisfi + satisfy satisfi satisfying satisfi + saturday saturdai saturdays saturdai + saturn saturn saturnine saturnin + saturninus saturninu satyr satyr + satyrs satyr sauc sauc + sauce sauc sauced sauc + saucers saucer sauces sauc + saucily saucili sauciness sauci + saucy sauci sauf sauf + saunder saunder sav sav + savage savag savagely savag + savageness savag savagery savageri + savages savag save save + saved save saves save + saving save saviour saviour + savory savori savour savour + savouring savour savours savour + savoury savouri savoy savoi + saw saw sawed saw + sawest sawest sawn sawn + sawpit sawpit saws saw + sawyer sawyer saxons saxon + saxony saxoni saxton saxton + say sai sayest sayest + saying sai sayings sai + says sai sayst sayst + sblood sblood sc sc + scab scab scabbard scabbard + scabs scab scaffold scaffold + scaffoldage scaffoldag scal scal + scald scald scalded scald + scalding scald scale scale + scaled scale scales scale + scaling scale scall scall + scalp scalp scalps scalp + scaly scali scamble scambl + scambling scambl scamels scamel + scan scan scandal scandal + scandaliz scandaliz scandalous scandal + scandy scandi scann scann + scant scant scanted scant + scanter scanter scanting scant + scantling scantl scants scant + scap scap scape scape + scaped scape scapes scape + scapeth scapeth scar scar + scarce scarc scarcely scarc + scarcity scarciti scare scare + scarecrow scarecrow scarecrows scarecrow + scarf scarf scarfed scarf + scarfs scarf scaring scare + scarlet scarlet scarr scarr + scarre scarr scars scar + scarus scaru scath scath + scathe scath scathful scath + scatt scatt scatter scatter + scattered scatter scattering scatter + scatters scatter scelera scelera + scelerisque scelerisqu scene scene + scenes scene scent scent + scented scent scept scept + scepter scepter sceptre sceptr + sceptred sceptr sceptres sceptr + schedule schedul schedules schedul + scholar scholar scholarly scholarli + scholars scholar school school + schoolboy schoolboi schoolboys schoolboi + schoolfellows schoolfellow schooling school + schoolmaster schoolmast schoolmasters schoolmast + schools school sciatica sciatica + sciaticas sciatica science scienc + sciences scienc scimitar scimitar + scion scion scions scion + scissors scissor scoff scoff + scoffer scoffer scoffing scof + scoffs scoff scoggin scoggin + scold scold scolding scold + scolds scold sconce sconc + scone scone scope scope + scopes scope scorch scorch + scorched scorch score score + scored score scores score + scoring score scorn scorn + scorned scorn scornful scorn + scornfully scornfulli scorning scorn + scorns scorn scorpion scorpion + scorpions scorpion scot scot + scotch scotch scotches scotch + scotland scotland scots scot + scottish scottish scoundrels scoundrel + scour scour scoured scour + scourg scourg scourge scourg + scouring scour scout scout + scouts scout scowl scowl + scrap scrap scrape scrape + scraping scrape scraps scrap + scratch scratch scratches scratch + scratching scratch scream scream + screams scream screech screech + screeching screech screen screen + screens screen screw screw + screws screw scribbl scribbl + scribbled scribbl scribe scribe + scribes scribe scrimers scrimer + scrip scrip scrippage scrippag + scripture scriptur scriptures scriptur + scrivener scriven scroll scroll + scrolls scroll scroop scroop + scrowl scrowl scroyles scroyl + scrubbed scrub scruple scrupl + scruples scrupl scrupulous scrupul + scuffles scuffl scuffling scuffl + scullion scullion sculls scull + scum scum scurril scurril + scurrility scurril scurrilous scurril + scurvy scurvi scuse scuse + scut scut scutcheon scutcheon + scutcheons scutcheon scylla scylla + scythe scyth scythed scyth + scythia scythia scythian scythian + sdeath sdeath se se + sea sea seacoal seacoal + seafaring seafar seal seal + sealed seal sealing seal + seals seal seam seam + seamen seamen seamy seami + seaport seaport sear sear + searce searc search search + searchers searcher searches search + searcheth searcheth searching search + seared sear seas sea + seasick seasick seaside seasid + season season seasoned season + seasons season seat seat + seated seat seats seat + sebastian sebastian second second + secondarily secondarili secondary secondari + seconded second seconds second + secrecy secreci secret secret + secretaries secretari secretary secretari + secretly secretli secrets secret + sect sect sectary sectari + sects sect secundo secundo + secure secur securely secur + securing secur security secur + sedg sedg sedge sedg + sedges sedg sedgy sedgi + sedition sedit seditious sediti + seduc seduc seduce seduc + seduced seduc seducer seduc + seducing seduc see see + seed seed seeded seed + seedness seed seeds seed + seedsman seedsman seein seein + seeing see seek seek + seeking seek seeks seek + seel seel seeling seel + seely seeli seem seem + seemed seem seemers seemer + seemest seemest seemeth seemeth + seeming seem seemingly seemingli + seemly seemli seems seem + seen seen seer seer + sees see seese sees + seest seest seethe seeth + seethes seeth seething seeth + seeting seet segregation segreg + seigneur seigneur seigneurs seigneur + seiz seiz seize seiz + seized seiz seizes seiz + seizeth seizeth seizing seiz + seizure seizur seld seld + seldom seldom select select + seleucus seleucu self self + selfsame selfsam sell sell + seller seller selling sell + sells sell selves selv + semblable semblabl semblably semblabl + semblance semblanc semblances semblanc + semblative sembl semi semi + semicircle semicircl semiramis semirami + semper semper sempronius semproniu + senate senat senator senat + senators senat send send + sender sender sendeth sendeth + sending send sends send + seneca seneca senior senior + seniory seniori senis seni + sennet sennet senoys senoi + sense sens senseless senseless + senses sens sensible sensibl + sensibly sensibl sensual sensual + sensuality sensual sent sent + sentenc sentenc sentence sentenc + sentences sentenc sententious sententi + sentinel sentinel sentinels sentinel + separable separ separate separ + separated separ separates separ + separation separ septentrion septentrion + sepulchre sepulchr sepulchres sepulchr + sepulchring sepulchr sequel sequel + sequence sequenc sequent sequent + sequest sequest sequester sequest + sequestration sequestr sere sere + serenis sereni serge serg + sergeant sergeant serious seriou + seriously serious sermon sermon + sermons sermon serpent serpent + serpentine serpentin serpents serpent + serpigo serpigo serv serv + servant servant servanted servant + servants servant serve serv + served serv server server + serves serv serveth serveth + service servic serviceable servic + services servic servile servil + servility servil servilius serviliu + serving serv servingman servingman + servingmen servingmen serviteur serviteur + servitor servitor servitors servitor + servitude servitud sessa sessa + session session sessions session + sestos sesto set set + setebos setebo sets set + setter setter setting set + settle settl settled settl + settlest settlest settling settl + sev sev seven seven + sevenfold sevenfold sevennight sevennight + seventeen seventeen seventh seventh + seventy seventi sever sever + several sever severally sever + severals sever severe sever + severed sever severely sever + severest severest severing sever + severity sever severn severn + severs sever sew sew + seward seward sewer sewer + sewing sew sex sex + sexes sex sexton sexton + sextus sextu seymour seymour + seyton seyton sfoot sfoot + sh sh shackle shackl + shackles shackl shade shade + shades shade shadow shadow + shadowed shadow shadowing shadow + shadows shadow shadowy shadowi + shady shadi shafalus shafalu + shaft shaft shafts shaft + shag shag shak shak + shake shake shaked shake + shaken shaken shakes shake + shaking shake shales shale + shall shall shallenge shalleng + shallow shallow shallowest shallowest + shallowly shallowli shallows shallow + shalt shalt sham sham + shambles shambl shame shame + shamed shame shameful shame + shamefully shamefulli shameless shameless + shames shame shamest shamest + shaming shame shank shank + shanks shank shap shap + shape shape shaped shape + shapeless shapeless shapen shapen + shapes shape shaping shape + shar shar shard shard + sharded shard shards shard + share share shared share + sharers sharer shares share + sharing share shark shark + sharp sharp sharpen sharpen + sharpened sharpen sharpens sharpen + sharper sharper sharpest sharpest + sharply sharpli sharpness sharp + sharps sharp shatter shatter + shav shav shave shave + shaven shaven shaw shaw + she she sheaf sheaf + sheal sheal shear shear + shearers shearer shearing shear + shearman shearman shears shear + sheath sheath sheathe sheath + sheathed sheath sheathes sheath + sheathing sheath sheaved sheav + sheaves sheav shed shed + shedding shed sheds shed + sheen sheen sheep sheep + sheepcote sheepcot sheepcotes sheepcot + sheeps sheep sheepskins sheepskin + sheer sheer sheet sheet + sheeted sheet sheets sheet + sheffield sheffield shelf shelf + shell shell shells shell + shelt shelt shelter shelter + shelters shelter shelves shelv + shelving shelv shelvy shelvi + shent shent shepherd shepherd + shepherdes shepherd shepherdess shepherdess + shepherdesses shepherdess shepherds shepherd + sher sher sheriff sheriff + sherris sherri shes she + sheweth sheweth shield shield + shielded shield shields shield + shift shift shifted shift + shifting shift shifts shift + shilling shill shillings shill + shin shin shine shine + shines shine shineth shineth + shining shine shins shin + shiny shini ship ship + shipboard shipboard shipman shipman + shipmaster shipmast shipmen shipmen + shipp shipp shipped ship + shipping ship ships ship + shipt shipt shipwreck shipwreck + shipwrecking shipwreck shipwright shipwright + shipwrights shipwright shire shire + shirley shirlei shirt shirt + shirts shirt shive shive + shiver shiver shivering shiver + shivers shiver shoal shoal + shoals shoal shock shock + shocks shock shod shod + shoe shoe shoeing shoe + shoemaker shoemak shoes shoe + shog shog shone shone + shook shook shoon shoon + shoot shoot shooter shooter + shootie shooti shooting shoot + shoots shoot shop shop + shops shop shore shore + shores shore shorn shorn + short short shortcake shortcak + shorten shorten shortened shorten + shortens shorten shorter shorter + shortly shortli shortness short + shot shot shotten shotten + shoughs shough should should + shoulder shoulder shouldering shoulder + shoulders shoulder shouldst shouldst + shout shout shouted shout + shouting shout shouts shout + shov shov shove shove + shovel shovel shovels shovel + show show showed show + shower shower showers shower + showest showest showing show + shown shown shows show + shreds shred shrew shrew + shrewd shrewd shrewdly shrewdli + shrewdness shrewd shrewish shrewish + shrewishly shrewishli shrewishness shrewish + shrews shrew shrewsbury shrewsburi + shriek shriek shrieking shriek + shrieks shriek shrieve shriev + shrift shrift shrill shrill + shriller shriller shrills shrill + shrilly shrilli shrimp shrimp + shrine shrine shrink shrink + shrinking shrink shrinks shrink + shriv shriv shrive shrive + shriver shriver shrives shrive + shriving shrive shroud shroud + shrouded shroud shrouding shroud + shrouds shroud shrove shrove + shrow shrow shrows shrow + shrub shrub shrubs shrub + shrug shrug shrugs shrug + shrunk shrunk shudd shudd + shudders shudder shuffl shuffl + shuffle shuffl shuffled shuffl + shuffling shuffl shun shun + shunless shunless shunn shunn + shunned shun shunning shun + shuns shun shut shut + shuts shut shuttle shuttl + shy shy shylock shylock + si si sibyl sibyl + sibylla sibylla sibyls sibyl + sicil sicil sicilia sicilia + sicilian sicilian sicilius siciliu + sicils sicil sicily sicili + sicinius siciniu sick sick + sicken sicken sickens sicken + sicker sicker sickle sickl + sicklemen sicklemen sicklied sickli + sickliness sickli sickly sickli + sickness sick sicles sicl + sicyon sicyon side side + sided side sides side + siege sieg sieges sieg + sienna sienna sies si + sieve siev sift sift + sifted sift sigeia sigeia + sigh sigh sighed sigh + sighing sigh sighs sigh + sight sight sighted sight + sightless sightless sightly sightli + sights sight sign sign + signal signal signet signet + signieur signieur significant signific + significants signific signified signifi + signifies signifi signify signifi + signifying signifi signior signior + signiories signiori signiors signior + signiory signiori signor signor + signories signori signs sign + signum signum silenc silenc + silence silenc silenced silenc + silencing silenc silent silent + silently silent silius siliu + silk silk silken silken + silkman silkman silks silk + silliest silliest silliness silli + silling sill silly silli + silva silva silver silver + silvered silver silverly silverli + silvia silvia silvius silviu + sima sima simile simil + similes simil simois simoi + simon simon simony simoni + simp simp simpcox simpcox + simple simpl simpleness simpl + simpler simpler simples simpl + simplicity simplic simply simpli + simular simular simulation simul + sin sin since sinc + sincere sincer sincerely sincer + sincerity sincer sinel sinel + sinew sinew sinewed sinew + sinews sinew sinewy sinewi + sinful sin sinfully sinfulli + sing sing singe sing + singeing sing singer singer + singes sing singeth singeth + singing sing single singl + singled singl singleness singl + singly singli sings sing + singular singular singulariter singularit + singularities singular singularity singular + singuled singul sinister sinist + sink sink sinking sink + sinks sink sinn sinn + sinner sinner sinners sinner + sinning sin sinon sinon + sins sin sip sip + sipping sip sir sir + sire sire siren siren + sirrah sirrah sirs sir + sist sist sister sister + sisterhood sisterhood sisterly sisterli + sisters sister sit sit + sith sith sithence sithenc + sits sit sitting sit + situate situat situation situat + situations situat siward siward + six six sixpence sixpenc + sixpences sixpenc sixpenny sixpenni + sixteen sixteen sixth sixth + sixty sixti siz siz + size size sizes size + sizzle sizzl skains skain + skamble skambl skein skein + skelter skelter skies ski + skilful skil skilfully skilfulli + skill skill skilless skilless + skillet skillet skillful skill + skills skill skim skim + skimble skimbl skin skin + skinker skinker skinny skinni + skins skin skip skip + skipp skipp skipper skipper + skipping skip skirmish skirmish + skirmishes skirmish skirr skirr + skirted skirt skirts skirt + skittish skittish skulking skulk + skull skull skulls skull + sky sky skyey skyei + skyish skyish slab slab + slack slack slackly slackli + slackness slack slain slain + slake slake sland sland + slander slander slandered slander + slanderer slander slanderers slander + slandering slander slanderous slander + slanders slander slash slash + slaught slaught slaughter slaughter + slaughtered slaughter slaughterer slaughter + slaughterman slaughterman slaughtermen slaughtermen + slaughterous slaughter slaughters slaughter + slave slave slaver slaver + slavery slaveri slaves slave + slavish slavish slay slai + slayeth slayeth slaying slai + slays slai sleave sleav + sledded sled sleek sleek + sleekly sleekli sleep sleep + sleeper sleeper sleepers sleeper + sleepest sleepest sleeping sleep + sleeps sleep sleepy sleepi + sleeve sleev sleeves sleev + sleid sleid sleided sleid + sleight sleight sleights sleight + slender slender slenderer slender + slenderly slenderli slept slept + slew slew slewest slewest + slice slice slid slid + slide slide slides slide + sliding slide slight slight + slighted slight slightest slightest + slightly slightli slightness slight + slights slight slily slili + slime slime slimy slimi + slings sling slink slink + slip slip slipp slipp + slipper slipper slippers slipper + slippery slipperi slips slip + slish slish slit slit + sliver sliver slobb slobb + slomber slomber slop slop + slope slope slops slop + sloth sloth slothful sloth + slough slough slovenly slovenli + slovenry slovenri slow slow + slower slower slowly slowli + slowness slow slubber slubber + slug slug sluggard sluggard + sluggardiz sluggardiz sluggish sluggish + sluic sluic slumb slumb + slumber slumber slumbers slumber + slumbery slumberi slunk slunk + slut slut sluts slut + sluttery slutteri sluttish sluttish + sluttishness sluttish sly sly + slys sly smack smack + smacking smack smacks smack + small small smaller smaller + smallest smallest smallness small + smalus smalu smart smart + smarting smart smartly smartli + smatch smatch smatter smatter + smear smear smell smell + smelling smell smells smell + smelt smelt smil smil + smile smile smiled smile + smiles smile smilest smilest + smilets smilet smiling smile + smilingly smilingli smirch smirch + smirched smirch smit smit + smite smite smites smite + smith smith smithfield smithfield + smock smock smocks smock + smok smok smoke smoke + smoked smoke smokes smoke + smoking smoke smoky smoki + smooth smooth smoothed smooth + smoothing smooth smoothly smoothli + smoothness smooth smooths smooth + smote smote smoth smoth + smother smother smothered smother + smothering smother smug smug + smulkin smulkin smutch smutch + snaffle snaffl snail snail + snails snail snake snake + snakes snake snaky snaki + snap snap snapp snapp + snapper snapper snar snar + snare snare snares snare + snarl snarl snarleth snarleth + snarling snarl snatch snatch + snatchers snatcher snatches snatch + snatching snatch sneak sneak + sneaking sneak sneap sneap + sneaping sneap sneck sneck + snip snip snipe snipe + snipt snipt snore snore + snores snore snoring snore + snorting snort snout snout + snow snow snowballs snowbal + snowed snow snowy snowi + snuff snuff snuffs snuff + snug snug so so + soak soak soaking soak + soaks soak soar soar + soaring soar soars soar + sob sob sobbing sob + sober sober soberly soberli + sobriety sobrieti sobs sob + sociable sociabl societies societi + society societi socks sock + socrates socrat sod sod + sodden sodden soe soe + soever soever soft soft + soften soften softens soften + softer softer softest softest + softly softli softness soft + soil soil soiled soil + soilure soilur soit soit + sojourn sojourn sol sol + sola sola solace solac + solanio solanio sold sold + soldat soldat solder solder + soldest soldest soldier soldier + soldiers soldier soldiership soldiership + sole sole solely sole + solem solem solemn solemn + solemness solem solemnities solemn + solemnity solemn solemniz solemniz + solemnize solemn solemnized solemn + solemnly solemnli soles sole + solicit solicit solicitation solicit + solicited solicit soliciting solicit + solicitings solicit solicitor solicitor + solicits solicit solid solid + solidares solidar solidity solid + solinus solinu solitary solitari + solomon solomon solon solon + solum solum solus solu + solyman solyman some some + somebody somebodi someone someon + somerset somerset somerville somervil + something someth sometime sometim + sometimes sometim somever somev + somewhat somewhat somewhere somewher + somewhither somewhith somme somm + son son sonance sonanc + song song songs song + sonnet sonnet sonneting sonnet + sonnets sonnet sons son + sont sont sonties sonti + soon soon sooner sooner + soonest soonest sooth sooth + soothe sooth soothers soother + soothing sooth soothsay soothsai + soothsayer soothsay sooty sooti + sop sop sophister sophist + sophisticated sophist sophy sophi + sops sop sorcerer sorcer + sorcerers sorcer sorceress sorceress + sorceries sorceri sorcery sorceri + sore sore sorel sorel + sorely sore sorer sorer + sores sore sorrier sorrier + sorriest sorriest sorrow sorrow + sorrowed sorrow sorrowest sorrowest + sorrowful sorrow sorrowing sorrow + sorrows sorrow sorry sorri + sort sort sortance sortanc + sorted sort sorting sort + sorts sort sossius sossiu + sot sot soto soto + sots sot sottish sottish + soud soud sought sought + soul soul sould sould + soulless soulless souls soul + sound sound sounded sound + sounder sounder soundest soundest + sounding sound soundless soundless + soundly soundli soundness sound + soundpost soundpost sounds sound + sour sour source sourc + sources sourc sourest sourest + sourly sourli sours sour + sous sou souse sous + south south southam southam + southampton southampton southerly southerli + southern southern southward southward + southwark southwark southwell southwel + souviendrai souviendrai sov sov + sovereign sovereign sovereignest sovereignest + sovereignly sovereignli sovereignty sovereignti + sovereignvours sovereignvour sow sow + sowing sow sowl sowl + sowter sowter space space + spaces space spacious spaciou + spade spade spades spade + spain spain spak spak + spake spake spakest spakest + span span spangle spangl + spangled spangl spaniard spaniard + spaniel spaniel spaniels spaniel + spanish spanish spann spann + spans span spar spar + spare spare spares spare + sparing spare sparingly sparingli + spark spark sparkle sparkl + sparkles sparkl sparkling sparkl + sparks spark sparrow sparrow + sparrows sparrow sparta sparta + spartan spartan spavin spavin + spavins spavin spawn spawn + speak speak speaker speaker + speakers speaker speakest speakest + speaketh speaketh speaking speak + speaks speak spear spear + speargrass speargrass spears spear + special special specialities special + specially special specialties specialti + specialty specialti specify specifi + speciously specious spectacle spectacl + spectacled spectacl spectacles spectacl + spectators spectat spectatorship spectatorship + speculation specul speculations specul + speculative specul sped sped + speech speech speeches speech + speechless speechless speed speed + speeded speed speedier speedier + speediest speediest speedily speedili + speediness speedi speeding speed + speeds speed speedy speedi + speens speen spell spell + spelling spell spells spell + spelt spelt spencer spencer + spend spend spendest spendest + spending spend spends spend + spendthrift spendthrift spent spent + sperato sperato sperm sperm + spero spero sperr sperr + spher spher sphere sphere + sphered sphere spheres sphere + spherical spheric sphery spheri + sphinx sphinx spice spice + spiced spice spicery spiceri + spices spice spider spider + spiders spider spied spi + spies spi spieth spieth + spightfully spightfulli spigot spigot + spill spill spilling spill + spills spill spilt spilt + spilth spilth spin spin + spinii spinii spinners spinner + spinster spinster spinsters spinster + spire spire spirit spirit + spirited spirit spiritless spiritless + spirits spirit spiritual spiritu + spiritualty spiritualti spirt spirt + spit spit spital spital + spite spite spited spite + spiteful spite spites spite + spits spit spitted spit + spitting spit splay splai + spleen spleen spleenful spleen + spleens spleen spleeny spleeni + splendour splendour splenitive splenit + splinter splinter splinters splinter + split split splits split + splitted split splitting split + spoil spoil spoils spoil + spok spok spoke spoke + spoken spoken spokes spoke + spokesman spokesman sponge spong + spongy spongi spoon spoon + spoons spoon sport sport + sportful sport sporting sport + sportive sportiv sports sport + spot spot spotless spotless + spots spot spotted spot + spousal spousal spouse spous + spout spout spouting spout + spouts spout sprag sprag + sprang sprang sprat sprat + sprawl sprawl spray sprai + sprays sprai spread spread + spreading spread spreads spread + sprighted spright sprightful spright + sprightly sprightli sprigs sprig + spring spring springe spring + springes spring springeth springeth + springhalt springhalt springing spring + springs spring springtime springtim + sprinkle sprinkl sprinkles sprinkl + sprite sprite sprited sprite + spritely sprite sprites sprite + spriting sprite sprout sprout + spruce spruce sprung sprung + spun spun spur spur + spurio spurio spurn spurn + spurns spurn spurr spurr + spurrer spurrer spurring spur + spurs spur spy spy + spying spy squabble squabbl + squadron squadron squadrons squadron + squand squand squar squar + square squar squarer squarer + squares squar squash squash + squeak squeak squeaking squeak + squeal squeal squealing squeal + squeezes squeez squeezing squeez + squele squel squier squier + squints squint squiny squini + squire squir squires squir + squirrel squirrel st st + stab stab stabb stabb + stabbed stab stabbing stab + stable stabl stableness stabl + stables stabl stablish stablish + stablishment stablish stabs stab + stacks stack staff staff + stafford stafford staffords stafford + staffordshire staffordshir stag stag + stage stage stages stage + stagger stagger staggering stagger + staggers stagger stags stag + staid staid staider staider + stain stain stained stain + staines stain staineth staineth + staining stain stainless stainless + stains stain stair stair + stairs stair stake stake + stakes stake stale stale + staled stale stalk stalk + stalking stalk stalks stalk + stall stall stalling stall + stalls stall stamford stamford + stammer stammer stamp stamp + stamped stamp stamps stamp + stanch stanch stanchless stanchless + stand stand standard standard + standards standard stander stander + standers stander standest standest + standeth standeth standing stand + stands stand staniel staniel + stanley stanlei stanze stanz + stanzo stanzo stanzos stanzo + staple stapl staples stapl + star star stare stare + stared stare stares stare + staring stare starings stare + stark stark starkly starkli + starlight starlight starling starl + starr starr starry starri + stars star start start + started start starting start + startingly startingli startle startl + startles startl starts start + starv starv starve starv + starved starv starvelackey starvelackei + starveling starvel starveth starveth + starving starv state state + statelier stateli stately state + states state statesman statesman + statesmen statesmen statilius statiliu + station station statist statist + statists statist statue statu + statues statu stature statur + statures statur statute statut + statutes statut stave stave + staves stave stay stai + stayed stai stayest stayest + staying stai stays stai + stead stead steaded stead + steadfast steadfast steadier steadier + steads stead steal steal + stealer stealer stealers stealer + stealing steal steals steal + stealth stealth stealthy stealthi + steed steed steeds steed + steel steel steeled steel + steely steeli steep steep + steeped steep steeple steepl + steeples steepl steeps steep + steepy steepi steer steer + steerage steerag steering steer + steers steer stelled stell + stem stem stemming stem + stench stench step step + stepdame stepdam stephano stephano + stephen stephen stepmothers stepmoth + stepp stepp stepping step + steps step sterile steril + sterility steril sterling sterl + stern stern sternage sternag + sterner sterner sternest sternest + sternness stern steterat steterat + stew stew steward steward + stewards steward stewardship stewardship + stewed stew stews stew + stick stick sticking stick + stickler stickler sticks stick + stiff stiff stiffen stiffen + stiffly stiffli stifle stifl + stifled stifl stifles stifl + stigmatic stigmat stigmatical stigmat + stile stile still still + stiller stiller stillest stillest + stillness still stilly stilli + sting sting stinging sting + stingless stingless stings sting + stink stink stinking stink + stinkingly stinkingli stinks stink + stint stint stinted stint + stints stint stir stir + stirr stirr stirred stir + stirrer stirrer stirrers stirrer + stirreth stirreth stirring stir + stirrup stirrup stirrups stirrup + stirs stir stitchery stitcheri + stitches stitch stithied stithi + stithy stithi stoccadoes stoccado + stoccata stoccata stock stock + stockfish stockfish stocking stock + stockings stock stockish stockish + stocks stock stog stog + stogs stog stoics stoic + stokesly stokesli stol stol + stole stole stolen stolen + stolest stolest stomach stomach + stomachers stomach stomaching stomach + stomachs stomach ston ston + stone stone stonecutter stonecutt + stones stone stonish stonish + stony stoni stood stood + stool stool stools stool + stoop stoop stooping stoop + stoops stoop stop stop + stope stope stopp stopp + stopped stop stopping stop + stops stop stor stor + store store storehouse storehous + storehouses storehous stores store + stories stori storm storm + stormed storm storming storm + storms storm stormy stormi + story stori stoup stoup + stoups stoup stout stout + stouter stouter stoutly stoutli + stoutness stout stover stover + stow stow stowage stowag + stowed stow strachy strachi + stragglers straggler straggling straggl + straight straight straightest straightest + straightway straightwai strain strain + strained strain straining strain + strains strain strait strait + straited strait straiter straiter + straitly straitli straitness strait + straits strait strand strand + strange strang strangely strang + strangeness strang stranger stranger + strangers stranger strangest strangest + strangle strangl strangled strangl + strangler strangler strangles strangl + strangling strangl strappado strappado + straps strap stratagem stratagem + stratagems stratagem stratford stratford + strato strato straw straw + strawberries strawberri strawberry strawberri + straws straw strawy strawi + stray strai straying strai + strays strai streak streak + streaks streak stream stream + streamers streamer streaming stream + streams stream streching strech + street street streets street + strength strength strengthen strengthen + strengthened strengthen strengthless strengthless + strengths strength stretch stretch + stretched stretch stretches stretch + stretching stretch strew strew + strewing strew strewings strew + strewments strewment stricken stricken + strict strict stricter stricter + strictest strictest strictly strictli + stricture strictur stride stride + strides stride striding stride + strife strife strifes strife + strik strik strike strike + strikers striker strikes strike + strikest strikest striking strike + string string stringless stringless + strings string strip strip + stripes stripe stripling stripl + striplings stripl stripp stripp + stripping strip striv striv + strive strive strives strive + striving strive strok strok + stroke stroke strokes stroke + strond strond stronds strond + strong strong stronger stronger + strongest strongest strongly strongli + strooke strook strossers strosser + strove strove strown strown + stroy stroi struck struck + strucken strucken struggle struggl + struggles struggl struggling struggl + strumpet strumpet strumpeted strumpet + strumpets strumpet strung strung + strut strut struts strut + strutted strut strutting strut + stubble stubbl stubborn stubborn + stubbornest stubbornest stubbornly stubbornli + stubbornness stubborn stuck stuck + studded stud student student + students student studied studi + studies studi studious studiou + studiously studious studs stud + study studi studying studi + stuff stuff stuffing stuf + stuffs stuff stumble stumbl + stumbled stumbl stumblest stumblest + stumbling stumbl stump stump + stumps stump stung stung + stupefy stupefi stupid stupid + stupified stupifi stuprum stuprum + sturdy sturdi sty sty + styga styga stygian stygian + styl styl style style + styx styx su su + sub sub subcontracted subcontract + subdu subdu subdue subdu + subdued subdu subduements subduement + subdues subdu subduing subdu + subject subject subjected subject + subjection subject subjects subject + submerg submerg submission submiss + submissive submiss submit submit + submits submit submitting submit + suborn suborn subornation suborn + suborned suborn subscrib subscrib + subscribe subscrib subscribed subscrib + subscribes subscrib subscription subscript + subsequent subsequ subsidies subsidi + subsidy subsidi subsist subsist + subsisting subsist substance substanc + substances substanc substantial substanti + substitute substitut substituted substitut + substitutes substitut substitution substitut + subtile subtil subtilly subtilli + subtle subtl subtleties subtleti + subtlety subtleti subtly subtli + subtractors subtractor suburbs suburb + subversion subvers subverts subvert + succedant succed succeed succe + succeeded succeed succeeders succeed + succeeding succeed succeeds succe + success success successantly successantli + successes success successful success + successfully successfulli succession success + successive success successively success + successor successor successors successor + succour succour succours succour + such such suck suck + sucker sucker suckers sucker + sucking suck suckle suckl + sucks suck sudden sudden + suddenly suddenli sue sue + sued su suerly suerli + sues sue sueth sueth + suff suff suffer suffer + sufferance suffer sufferances suffer + suffered suffer suffering suffer + suffers suffer suffic suffic + suffice suffic sufficed suffic + suffices suffic sufficeth sufficeth + sufficiency suffici sufficient suffici + sufficiently suffici sufficing suffic + sufficit sufficit suffigance suffig + suffocate suffoc suffocating suffoc + suffocation suffoc suffolk suffolk + suffrage suffrag suffrages suffrag + sug sug sugar sugar + sugarsop sugarsop suggest suggest + suggested suggest suggesting suggest + suggestion suggest suggestions suggest + suggests suggest suis sui + suit suit suitable suitabl + suited suit suiting suit + suitor suitor suitors suitor + suits suit suivez suivez + sullen sullen sullens sullen + sullied sulli sullies sulli + sully sulli sulph sulph + sulpherous sulpher sulphur sulphur + sulphurous sulphur sultan sultan + sultry sultri sum sum + sumless sumless summ summ + summa summa summary summari + summer summer summers summer + summit summit summon summon + summoners summon summons summon + sumpter sumpter sumptuous sumptuou + sumptuously sumptuous sums sum + sun sun sunbeams sunbeam + sunburning sunburn sunburnt sunburnt + sund sund sunday sundai + sundays sundai sunder sunder + sunders sunder sundry sundri + sung sung sunk sunk + sunken sunken sunny sunni + sunrising sunris suns sun + sunset sunset sunshine sunshin + sup sup super super + superficial superfici superficially superfici + superfluity superflu superfluous superflu + superfluously superflu superflux superflux + superior superior supernal supern + supernatural supernatur superpraise superprais + superscript superscript superscription superscript + superserviceable superservic superstition superstit + superstitious superstiti superstitiously superstiti + supersubtle supersubtl supervise supervis + supervisor supervisor supp supp + supper supper suppers supper + suppertime suppertim supping sup + supplant supplant supple suppl + suppler suppler suppliance supplianc + suppliant suppliant suppliants suppliant + supplicant supplic supplication supplic + supplications supplic supplie suppli + supplied suppli supplies suppli + suppliest suppliest supply suppli + supplyant supplyant supplying suppli + supplyment supplyment support support + supportable support supportance support + supported support supporter support + supporters support supporting support + supportor supportor suppos suppo + supposal suppos suppose suppos + supposed suppos supposes suppos + supposest supposest supposing suppos + supposition supposit suppress suppress + suppressed suppress suppresseth suppresseth + supremacy supremaci supreme suprem + sups sup sur sur + surance suranc surcease surceas + surd surd sure sure + surecard surecard surely sure + surer surer surest surest + sureties sureti surety sureti + surfeit surfeit surfeited surfeit + surfeiter surfeit surfeiting surfeit + surfeits surfeit surge surg + surgeon surgeon surgeons surgeon + surgere surger surgery surgeri + surges surg surly surli + surmis surmi surmise surmis + surmised surmis surmises surmis + surmount surmount surmounted surmount + surmounts surmount surnam surnam + surname surnam surnamed surnam + surpasseth surpasseth surpassing surpass + surplice surplic surplus surplu + surpris surpri surprise surpris + surprised surpris surrender surrend + surrey surrei surreys surrei + survey survei surveyest surveyest + surveying survei surveyor surveyor + surveyors surveyor surveys survei + survive surviv survives surviv + survivor survivor susan susan + suspect suspect suspected suspect + suspecting suspect suspects suspect + suspend suspend suspense suspens + suspicion suspicion suspicions suspicion + suspicious suspici suspiration suspir + suspire suspir sust sust + sustain sustain sustaining sustain + sutler sutler sutton sutton + suum suum swabber swabber + swaddling swaddl swag swag + swagg swagg swagger swagger + swaggerer swagger swaggerers swagger + swaggering swagger swain swain + swains swain swallow swallow + swallowed swallow swallowing swallow + swallows swallow swam swam + swan swan swans swan + sward sward sware sware + swarm swarm swarming swarm + swart swart swarth swarth + swarths swarth swarthy swarthi + swashers swasher swashing swash + swath swath swathing swath + swathling swathl sway swai + swaying swai sways swai + swear swear swearer swearer + swearers swearer swearest swearest + swearing swear swearings swear + swears swear sweat sweat + sweaten sweaten sweating sweat + sweats sweat sweaty sweati + sweep sweep sweepers sweeper + sweeps sweep sweet sweet + sweeten sweeten sweetens sweeten + sweeter sweeter sweetest sweetest + sweetheart sweetheart sweeting sweet + sweetly sweetli sweetmeats sweetmeat + sweetness sweet sweets sweet + swell swell swelling swell + swellings swell swells swell + swelter swelter sweno sweno + swept swept swerve swerv + swerver swerver swerving swerv + swift swift swifter swifter + swiftest swiftest swiftly swiftli + swiftness swift swill swill + swills swill swim swim + swimmer swimmer swimmers swimmer + swimming swim swims swim + swine swine swineherds swineherd + swing swing swinge swing + swinish swinish swinstead swinstead + switches switch swits swit + switzers switzer swol swol + swoll swoll swoln swoln + swoon swoon swooned swoon + swooning swoon swoons swoon + swoop swoop swoopstake swoopstak + swor swor sword sword + sworder sworder swords sword + swore swore sworn sworn + swounded swound swounds swound + swum swum swung swung + sy sy sycamore sycamor + sycorax sycorax sylla sylla + syllable syllabl syllables syllabl + syllogism syllog symbols symbol + sympathise sympathis sympathiz sympathiz + sympathize sympath sympathized sympath + sympathy sympathi synagogue synagogu + synod synod synods synod + syracuse syracus syracusian syracusian + syracusians syracusian syria syria + syrups syrup t t + ta ta taber taber + table tabl tabled tabl + tables tabl tablet tablet + tabor tabor taborer tabor + tabors tabor tabourines tabourin + taciturnity taciturn tack tack + tackle tackl tackled tackl + tackles tackl tackling tackl + tacklings tackl taddle taddl + tadpole tadpol taffeta taffeta + taffety taffeti tag tag + tagrag tagrag tah tah + tail tail tailor tailor + tailors tailor tails tail + taint taint tainted taint + tainting taint taints taint + tainture taintur tak tak + take take taken taken + taker taker takes take + takest takest taketh taketh + taking take tal tal + talbot talbot talbotites talbotit + talbots talbot tale tale + talent talent talents talent + taleporter taleport tales tale + talk talk talked talk + talker talker talkers talker + talkest talkest talking talk + talks talk tall tall + taller taller tallest tallest + tallies talli tallow tallow + tally talli talons talon + tam tam tambourines tambourin + tame tame tamed tame + tamely tame tameness tame + tamer tamer tames tame + taming tame tamora tamora + tamworth tamworth tan tan + tang tang tangle tangl + tangled tangl tank tank + tanlings tanl tann tann + tanned tan tanner tanner + tanquam tanquam tanta tanta + tantaene tantaen tap tap + tape tape taper taper + tapers taper tapestries tapestri + tapestry tapestri taphouse taphous + tapp tapp tapster tapster + tapsters tapster tar tar + tardied tardi tardily tardili + tardiness tardi tardy tardi + tarentum tarentum targe targ + targes targ target target + targets target tarpeian tarpeian + tarquin tarquin tarquins tarquin + tarr tarr tarre tarr + tarriance tarrianc tarried tarri + tarries tarri tarry tarri + tarrying tarri tart tart + tartar tartar tartars tartar + tartly tartli tartness tart + task task tasker tasker + tasking task tasks task + tassel tassel taste tast + tasted tast tastes tast + tasting tast tatt tatt + tatter tatter tattered tatter + tatters tatter tattle tattl + tattling tattl tattlings tattl + taught taught taunt taunt + taunted taunt taunting taunt + tauntingly tauntingli taunts taunt + taurus tauru tavern tavern + taverns tavern tavy tavi + tawdry tawdri tawny tawni + tax tax taxation taxat + taxations taxat taxes tax + taxing tax tc tc + te te teach teach + teacher teacher teachers teacher + teaches teach teachest teachest + teacheth teacheth teaching teach + team team tear tear + tearful tear tearing tear + tears tear tearsheet tearsheet + teat teat tedious tediou + tediously tedious tediousness tedious + teem teem teeming teem + teems teem teen teen + teeth teeth teipsum teipsum + telamon telamon telamonius telamoniu + tell tell teller teller + telling tell tells tell + tellus tellu temp temp + temper temper temperality temper + temperance temper temperate temper + temperately temper tempers temper + tempest tempest tempests tempest + tempestuous tempestu temple templ + temples templ temporal tempor + temporary temporari temporiz temporiz + temporize tempor temporizer tempor + temps temp tempt tempt + temptation temptat temptations temptat + tempted tempt tempter tempter + tempters tempter tempteth tempteth + tempting tempt tempts tempt + ten ten tenable tenabl + tenant tenant tenantius tenantiu + tenantless tenantless tenants tenant + tench tench tend tend + tendance tendanc tended tend + tender tender tendered tender + tenderly tenderli tenderness tender + tenders tender tending tend + tends tend tenedos tenedo + tenement tenement tenements tenement + tenfold tenfold tennis tenni + tenour tenour tenours tenour + tens ten tent tent + tented tent tenth tenth + tenths tenth tents tent + tenure tenur tenures tenur + tercel tercel tereus tereu + term term termagant termag + termed term terminations termin + termless termless terms term + terra terra terrace terrac + terram terram terras terra + terre terr terrene terren + terrestrial terrestri terrible terribl + terribly terribl territories territori + territory territori terror terror + terrors terror tertian tertian + tertio tertio test test + testament testament tested test + tester tester testern testern + testify testifi testimonied testimoni + testimonies testimoni testimony testimoni + testiness testi testril testril + testy testi tetchy tetchi + tether tether tetter tetter + tevil tevil tewksbury tewksburi + text text tgv tgv + th th thaes thae + thames thame than than + thane thane thanes thane + thank thank thanked thank + thankful thank thankfully thankfulli + thankfulness thank thanking thank + thankings thank thankless thankless + thanks thank thanksgiving thanksgiv + thasos thaso that that + thatch thatch thaw thaw + thawing thaw thaws thaw + the the theatre theatr + theban theban thebes thebe + thee thee theft theft + thefts theft thein thein + their their theirs their + theise theis them them + theme theme themes theme + themselves themselv then then + thence thenc thenceforth thenceforth + theoric theoric there there + thereabout thereabout thereabouts thereabout + thereafter thereaft thereat thereat + thereby therebi therefore therefor + therein therein thereof thereof + thereon thereon thereto thereto + thereunto thereunto thereupon thereupon + therewith therewith therewithal therewith + thersites thersit these these + theseus theseu thessalian thessalian + thessaly thessali thetis theti + thews thew they thei + thick thick thicken thicken + thickens thicken thicker thicker + thickest thickest thicket thicket + thickskin thickskin thief thief + thievery thieveri thieves thiev + thievish thievish thigh thigh + thighs thigh thimble thimbl + thimbles thimbl thin thin + thine thine thing thing + things thing think think + thinkest thinkest thinking think + thinkings think thinks think + thinkst thinkst thinly thinli + third third thirdly thirdli + thirds third thirst thirst + thirsting thirst thirsts thirst + thirsty thirsti thirteen thirteen + thirties thirti thirtieth thirtieth + thirty thirti this thi + thisby thisbi thisne thisn + thistle thistl thistles thistl + thither thither thitherward thitherward + thoas thoa thomas thoma + thorn thorn thorns thorn + thorny thorni thorough thorough + thoroughly thoroughli those those + thou thou though though + thought thought thoughtful thought + thoughts thought thousand thousand + thousands thousand thracian thracian + thraldom thraldom thrall thrall + thralled thrall thralls thrall + thrash thrash thrasonical thrason + thread thread threadbare threadbar + threaden threaden threading thread + threat threat threaten threaten + threatening threaten threatens threaten + threatest threatest threats threat + three three threefold threefold + threepence threepenc threepile threepil + threes three threescore threescor + thresher thresher threshold threshold + threw threw thrice thrice + thrift thrift thriftless thriftless + thrifts thrift thrifty thrifti + thrill thrill thrilling thrill + thrills thrill thrive thrive + thrived thrive thrivers thriver + thrives thrive thriving thrive + throat throat throats throat + throbbing throb throbs throb + throca throca throe throe + throes throe thromuldo thromuldo + thron thron throne throne + throned throne thrones throne + throng throng thronging throng + throngs throng throstle throstl + throttle throttl through through + throughfare throughfar throughfares throughfar + throughly throughli throughout throughout + throw throw thrower thrower + throwest throwest throwing throw + thrown thrown throws throw + thrum thrum thrumm thrumm + thrush thrush thrust thrust + thrusteth thrusteth thrusting thrust + thrusts thrust thumb thumb + thumbs thumb thump thump + thund thund thunder thunder + thunderbolt thunderbolt thunderbolts thunderbolt + thunderer thunder thunders thunder + thunderstone thunderston thunderstroke thunderstrok + thurio thurio thursday thursdai + thus thu thwack thwack + thwart thwart thwarted thwart + thwarting thwart thwartings thwart + thy thy thyme thyme + thymus thymu thyreus thyreu + thyself thyself ti ti + tib tib tiber tiber + tiberio tiberio tibey tibei + ticed tice tick tick + tickl tickl tickle tickl + tickled tickl tickles tickl + tickling tickl ticklish ticklish + tiddle tiddl tide tide + tides tide tidings tide + tidy tidi tie tie + tied ti ties ti + tiff tiff tiger tiger + tigers tiger tight tight + tightly tightli tike tike + til til tile tile + till till tillage tillag + tilly tilli tilt tilt + tilter tilter tilth tilth + tilting tilt tilts tilt + tiltyard tiltyard tim tim + timandra timandra timber timber + time time timeless timeless + timelier timeli timely time + times time timon timon + timor timor timorous timor + timorously timor tinct tinct + tincture tinctur tinctures tinctur + tinder tinder tingling tingl + tinker tinker tinkers tinker + tinsel tinsel tiny tini + tip tip tipp tipp + tippling tippl tips tip + tipsy tipsi tiptoe tipto + tir tir tire tire + tired tire tires tire + tirest tirest tiring tire + tirra tirra tirrits tirrit + tis ti tish tish + tisick tisick tissue tissu + titan titan titania titania + tithe tith tithed tith + tithing tith titinius titiniu + title titl titled titl + titleless titleless titles titl + tittle tittl tittles tittl + titular titular titus titu + tn tn to to + toad toad toads toad + toadstool toadstool toast toast + toasted toast toasting toast + toasts toast toaze toaz + toby tobi tock tock + tod tod today todai + todpole todpol tods tod + toe toe toes toe + tofore tofor toge toge + toged toge together togeth + toil toil toiled toil + toiling toil toils toil + token token tokens token + told told toledo toledo + tolerable toler toll toll + tolling toll tom tom + tomb tomb tombe tomb + tombed tomb tombless tombless + tomboys tomboi tombs tomb + tomorrow tomorrow tomyris tomyri + ton ton tongs tong + tongu tongu tongue tongu + tongued tongu tongueless tongueless + tongues tongu tonight tonight + too too took took + tool tool tools tool + tooth tooth toothache toothach + toothpick toothpick toothpicker toothpick + top top topas topa + topful top topgallant topgal + topless topless topmast topmast + topp topp topping top + topple toppl topples toppl + tops top topsail topsail + topsy topsi torch torch + torchbearer torchbear torchbearers torchbear + torcher torcher torches torch + torchlight torchlight tore tore + torment torment tormenta tormenta + tormente torment tormented torment + tormenting torment tormentors tormentor + torments torment torn torn + torrent torrent tortive tortiv + tortoise tortois tortur tortur + torture tortur tortured tortur + torturer tortur torturers tortur + tortures tortur torturest torturest + torturing tortur toryne toryn + toss toss tossed toss + tosseth tosseth tossing toss + tot tot total total + totally total tott tott + tottered totter totters totter + tou tou touch touch + touched touch touches touch + toucheth toucheth touching touch + touchstone touchston tough tough + tougher tougher toughness tough + touraine tourain tournaments tournament + tours tour tous tou + tout tout touze touz + tow tow toward toward + towardly towardli towards toward + tower tower towering tower + towers tower town town + towns town township township + townsman townsman townsmen townsmen + towton towton toy toi + toys toi trace trace + traces trace track track + tract tract tractable tractabl + trade trade traded trade + traders trader trades trade + tradesman tradesman tradesmen tradesmen + trading trade tradition tradit + traditional tradit traduc traduc + traduced traduc traducement traduc + traffic traffic traffickers traffick + traffics traffic tragedian tragedian + tragedians tragedian tragedies tragedi + tragedy tragedi tragic tragic + tragical tragic trail trail + train train trained train + training train trains train + trait trait traitor traitor + traitorly traitorli traitorous traitor + traitorously traitor traitors traitor + traitress traitress traject traject + trammel trammel trample trampl + trampled trampl trampling trampl + tranc tranc trance tranc + tranio tranio tranquil tranquil + tranquillity tranquil transcendence transcend + transcends transcend transferred transfer + transfigur transfigur transfix transfix + transform transform transformation transform + transformations transform transformed transform + transgress transgress transgresses transgress + transgressing transgress transgression transgress + translate translat translated translat + translates translat translation translat + transmigrates transmigr transmutation transmut + transparent transpar transport transport + transportance transport transported transport + transporting transport transports transport + transpose transpos transshape transshap + trap trap trapp trapp + trappings trap traps trap + trash trash travail travail + travails travail travel travel + traveler travel traveling travel + travell travel travelled travel + traveller travel travellers travel + travellest travellest travelling travel + travels travel travers traver + traverse travers tray trai + treacherous treacher treacherously treacher + treachers treacher treachery treacheri + tread tread treading tread + treads tread treason treason + treasonable treason treasonous treason + treasons treason treasure treasur + treasurer treasur treasures treasur + treasuries treasuri treasury treasuri + treat treat treaties treati + treatise treatis treats treat + treaty treati treble trebl + trebled trebl trebles trebl + trebonius treboniu tree tree + trees tree tremble trembl + trembled trembl trembles trembl + tremblest tremblest trembling trembl + tremblingly tremblingli tremor tremor + trempling trempl trench trench + trenchant trenchant trenched trench + trencher trencher trenchering trencher + trencherman trencherman trenchers trencher + trenches trench trenching trench + trent trent tres tre + trespass trespass trespasses trespass + tressel tressel tresses tress + treys trei trial trial + trials trial trib trib + tribe tribe tribes tribe + tribulation tribul tribunal tribun + tribune tribun tribunes tribun + tributaries tributari tributary tributari + tribute tribut tributes tribut + trice trice trick trick + tricking trick trickling trickl + tricks trick tricksy tricksi + trident trident tried tri + trier trier trifle trifl + trifled trifl trifler trifler + trifles trifl trifling trifl + trigon trigon trill trill + trim trim trimly trimli + trimm trimm trimmed trim + trimming trim trims trim + trinculo trinculo trinculos trinculo + trinkets trinket trip trip + tripartite tripartit tripe tripe + triple tripl triplex triplex + tripoli tripoli tripolis tripoli + tripp tripp tripping trip + trippingly trippingli trips trip + tristful trist triton triton + triumph triumph triumphant triumphant + triumphantly triumphantli triumpher triumpher + triumphers triumpher triumphing triumph + triumphs triumph triumvir triumvir + triumvirate triumvir triumvirs triumvir + triumviry triumviri trivial trivial + troat troat trod trod + trodden trodden troiant troiant + troien troien troilus troilu + troiluses troilus trojan trojan + trojans trojan troll troll + tromperies tromperi trompet trompet + troop troop trooping troop + troops troop trop trop + trophies trophi trophy trophi + tropically tropic trot trot + troth troth trothed troth + troths troth trots trot + trotting trot trouble troubl + troubled troubl troubler troubler + troubles troubl troublesome troublesom + troublest troublest troublous troublou + trough trough trout trout + trouts trout trovato trovato + trow trow trowel trowel + trowest trowest troy troi + troyan troyan troyans troyan + truant truant truce truce + truckle truckl trudge trudg + true true trueborn trueborn + truepenny truepenni truer truer + truest truest truie truie + trull trull trulls trull + truly truli trump trump + trumpery trumperi trumpet trumpet + trumpeter trumpet trumpeters trumpet + trumpets trumpet truncheon truncheon + truncheoners truncheon trundle trundl + trunk trunk trunks trunk + trust trust trusted trust + truster truster trusters truster + trusting trust trusts trust + trusty trusti truth truth + truths truth try try + ts ts tu tu + tuae tuae tub tub + tubal tubal tubs tub + tuck tuck tucket tucket + tuesday tuesdai tuft tuft + tufts tuft tug tug + tugg tugg tugging tug + tuition tuition tullus tullu + tully tulli tumble tumbl + tumbled tumbl tumbler tumbler + tumbling tumbl tumult tumult + tumultuous tumultu tun tun + tune tune tuneable tuneabl + tuned tune tuners tuner + tunes tune tunis tuni + tuns tun tupping tup + turban turban turbans turban + turbulence turbul turbulent turbul + turd turd turf turf + turfy turfi turk turk + turkey turkei turkeys turkei + turkish turkish turks turk + turlygod turlygod turmoil turmoil + turmoiled turmoil turn turn + turnbull turnbul turncoat turncoat + turncoats turncoat turned turn + turneth turneth turning turn + turnips turnip turns turn + turph turph turpitude turpitud + turquoise turquois turret turret + turrets turret turtle turtl + turtles turtl turvy turvi + tuscan tuscan tush tush + tut tut tutor tutor + tutored tutor tutors tutor + tutto tutto twain twain + twang twang twangling twangl + twas twa tway twai + tweaks tweak tween tween + twelfth twelfth twelve twelv + twelvemonth twelvemonth twentieth twentieth + twenty twenti twere twere + twice twice twig twig + twiggen twiggen twigs twig + twilight twilight twill twill + twilled twill twin twin + twine twine twink twink + twinkle twinkl twinkled twinkl + twinkling twinkl twinn twinn + twins twin twire twire + twist twist twisted twist + twit twit twits twit + twitting twit twixt twixt + two two twofold twofold + twopence twopenc twopences twopenc + twos two twould twould + tyb tyb tybalt tybalt + tybalts tybalt tyburn tyburn + tying ty tyke tyke + tymbria tymbria type type + types type typhon typhon + tyrannical tyrann tyrannically tyrann + tyrannize tyrann tyrannous tyrann + tyranny tyranni tyrant tyrant + tyrants tyrant tyrian tyrian + tyrrel tyrrel u u + ubique ubiqu udders udder + udge udg uds ud + uglier uglier ugliest ugliest + ugly ugli ulcer ulcer + ulcerous ulcer ulysses ulyss + um um umber umber + umbra umbra umbrage umbrag + umfrevile umfrevil umpire umpir + umpires umpir un un + unable unabl unaccommodated unaccommod + unaccompanied unaccompani unaccustom unaccustom + unaching unach unacquainted unacquaint + unactive unact unadvis unadvi + unadvised unadvis unadvisedly unadvisedli + unagreeable unagre unanel unanel + unanswer unansw unappeas unappea + unapproved unapprov unapt unapt + unaptness unapt unarm unarm + unarmed unarm unarms unarm + unassail unassail unassailable unassail + unattainted unattaint unattempted unattempt + unattended unattend unauspicious unauspici + unauthorized unauthor unavoided unavoid + unawares unawar unback unback + unbak unbak unbanded unband + unbar unbar unbarb unbarb + unbashful unbash unbated unbat + unbatter unbatt unbecoming unbecom + unbefitting unbefit unbegot unbegot + unbegotten unbegotten unbelieved unbeliev + unbend unbend unbent unbent + unbewail unbewail unbid unbid + unbidden unbidden unbind unbind + unbinds unbind unbitted unbit + unbless unbless unblest unblest + unbloodied unbloodi unblown unblown + unbodied unbodi unbolt unbolt + unbolted unbolt unbonneted unbonnet + unbookish unbookish unborn unborn + unbosom unbosom unbound unbound + unbounded unbound unbow unbow + unbowed unbow unbrac unbrac + unbraced unbrac unbraided unbraid + unbreathed unbreath unbred unbr + unbreech unbreech unbridled unbridl + unbroke unbrok unbruis unbrui + unbruised unbruis unbuckle unbuckl + unbuckles unbuckl unbuckling unbuckl + unbuild unbuild unburden unburden + unburdens unburden unburied unburi + unburnt unburnt unburthen unburthen + unbutton unbutton unbuttoning unbutton + uncapable uncap uncape uncap + uncase uncas uncasing uncas + uncaught uncaught uncertain uncertain + uncertainty uncertainti unchain unchain + unchanging unchang uncharge uncharg + uncharged uncharg uncharitably uncharit + unchary unchari unchaste unchast + uncheck uncheck unchilded unchild + uncivil uncivil unclaim unclaim + unclasp unclasp uncle uncl + unclean unclean uncleanliness uncleanli + uncleanly uncleanli uncleanness unclean + uncles uncl unclew unclew + unclog unclog uncoined uncoin + uncolted uncolt uncomeliness uncomeli + uncomfortable uncomfort uncompassionate uncompassion + uncomprehensive uncomprehens unconfinable unconfin + unconfirm unconfirm unconfirmed unconfirm + unconquer unconqu unconquered unconqu + unconsidered unconsid unconstant unconst + unconstrain unconstrain unconstrained unconstrain + uncontemn uncontemn uncontroll uncontrol + uncorrected uncorrect uncounted uncount + uncouple uncoupl uncourteous uncourt + uncouth uncouth uncover uncov + uncovered uncov uncropped uncrop + uncross uncross uncrown uncrown + unction unction unctuous unctuou + uncuckolded uncuckold uncurable uncur + uncurbable uncurb uncurbed uncurb + uncurls uncurl uncurrent uncurr + uncurse uncurs undaunted undaunt + undeaf undeaf undeck undeck + undeeded undeed under under + underbearing underbear underborne underborn + undercrest undercrest underfoot underfoot + undergo undergo undergoes undergo + undergoing undergo undergone undergon + underground underground underhand underhand + underlings underl undermine undermin + underminers undermin underneath underneath + underprizing underpr underprop underprop + understand understand understandeth understandeth + understanding understand understandings understand + understands understand understood understood + underta underta undertake undertak + undertakeing undertak undertaker undertak + undertakes undertak undertaking undertak + undertakings undertak undertook undertook + undervalu undervalu undervalued undervalu + underwent underw underwrit underwrit + underwrite underwrit undescried undescri + undeserved undeserv undeserver undeserv + undeservers undeserv undeserving undeserv + undetermin undetermin undid undid + undinted undint undiscernible undiscern + undiscover undiscov undishonoured undishonour + undispos undispo undistinguishable undistinguish + undistinguished undistinguish undividable undivid + undivided undivid undivulged undivulg + undo undo undoes undo + undoing undo undone undon + undoubted undoubt undoubtedly undoubtedli + undream undream undress undress + undressed undress undrown undrown + unduteous undut undutiful unduti + une un uneared unear + unearned unearn unearthly unearthli + uneasines uneasin uneasy uneasi + uneath uneath uneducated uneduc + uneffectual uneffectu unelected unelect + unequal unequ uneven uneven + unexamin unexamin unexecuted unexecut + unexpected unexpect unexperienc unexperienc + unexperient unexperi unexpressive unexpress + unfair unfair unfaithful unfaith + unfallible unfal unfam unfam + unfashionable unfashion unfasten unfasten + unfather unfath unfathered unfath + unfed unf unfeed unfe + unfeeling unfeel unfeigned unfeign + unfeignedly unfeignedli unfellowed unfellow + unfelt unfelt unfenced unfenc + unfilial unfili unfill unfil + unfinish unfinish unfirm unfirm + unfit unfit unfitness unfit + unfix unfix unfledg unfledg + unfold unfold unfolded unfold + unfoldeth unfoldeth unfolding unfold + unfolds unfold unfool unfool + unforc unforc unforced unforc + unforfeited unforfeit unfortified unfortifi + unfortunate unfortun unfought unfought + unfrequented unfrequ unfriended unfriend + unfurnish unfurnish ungain ungain + ungalled ungal ungart ungart + ungarter ungart ungenitur ungenitur + ungentle ungentl ungentleness ungentl + ungently ungent ungird ungird + ungodly ungodli ungor ungor + ungot ungot ungotten ungotten + ungovern ungovern ungracious ungraci + ungrateful ungrat ungravely ungrav + ungrown ungrown unguarded unguard + unguem unguem unguided unguid + unhack unhack unhair unhair + unhallow unhallow unhallowed unhallow + unhand unhand unhandled unhandl + unhandsome unhandsom unhang unhang + unhappied unhappi unhappily unhappili + unhappiness unhappi unhappy unhappi + unhardened unharden unharm unharm + unhatch unhatch unheard unheard + unhearts unheart unheedful unheed + unheedfully unheedfulli unheedy unheedi + unhelpful unhelp unhidden unhidden + unholy unholi unhop unhop + unhopefullest unhopefullest unhorse unhors + unhospitable unhospit unhous unhou + unhoused unhous unhurtful unhurt + unicorn unicorn unicorns unicorn + unimproved unimprov uninhabitable uninhabit + uninhabited uninhabit unintelligent unintellig + union union unions union + unite unit united unit + unity uniti universal univers + universe univers universities univers + university univers unjointed unjoint + unjust unjust unjustice unjustic + unjustly unjustli unkennel unkennel + unkept unkept unkind unkind + unkindest unkindest unkindly unkindli + unkindness unkind unking unk + unkinglike unkinglik unkiss unkiss + unknit unknit unknowing unknow + unknown unknown unlace unlac + unlaid unlaid unlawful unlaw + unlawfully unlawfulli unlearn unlearn + unlearned unlearn unless unless + unlesson unlesson unletter unlett + unlettered unlett unlick unlick + unlike unlik unlikely unlik + unlimited unlimit unlineal unlin + unlink unlink unload unload + unloaded unload unloading unload + unloads unload unlock unlock + unlocks unlock unlook unlook + unlooked unlook unloos unloo + unloose unloos unlov unlov + unloving unlov unluckily unluckili + unlucky unlucki unmade unmad + unmake unmak unmanly unmanli + unmann unmann unmanner unmann + unmannerd unmannerd unmannerly unmannerli + unmarried unmarri unmask unmask + unmasked unmask unmasking unmask + unmasks unmask unmast unmast + unmatch unmatch unmatchable unmatch + unmatched unmatch unmeasurable unmeasur + unmeet unmeet unmellowed unmellow + unmerciful unmerci unmeritable unmerit + unmeriting unmerit unminded unmind + unmindfull unmindful unmingled unmingl + unmitigable unmitig unmitigated unmitig + unmix unmix unmoan unmoan + unmov unmov unmoved unmov + unmoving unmov unmuffles unmuffl + unmuffling unmuffl unmusical unmus + unmuzzle unmuzzl unmuzzled unmuzzl + unnatural unnatur unnaturally unnatur + unnaturalness unnatur unnecessarily unnecessarili + unnecessary unnecessari unneighbourly unneighbourli + unnerved unnerv unnoble unnobl + unnoted unnot unnumb unnumb + unnumber unnumb unowed unow + unpack unpack unpaid unpaid + unparagon unparagon unparallel unparallel + unpartial unparti unpath unpath + unpaved unpav unpay unpai + unpeaceable unpeac unpeg unpeg + unpeople unpeopl unpeopled unpeopl + unperfect unperfect unperfectness unperfect + unpick unpick unpin unpin + unpink unpink unpitied unpiti + unpitifully unpitifulli unplagu unplagu + unplausive unplaus unpleas unplea + unpleasant unpleas unpleasing unpleas + unpolicied unpolici unpolish unpolish + unpolished unpolish unpolluted unpollut + unpossess unpossess unpossessing unpossess + unpossible unposs unpractis unpracti + unpregnant unpregn unpremeditated unpremedit + unprepar unprepar unprepared unprepar + unpress unpress unprevailing unprevail + unprevented unprev unpriz unpriz + unprizable unpriz unprofitable unprofit + unprofited unprofit unproper unprop + unproperly unproperli unproportion unproport + unprovide unprovid unprovided unprovid + unprovident unprovid unprovokes unprovok + unprun unprun unpruned unprun + unpublish unpublish unpurged unpurg + unpurpos unpurpo unqualitied unqual + unqueen unqueen unquestion unquest + unquestionable unquestion unquiet unquiet + unquietly unquietli unquietness unquiet + unraised unrais unrak unrak + unread unread unready unreadi + unreal unreal unreasonable unreason + unreasonably unreason unreclaimed unreclaim + unreconciled unreconcil unreconciliable unreconcili + unrecounted unrecount unrecuring unrecur + unregarded unregard unregist unregist + unrelenting unrel unremovable unremov + unremovably unremov unreprievable unrepriev + unresolv unresolv unrespected unrespect + unrespective unrespect unrest unrest + unrestor unrestor unrestrained unrestrain + unreveng unreveng unreverend unreverend + unreverent unrever unrevers unrev + unrewarded unreward unrighteous unright + unrightful unright unripe unrip + unripp unripp unrivall unrival + unroll unrol unroof unroof + unroosted unroost unroot unroot + unrough unrough unruly unruli + unsafe unsaf unsaluted unsalut + unsanctified unsanctifi unsatisfied unsatisfi + unsavoury unsavouri unsay unsai + unscalable unscal unscann unscann + unscarr unscarr unschool unschool + unscorch unscorch unscour unscour + unscratch unscratch unseal unseal + unseam unseam unsearch unsearch + unseason unseason unseasonable unseason + unseasonably unseason unseasoned unseason + unseconded unsecond unsecret unsecret + unseduc unseduc unseeing unse + unseeming unseem unseemly unseemli + unseen unseen unseminar unseminar + unseparable unsepar unserviceable unservic + unset unset unsettle unsettl + unsettled unsettl unsever unsev + unsex unsex unshak unshak + unshaked unshak unshaken unshaken + unshaped unshap unshapes unshap + unsheath unsheath unsheathe unsheath + unshorn unshorn unshout unshout + unshown unshown unshrinking unshrink + unshrubb unshrubb unshunn unshunn + unshunnable unshunn unsifted unsift + unsightly unsightli unsinew unsinew + unsisting unsist unskilful unskil + unskilfully unskilfulli unskillful unskil + unslipping unslip unsmirched unsmirch + unsoil unsoil unsolicited unsolicit + unsorted unsort unsought unsought + unsound unsound unsounded unsound + unspeak unspeak unspeakable unspeak + unspeaking unspeak unsphere unspher + unspoke unspok unspoken unspoken + unspotted unspot unsquar unsquar + unstable unstabl unstaid unstaid + unstain unstain unstained unstain + unstanched unstanch unstate unstat + unsteadfast unsteadfast unstooping unstoop + unstringed unstring unstuff unstuff + unsubstantial unsubstanti unsuitable unsuit + unsuiting unsuit unsullied unsulli + unsunn unsunn unsur unsur + unsure unsur unsuspected unsuspect + unsway unswai unswayable unsway + unswayed unswai unswear unswear + unswept unswept unsworn unsworn + untainted untaint untalk untalk + untangle untangl untangled untangl + untasted untast untaught untaught + untempering untemp untender untend + untent untent untented untent + unthankful unthank unthankfulness unthank + unthink unthink unthought unthought + unthread unthread unthrift unthrift + unthrifts unthrift unthrifty unthrifti + untie unti untied unti + until until untimber untimb + untimely untim untir untir + untirable untir untired untir + untitled untitl unto unto + untold untold untouch untouch + untoward untoward untowardly untowardli + untraded untrad untrain untrain + untrained untrain untread untread + untreasur untreasur untried untri + untrimmed untrim untrod untrod + untrodden untrodden untroubled untroubl + untrue untru untrussing untruss + untruth untruth untruths untruth + untucked untuck untun untun + untune untun untuneable untun + untutor untutor untutored untutor + untwine untwin unurg unurg + unus unu unused unus + unusual unusu unvalued unvalu + unvanquish unvanquish unvarnish unvarnish + unveil unveil unveiling unveil + unvenerable unvener unvex unvex + unviolated unviol unvirtuous unvirtu + unvisited unvisit unvulnerable unvulner + unwares unwar unwarily unwarili + unwash unwash unwatch unwatch + unwearied unweari unwed unw + unwedgeable unwedg unweeded unweed + unweighed unweigh unweighing unweigh + unwelcome unwelcom unwept unwept + unwhipp unwhipp unwholesome unwholesom + unwieldy unwieldi unwilling unwil + unwillingly unwillingli unwillingness unwilling + unwind unwind unwiped unwip + unwise unwis unwisely unwis + unwish unwish unwished unwish + unwitted unwit unwittingly unwittingli + unwonted unwont unwooed unwoo + unworthier unworthi unworthiest unworthiest + unworthily unworthili unworthiness unworthi + unworthy unworthi unwrung unwrung + unyok unyok unyoke unyok + up up upbraid upbraid + upbraided upbraid upbraidings upbraid + upbraids upbraid uphoarded uphoard + uphold uphold upholdeth upholdeth + upholding uphold upholds uphold + uplift uplift uplifted uplift + upmost upmost upon upon + upper upper uprear uprear + upreared uprear upright upright + uprighteously upright uprightness upright + uprise upris uprising upris + uproar uproar uproars uproar + uprous uprou upshoot upshoot + upshot upshot upside upsid + upspring upspr upstairs upstair + upstart upstart upturned upturn + upward upward upwards upward + urchin urchin urchinfield urchinfield + urchins urchin urg urg + urge urg urged urg + urgent urgent urges urg + urgest urgest urging urg + urinal urin urinals urin + urine urin urn urn + urns urn urs ur + ursa ursa ursley urslei + ursula ursula urswick urswick + us us usage usag + usance usanc usances usanc + use us used us + useful us useless useless + user user uses us + usest usest useth useth + usher usher ushered usher + ushering usher ushers usher + using us usual usual + usually usual usurer usur + usurers usur usuries usuri + usuring usur usurp usurp + usurpation usurp usurped usurp + usurper usurp usurpers usurp + usurping usurp usurpingly usurpingli + usurps usurp usury usuri + ut ut utensil utensil + utensils utensil utility util + utmost utmost utt utt + utter utter utterance utter + uttered utter uttereth uttereth + uttering utter utterly utterli + uttermost uttermost utters utter + uy uy v v + va va vacancy vacanc + vacant vacant vacation vacat + vade vade vagabond vagabond + vagabonds vagabond vagram vagram + vagrom vagrom vail vail + vailed vail vailing vail + vaillant vaillant vain vain + vainer vainer vainglory vainglori + vainly vainli vainness vain + vais vai valanc valanc + valance valanc vale vale + valence valenc valentine valentin + valentinus valentinu valentio valentio + valeria valeria valerius valeriu + vales vale valiant valiant + valiantly valiantli valiantness valiant + validity valid vallant vallant + valley vallei valleys vallei + vally valli valor valor + valorous valor valorously valor + valour valour valu valu + valuation valuat value valu + valued valu valueless valueless + values valu valuing valu + vane vane vanish vanish + vanished vanish vanishes vanish + vanishest vanishest vanishing vanish + vanities vaniti vanity vaniti + vanquish vanquish vanquished vanquish + vanquisher vanquish vanquishest vanquishest + vanquisheth vanquisheth vant vant + vantage vantag vantages vantag + vantbrace vantbrac vapians vapian + vapor vapor vaporous vapor + vapour vapour vapours vapour + vara vara variable variabl + variance varianc variation variat + variations variat varied vari + variest variest variety varieti + varld varld varlet varlet + varletry varletri varlets varlet + varletto varletto varnish varnish + varrius varriu varro varro + vary vari varying vari + vassal vassal vassalage vassalag + vassals vassal vast vast + vastidity vastid vasty vasti + vat vat vater vater + vaudemont vaudemont vaughan vaughan + vault vault vaultages vaultag + vaulted vault vaulting vault + vaults vault vaulty vaulti + vaumond vaumond vaunt vaunt + vaunted vaunt vaunter vaunter + vaunting vaunt vauntingly vauntingli + vaunts vaunt vauvado vauvado + vaux vaux vaward vaward + ve ve veal veal + vede vede vehemence vehem + vehemency vehem vehement vehement + vehor vehor veil veil + veiled veil veiling veil + vein vein veins vein + vell vell velure velur + velutus velutu velvet velvet + vendible vendibl venerable vener + venereal vener venetia venetia + venetian venetian venetians venetian + veneys venei venge veng + vengeance vengeanc vengeances vengeanc + vengeful veng veni veni + venial venial venice venic + venison venison venit venit + venom venom venomous venom + venomously venom vent vent + ventages ventag vented vent + ventidius ventidiu ventricle ventricl + vents vent ventur ventur + venture ventur ventured ventur + ventures ventur venturing ventur + venturous ventur venue venu + venus venu venuto venuto + ver ver verb verb + verba verba verbal verbal + verbatim verbatim verbosity verbos + verdict verdict verdun verdun + verdure verdur vere vere + verefore verefor verg verg + verge verg vergers verger + verges verg verier verier + veriest veriest verified verifi + verify verifi verily verili + veritable verit verite verit + verities veriti verity veriti + vermilion vermilion vermin vermin + vernon vernon verona verona + veronesa veronesa versal versal + verse vers verses vers + versing vers vert vert + very veri vesper vesper + vessel vessel vessels vessel + vestal vestal vestments vestment + vesture vestur vetch vetch + vetches vetch veux veux + vex vex vexation vexat + vexations vexat vexed vex + vexes vex vexest vexest + vexeth vexeth vexing vex + vi vi via via + vial vial vials vial + viand viand viands viand + vic vic vicar vicar + vice vice vicegerent viceger + vicentio vicentio viceroy viceroi + viceroys viceroi vices vice + vici vici vicious viciou + viciousness vicious vict vict + victims victim victor victor + victoress victoress victories victori + victorious victori victors victor + victory victori victual victual + victuall victual victuals victual + videlicet videlicet video video + vides vide videsne videsn + vidi vidi vie vie + vied vi vienna vienna + view view viewest viewest + vieweth vieweth viewing view + viewless viewless views view + vigil vigil vigilance vigil + vigilant vigil vigitant vigit + vigour vigour vii vii + viii viii vile vile + vilely vile vileness vile + viler viler vilest vilest + vill vill village villag + villager villag villagery villageri + villages villag villain villain + villainies villaini villainous villain + villainously villain villains villain + villainy villaini villanies villani + villanous villan villany villani + villiago villiago villian villian + villianda villianda villians villian + vinaigre vinaigr vincentio vincentio + vincere vincer vindicative vindic + vine vine vinegar vinegar + vines vine vineyard vineyard + vineyards vineyard vint vint + vintner vintner viol viol + viola viola violate violat + violated violat violates violat + violation violat violator violat + violence violenc violent violent + violenta violenta violenteth violenteth + violently violent violet violet + violets violet viper viper + viperous viper vipers viper + vir vir virgilia virgilia + virgin virgin virginal virgin + virginalling virginal virginity virgin + virginius virginiu virgins virgin + virgo virgo virtue virtu + virtues virtu virtuous virtuou + virtuously virtuous visag visag + visage visag visages visag + visard visard viscount viscount + visible visibl visibly visibl + vision vision visions vision + visit visit visitation visit + visitations visit visited visit + visiting visit visitings visit + visitor visitor visitors visitor + visits visit visor visor + vita vita vitae vita + vital vital vitement vitement + vitruvio vitruvio vitx vitx + viva viva vivant vivant + vive vive vixen vixen + viz viz vizaments vizament + vizard vizard vizarded vizard + vizards vizard vizor vizor + vlouting vlout vocation vocat + vocativo vocativo vocatur vocatur + voce voce voic voic + voice voic voices voic + void void voided void + voiding void voke voke + volable volabl volant volant + volivorco volivorco volley vollei + volquessen volquessen volsce volsc + volsces volsc volscian volscian + volscians volscian volt volt + voltemand voltemand volubility volubl + voluble volubl volume volum + volumes volum volumnia volumnia + volumnius volumniu voluntaries voluntari + voluntary voluntari voluptuously voluptu + voluptuousness voluptu vomissement vomiss + vomit vomit vomits vomit + vor vor vore vore + vortnight vortnight vot vot + votaries votari votarist votarist + votarists votarist votary votari + votre votr vouch vouch + voucher voucher vouchers voucher + vouches vouch vouching vouch + vouchsaf vouchsaf vouchsafe vouchsaf + vouchsafed vouchsaf vouchsafes vouchsaf + vouchsafing vouchsaf voudrais voudrai + vour vour vous vou + voutsafe voutsaf vow vow + vowed vow vowel vowel + vowels vowel vowing vow + vows vow vox vox + voyage voyag voyages voyag + vraiment vraiment vulcan vulcan + vulgar vulgar vulgarly vulgarli + vulgars vulgar vulgo vulgo + vulnerable vulner vulture vultur + vultures vultur vurther vurther + w w wad wad + waddled waddl wade wade + waded wade wafer wafer + waft waft waftage waftag + wafting waft wafts waft + wag wag wage wage + wager wager wagers wager + wages wage wagging wag + waggish waggish waggling waggl + waggon waggon waggoner waggon + wagon wagon wagoner wagon + wags wag wagtail wagtail + wail wail wailful wail + wailing wail wails wail + wain wain wainropes wainrop + wainscot wainscot waist waist + wait wait waited wait + waiter waiter waiteth waiteth + waiting wait waits wait + wak wak wake wake + waked wake wakefield wakefield + waken waken wakened waken + wakes wake wakest wakest + waking wake wales wale + walk walk walked walk + walking walk walks walk + wall wall walled wall + wallet wallet wallets wallet + wallon wallon walloon walloon + wallow wallow walls wall + walnut walnut walter walter + wan wan wand wand + wander wander wanderer wander + wanderers wander wandering wander + wanders wander wands wand + wane wane waned wane + wanes wane waning wane + wann wann want want + wanted want wanteth wanteth + wanting want wanton wanton + wantonly wantonli wantonness wanton + wantons wanton wants want + wappen wappen war war + warble warbl warbling warbl + ward ward warded ward + warden warden warder warder + warders warder wardrobe wardrob + wardrop wardrop wards ward + ware ware wares ware + warily warili warkworth warkworth + warlike warlik warm warm + warmed warm warmer warmer + warming warm warms warm + warmth warmth warn warn + warned warn warning warn + warnings warn warns warn + warp warp warped warp + warr warr warrant warrant + warranted warrant warranteth warranteth + warrantise warrantis warrantize warrant + warrants warrant warranty warranti + warren warren warrener warren + warring war warrior warrior + warriors warrior wars war + wart wart warwick warwick + warwickshire warwickshir wary wari + was wa wash wash + washed wash washer washer + washes wash washford washford + washing wash wasp wasp + waspish waspish wasps wasp + wassail wassail wassails wassail + wast wast waste wast + wasted wast wasteful wast + wasters waster wastes wast + wasting wast wat wat + watch watch watched watch + watchers watcher watches watch + watchful watch watching watch + watchings watch watchman watchman + watchmen watchmen watchword watchword + water water waterdrops waterdrop + watered water waterfly waterfli + waterford waterford watering water + waterish waterish waterpots waterpot + waterrugs waterrug waters water + waterton waterton watery wateri + wav wav wave wave + waved wave waver waver + waverer waver wavering waver + waves wave waving wave + waw waw wawl wawl + wax wax waxed wax + waxen waxen waxes wax + waxing wax way wai + waylaid waylaid waylay waylai + ways wai wayward wayward + waywarder wayward waywardness wayward + we we weak weak + weaken weaken weakens weaken + weaker weaker weakest weakest + weakling weakl weakly weakli + weakness weak weal weal + wealsmen wealsmen wealth wealth + wealthiest wealthiest wealthily wealthili + wealthy wealthi wealtlly wealtlli + wean wean weapon weapon + weapons weapon wear wear + wearer wearer wearers wearer + wearied weari wearies weari + weariest weariest wearily wearili + weariness weari wearing wear + wearisome wearisom wears wear + weary weari weasel weasel + weather weather weathercock weathercock + weathers weather weav weav + weave weav weaver weaver + weavers weaver weaves weav + weaving weav web web + wed wed wedded wed + wedding wed wedg wedg + wedged wedg wedges wedg + wedlock wedlock wednesday wednesdai + weed weed weeded weed + weeder weeder weeding weed + weeds weed weedy weedi + week week weeke week + weekly weekli weeks week + ween ween weening ween + weep weep weeper weeper + weeping weep weepingly weepingli + weepings weep weeps weep + weet weet weigh weigh + weighed weigh weighing weigh + weighs weigh weight weight + weightier weightier weightless weightless + weights weight weighty weighti + weird weird welcom welcom + welcome welcom welcomer welcom + welcomes welcom welcomest welcomest + welfare welfar welkin welkin + well well wells well + welsh welsh welshman welshman + welshmen welshmen welshwomen welshwomen + wench wench wenches wench + wenching wench wend wend + went went wept wept + weraday weradai were were + wert wert west west + western western westminster westminst + westmoreland westmoreland westward westward + wet wet wether wether + wetting wet wezand wezand + whale whale whales whale + wharf wharf wharfs wharf + what what whate whate + whatever whatev whatsoe whatso + whatsoever whatsoev whatsome whatsom + whe whe wheat wheat + wheaten wheaten wheel wheel + wheeling wheel wheels wheel + wheer wheer wheeson wheeson + wheezing wheez whelk whelk + whelks whelk whelm whelm + whelp whelp whelped whelp + whelps whelp when when + whenas whena whence whenc + whencesoever whencesoev whene whene + whenever whenev whensoever whensoev + where where whereabout whereabout + whereas wherea whereat whereat + whereby wherebi wherefore wherefor + wherein wherein whereinto whereinto + whereof whereof whereon whereon + whereout whereout whereso whereso + wheresoe whereso wheresoever wheresoev + wheresome wheresom whereto whereto + whereuntil whereuntil whereunto whereunto + whereupon whereupon wherever wherev + wherewith wherewith wherewithal wherewith + whet whet whether whether + whetstone whetston whetted whet + whew whew whey whei + which which whiff whiff + whiffler whiffler while while + whiles while whilst whilst + whin whin whine whine + whined whine whinid whinid + whining whine whip whip + whipp whipp whippers whipper + whipping whip whips whip + whipster whipster whipstock whipstock + whipt whipt whirl whirl + whirled whirl whirligig whirligig + whirling whirl whirlpool whirlpool + whirls whirl whirlwind whirlwind + whirlwinds whirlwind whisp whisp + whisper whisper whispering whisper + whisperings whisper whispers whisper + whist whist whistle whistl + whistles whistl whistling whistl + whit whit white white + whitehall whitehal whitely white + whiteness white whiter whiter + whites white whitest whitest + whither whither whiting white + whitmore whitmor whitsters whitster + whitsun whitsun whittle whittl + whizzing whizz who who + whoa whoa whoe whoe + whoever whoever whole whole + wholesom wholesom wholesome wholesom + wholly wholli whom whom + whoobub whoobub whoop whoop + whooping whoop whor whor + whore whore whoremaster whoremast + whoremasterly whoremasterli whoremonger whoremong + whores whore whoreson whoreson + whoresons whoreson whoring whore + whorish whorish whose whose + whoso whoso whosoe whoso + whosoever whosoev why why + wi wi wick wick + wicked wick wickednes wickedn + wickedness wicked wicket wicket + wicky wicki wid wid + wide wide widens widen + wider wider widow widow + widowed widow widower widow + widowhood widowhood widows widow + wield wield wife wife + wight wight wights wight + wild wild wildcats wildcat + wilder wilder wilderness wilder + wildest wildest wildfire wildfir + wildly wildli wildness wild + wilds wild wiles wile + wilful wil wilfull wilful + wilfully wilfulli wilfulnes wilfuln + wilfulness wil will will + willed will willers willer + willeth willeth william william + williams william willing will + willingly willingli willingness willing + willoughby willoughbi willow willow + wills will wilt wilt + wiltshire wiltshir wimpled wimpl + win win wince winc + winch winch winchester winchest + wincot wincot wind wind + winded wind windgalls windgal + winding wind windlasses windlass + windmill windmil window window + windows window windpipe windpip + winds wind windsor windsor + windy windi wine wine + wing wing winged wing + wingfield wingfield wingham wingham + wings wing wink wink + winking wink winks wink + winner winner winners winner + winning win winnow winnow + winnowed winnow winnows winnow + wins win winter winter + winterly winterli winters winter + wip wip wipe wipe + wiped wipe wipes wipe + wiping wipe wire wire + wires wire wiry wiri + wisdom wisdom wisdoms wisdom + wise wise wiselier wiseli + wisely wise wiser wiser + wisest wisest wish wish + wished wish wisher wisher + wishers wisher wishes wish + wishest wishest wisheth wisheth + wishful wish wishing wish + wishtly wishtli wisp wisp + wist wist wit wit + witb witb witch witch + witchcraft witchcraft witches witch + witching witch with with + withal withal withdraw withdraw + withdrawing withdraw withdrawn withdrawn + withdrew withdrew wither wither + withered wither withering wither + withers wither withheld withheld + withhold withhold withholds withhold + within within withold withold + without without withstand withstand + withstanding withstand withstood withstood + witless witless witness wit + witnesses wit witnesseth witnesseth + witnessing wit wits wit + witted wit wittenberg wittenberg + wittiest wittiest wittily wittili + witting wit wittingly wittingli + wittol wittol wittolly wittolli + witty witti wiv wiv + wive wive wived wive + wives wive wiving wive + wizard wizard wizards wizard + wo wo woe woe + woeful woeful woefull woeful + woefullest woefullest woes woe + woful woful wolf wolf + wolfish wolfish wolsey wolsei + wolves wolv wolvish wolvish + woman woman womanhood womanhood + womanish womanish womankind womankind + womanly womanli womb womb + wombs womb womby wombi + women women won won + woncot woncot wond wond + wonder wonder wondered wonder + wonderful wonder wonderfully wonderfulli + wondering wonder wonders wonder + wondrous wondrou wondrously wondrous + wont wont wonted wont + woo woo wood wood + woodbine woodbin woodcock woodcock + woodcocks woodcock wooden wooden + woodland woodland woodman woodman + woodmonger woodmong woods wood + woodstock woodstock woodville woodvil + wooed woo wooer wooer + wooers wooer wooes wooe + woof woof wooing woo + wooingly wooingli wool wool + woollen woollen woolly woolli + woolsack woolsack woolsey woolsei + woolward woolward woos woo + wor wor worcester worcest + word word words word + wore wore worins worin + work work workers worker + working work workings work + workman workman workmanly workmanli + workmanship workmanship workmen workmen + works work worky worki + world world worldlings worldl + worldly worldli worlds world + worm worm worms worm + wormwood wormwood wormy wormi + worn worn worried worri + worries worri worry worri + worrying worri worse wors + worser worser worship worship + worshipful worship worshipfully worshipfulli + worshipp worshipp worshipper worshipp + worshippers worshipp worshippest worshippest + worships worship worst worst + worsted worst wort wort + worth worth worthied worthi + worthier worthier worthies worthi + worthiest worthiest worthily worthili + worthiness worthi worthless worthless + worths worth worthy worthi + worts wort wot wot + wots wot wotting wot + wouid wouid would would + wouldest wouldest wouldst wouldst + wound wound wounded wound + wounding wound woundings wound + woundless woundless wounds wound + wouns woun woven woven + wow wow wrack wrack + wrackful wrack wrangle wrangl + wrangler wrangler wranglers wrangler + wrangling wrangl wrap wrap + wrapp wrapp wraps wrap + wrapt wrapt wrath wrath + wrathful wrath wrathfully wrathfulli + wraths wrath wreak wreak + wreakful wreak wreaks wreak + wreath wreath wreathed wreath + wreathen wreathen wreaths wreath + wreck wreck wrecked wreck + wrecks wreck wren wren + wrench wrench wrenching wrench + wrens wren wrest wrest + wrested wrest wresting wrest + wrestle wrestl wrestled wrestl + wrestler wrestler wrestling wrestl + wretch wretch wretchcd wretchcd + wretched wretch wretchedness wretched + wretches wretch wring wring + wringer wringer wringing wring + wrings wring wrinkle wrinkl + wrinkled wrinkl wrinkles wrinkl + wrist wrist wrists wrist + writ writ write write + writer writer writers writer + writes write writhled writhl + writing write writings write + writs writ written written + wrong wrong wronged wrong + wronger wronger wrongful wrong + wrongfully wrongfulli wronging wrong + wrongly wrongli wrongs wrong + wronk wronk wrote wrote + wroth wroth wrought wrought + wrung wrung wry wry + wrying wry wt wt + wul wul wye wye + x x xanthippe xanthipp + xi xi xii xii + xiii xiii xiv xiv + xv xv y y + yard yard yards yard + yare yare yarely yare + yarn yarn yaughan yaughan + yaw yaw yawn yawn + yawning yawn ycleped yclepe + ycliped yclipe ye ye + yea yea yead yead + year year yearly yearli + yearn yearn yearns yearn + years year yeas yea + yeast yeast yedward yedward + yell yell yellow yellow + yellowed yellow yellowing yellow + yellowness yellow yellows yellow + yells yell yelping yelp + yeoman yeoman yeomen yeomen + yerk yerk yes ye + yesterday yesterdai yesterdays yesterdai + yesternight yesternight yesty yesti + yet yet yew yew + yicld yicld yield yield + yielded yield yielder yielder + yielders yielder yielding yield + yields yield yok yok + yoke yoke yoked yoke + yokefellow yokefellow yokes yoke + yoketh yoketh yon yon + yond yond yonder yonder + yongrey yongrei yore yore + yorick yorick york york + yorkists yorkist yorks york + yorkshire yorkshir you you + young young younger younger + youngest youngest youngling youngl + younglings youngl youngly youngli + younker younker your your + yours your yourself yourself + yourselves yourselv youth youth + youthful youth youths youth + youtli youtli zanies zani + zany zani zeal zeal + zealous zealou zeals zeal + zed zed zenelophon zenelophon + zenith zenith zephyrs zephyr + zir zir zo zo + zodiac zodiac zodiacs zodiac + zone zone zounds zound + zwagger zwagger +} + + +set i 0 +foreach {in out} $test_vocab { + do_test "1.$i.($in -> $out)" { + lindex [sqlite3_fts5_tokenize db porter $in] 0 + } $out + incr i +} + + +finish_test + diff --git a/ext/fts5/test/fts5porter2.test b/ext/fts5/test/fts5porter2.test new file mode 100644 index 0000000..5e0aeb0 --- /dev/null +++ b/ext/fts5/test/fts5porter2.test @@ -0,0 +1,70 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on the fts5 porter stemmer implementation. +# +# These are extra tests added to those in fts5porter.test in order to +# improve test coverage of the porter stemmer implementation. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5porter2 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +set test_vocab { + tion tion + ation ation + vation vation + avation avat + vion vion + ion ion + relational relat + relation relat + relate relat + zzz zzz + ii ii + iiing ii + xtional xtional + xenci xenci + xlogi xlogi + realization realiz + realize realiz + xization xizat + capitalism capit + talism talism + xiveness xive + xfulness xful + xousness xous + xical xical + xicate xicat + xicity xiciti + ies ie + eed e + eing e + s s +} + +set i 0 +foreach {in out} $test_vocab { + do_test "1.$i.($in -> $out)" { + lindex [sqlite3_fts5_tokenize db porter $in] 0 + } $out + incr i +} + + +finish_test + diff --git a/ext/fts5/test/fts5prefix.test b/ext/fts5/test/fts5prefix.test new file mode 100644 index 0000000..8e0d5a2 --- /dev/null +++ b/ext/fts5/test/fts5prefix.test @@ -0,0 +1,345 @@ +# 2015 Jan 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 file containst tests focused on prefix indexes. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5prefix + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE xx USING fts5(x, prefix=1); + INSERT INTO xx VALUES('one two three'); + INSERT INTO xx VALUES('four five six'); + INSERT INTO xx VALUES('seven eight nine ten'); +} + +do_execsql_test 1.1 { + SELECT rowid FROM xx WHERE xx MATCH 't*' +} {1 3} + + +#------------------------------------------------------------------------- +# Check that prefix indexes really do index n-character prefixes, not +# n-byte prefixes. Use the ascii tokenizer so as not to be confused by +# diacritic removal. +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = ascii, prefix = 2) +} + +do_test 2.1 { + foreach {rowid string} { + 1 "\xCA\xCB\xCC\xCD" + 2 "\u1234\u5678\u4321\u8765" + } { + execsql { INSERT INTO t1(rowid, x) VALUES($rowid, $string) } + } +} {} + +do_execsql_test 2.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +foreach {tn q res} { + 1 "SELECT rowid FROM t1 WHERE t1 MATCH '\xCA\xCB*'" 1 + 2 "SELECT rowid FROM t1 WHERE t1 MATCH '\u1234\u5678*'" 2 +} { + do_execsql_test 2.3.$tn $q $res +} + +#------------------------------------------------------------------------- +# Check that prefix queries with: +# +# * a column filter, and +# * no prefix index. +# +# work Ok. +# +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t3 USING fts5(a, b, c); + INSERT INTO t3(t3, rank) VALUES('pgsz', 32); + BEGIN; + INSERT INTO t3 VALUES('acb ccc bba', 'cca bba bca', 'bbc ccc bca'); -- 1 + INSERT INTO t3 VALUES('cbb cac cab', 'abb aac bba', 'aab ccc cac'); -- 2 + INSERT INTO t3 VALUES('aac bcb aac', 'acb bcb caa', 'aca bab bca'); -- 3 + INSERT INTO t3 VALUES('aab ccb ccc', 'aca cba cca', 'aca aac cbb'); -- 4 + INSERT INTO t3 VALUES('bac aab bab', 'ccb bac cba', 'acb aba abb'); -- 5 + INSERT INTO t3 VALUES('bab abc ccb', 'acb cba abb', 'cbb aaa cab'); -- 6 + INSERT INTO t3 VALUES('cbb bbc baa', 'aab aca baa', 'bcc cca aca'); -- 7 + INSERT INTO t3 VALUES('abc bba abb', 'cac abc cba', 'acc aac cac'); -- 8 + INSERT INTO t3 VALUES('bbc bbc cab', 'bcb ccb cba', 'bcc cac acb'); -- 9 + COMMIT; +} + +foreach {tn match res} { + 1 "a : c*" {1 2 4 6 7 9} + 2 "b : c*" {1 3 4 5 6 8 9} + 3 "c : c*" {1 2 4 6 7 8 9} + 4 "a : b*" {1 3 5 6 7 8 9} + 5 "b : b*" {1 2 3 5 7 9} + 6 "c : b*" {1 3 7 9} + 7 "a : a*" {1 3 4 5 6 8} + 8 "b : a*" {2 3 4 6 7 8} + 9 "c : a*" {2 3 4 5 6 7 8 9} +} { + do_execsql_test 3.1.$tn { + SELECT rowid FROM t3($match) + } $res +} + +do_test 3.2 { + expr srand(0) + execsql { DELETE FROM t3 } + for {set i 0} {$i < 1000} {incr i} { + set a [fts5_rnddoc 3] + set b [fts5_rnddoc 8] + set c [fts5_rnddoc 20] + execsql { INSERT INTO t3 VALUES($a, $b, $c) } + } + execsql { INSERT INTO t3(t3) VALUES('integrity-check') } +} {} + +proc gmatch {col pattern} { + expr {[lsearch -glob $col $pattern]>=0} +} +db func gmatch gmatch + +proc ghl {col pattern} { + foreach t $col { + if {[string match $pattern $t]} { + lappend res "*$t*" + } else { + lappend res $t + } + } + set res +} +db func ghl ghl + +set COLS(a) 0 +set COLS(b) 1 +set COLS(c) 2 + +for {set x 0} {$x<2} {incr x} { + foreach {tn pattern} { + 1 {xa*} + 2 {xb*} + 3 {xc*} + 4 {xd*} + 5 {xe*} + 6 {xf*} + 7 {xg*} + 8 {xh*} + 9 {xi*} + 10 {xj*} + } { + foreach col {a b c} { + + # Check that the list of returned rowids is correct. + # + set res [db eval "SELECT rowid FROM t3 WHERE gmatch($col, '$pattern')"] + set query "$col : $pattern" + do_execsql_test 3.3.$x.$tn.$col.rowid { + SELECT rowid FROM t3($query); + } $res + + # Check that the highlight() function works. + # + set res [db eval \ + "SELECT ghl($col, '$pattern') FROM t3 WHERE gmatch($col, '$pattern')" + ] + set idx $COLS($col) + do_execsql_test 3.3.$x.$tn.$col.highlight { + SELECT highlight(t3, $idx, '*', '*') FROM t3($query); + } $res + } + + foreach colset {{a b} {b c} {c a} {a c} {b a}} { + # Check that the list of returned rowids is correct. + # + foreach {col1 col2} $colset {} + set expr "gmatch($col1, '$pattern') OR gmatch($col2, '$pattern')" + set res [db eval "SELECT rowid FROM t3 WHERE $expr"] + set query "{$colset} : $pattern" + do_execsql_test 3.3.$x.$tn.{$colset}.rowid { + SELECT rowid FROM t3($query); + } $res + + set resq "SELECT ghl($col1, '$pattern'), ghl($col2, '$pattern')" + append resq " FROM t3 WHERE $expr" + set res [db eval $resq] + set idx1 $COLS($col1) + set idx2 $COLS($col2) + do_execsql_test 3.3.$x.$tn.{$colset}.highlight { + SELECT highlight(t3, $idx1, '*', '*'), highlight(t3, $idx2, '*', '*') + FROM t3($query) + } $res + } + } + execsql { INSERT INTO t3(t3) VALUES('optimize') } + execsql { INSERT INTO t3(t3) VALUES('integrity-check') } +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE t2 USING fts5(c1, c2); + INSERT INTO t2 VALUES('xa xb', 'xb xa'); + + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 2 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 4 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 8 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 16 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 32 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 64 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 128 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 256 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 512 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 1024 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 2048 + INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 4096 + + SELECT count(*) FROM t2('x*'); +} {4096} + +do_execsql_test 4.1 { + UPDATE t2 SET c2 = 'ya yb'; + SELECT count(*) FROM t2('c1:x*'); + SELECT count(*) FROM t2('c2:x*'); +} {4096 0} + +do_execsql_test 4.2 { + UPDATE t2 SET c2 = 'xa'; + SELECT count(*) FROM t2('c1:x*'); + SELECT count(*) FROM t2('c2:x*'); +} {4096 4096} + +#------------------------------------------------------------------------- +# +reset_db +proc rnddoc {n} { + set map [list a b c d] + set doc [list] + for {set i 0} {$i < $n} {incr i} { + lappend doc "x[lindex $map [expr int(rand()*4)]]" + } + set doc +} +set cols [list] +for {set i 1} {$i<250} {incr i} { + lappend cols "c$i" + lappend vals "'[rnddoc 10]'" +} + +do_test 5.0 { + execsql "CREATE VIRTUAL TABLE t4 USING fts5([join $cols ,])" + execsql {INSERT INTO t4(t4, rank) VALUES('pgsz', 32)} + execsql "INSERT INTO t4 VALUES([join $vals ,])" + execsql "INSERT INTO t4 VALUES([join $vals ,])" + execsql "INSERT INTO t4 VALUES([join $vals ,])" + execsql "INSERT INTO t4 VALUES([join $vals ,])" +} {} + +proc gmatch {col pattern} { + expr {[lsearch -glob $col $pattern]>=0} +} +db func gmatch gmatch +foreach {tn col pattern} { + 1 c100 {xa*} + 2 c200 {xb*} +} { + set res [db eval "SELECT rowid FROM t4 WHERE gmatch($col, \$pattern)"] + set query "$col : $pattern" + do_execsql_test 5.$tn { SELECT rowid FROM t4($query) } $res +} + +reset_db +db func fts5_rnddoc fts5_rnddoc +do_test 6.0 { + execsql { + CREATE VIRTUAL TABLE t5 USING fts5(x, y); + INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) ); + INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) ); + INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) ); + INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) ); + } +} {} + +proc gmatch {col pattern} { + expr {[lsearch -glob $col $pattern]>=0} +} +db func gmatch gmatch +foreach {tn col pattern} { + 1 y {xa*} + 2 y {xb*} + 3 y {xc*} + 4 x {xa*} + 5 x {xb*} + 6 x {xc*} +} { + set res [db eval "SELECT rowid FROM t5 WHERE gmatch($col, \$pattern)"] + set query "$col : $pattern" + do_execsql_test 6.$tn { SELECT rowid FROM t5($query) } $res +} + +#------------------------------------------------------------------------- +# Check that the various ways of creating prefix indexes produce the +# same database on disk. +# +save_prng_state +foreach {tn create} { + 1 { CREATE VIRTUAL TABLE tt USING fts5(x, y, prefix="1,2,3") } + 2 { CREATE VIRTUAL TABLE tt USING fts5(x, y, prefix="1 2 3") } + 3 { CREATE VIRTUAL TABLE tt USING fts5(x, y, prefix=1, prefix=2, prefix=3) } + 4 { CREATE VIRTUAL TABLE tt USING fts5(x, y, prefix="1 2", prefix=3) } +} { + execsql { DROP TABLE IF EXISTS tt } + restore_prng_state + execsql $create + execsql { + INSERT INTO tt VALUES('cc b ggg ccc aa eee hh', 'aa g b hh a e'); + INSERT INTO tt VALUES('cc bb cc gg j g cc', 'ii jjj ggg jjj cc cc'); + INSERT INTO tt VALUES('h eee cc h iii', 'aaa iii dd iii dd'); + INSERT INTO tt VALUES('jjj hh eee c e b gg', 'j bbb jj ddd jj'); + INSERT INTO tt VALUES('ii hhh aaa ff c hhh iii', 'j cc hh bb e'); + INSERT INTO tt VALUES('e fff hhh i aaa', 'g b aa gg c aa dd'); + INSERT INTO tt VALUES('i aaa ccc gg hhh aa h', 'j bbb bbb d ff'); + INSERT INTO tt VALUES('g f gg ff ff jjj d', 'jjj d j fff fff ee j'); + INSERT INTO tt VALUES('a cc e ccc jjj c', 'ccc iii d bb a eee g'); + INSERT INTO tt VALUES('jj hh hh bb bbb gg', 'j c jjj bb iii f'); + INSERT INTO tt VALUES('a ggg g cc ccc aa', 'jjj j j aaa c'); + INSERT INTO tt VALUES('ddd j dd b i', 'aaa bbb iii ggg ff ccc ddd'); + INSERT INTO tt VALUES('jj ii hh c ii h gg', 'hhh bbb ddd bbb hh g ggg'); + INSERT INTO tt VALUES('aa hhh ccc h ggg ccc', 'iii d jj a ff ii'); + } + + #db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM tt_data} {puts $r} + + if {$tn==1} { + set ::checksum [execsql {SELECT md5sum(id, block) FROM tt_data}] + } else { + do_execsql_test 7.$tn { + SELECT md5sum(id, block) FROM tt_data + } [list $::checksum] + } +} + +finish_test + + diff --git a/ext/fts5/test/fts5query.test b/ext/fts5/test/fts5query.test new file mode 100644 index 0000000..570abf4 --- /dev/null +++ b/ext/fts5/test/fts5query.test @@ -0,0 +1,83 @@ +# 2015 October 27 +# +# 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 fts5query + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} { + reset_db + do_test 1.$tn.1 { + execsql { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz); + BEGIN; + } + foreach x [list aaa bbb ccc ddd eee fff ggg hhh iii jjj] { + set doc [string repeat "$x " 30] + execsql { INSERT INTO t1 VALUES($doc) } + } + execsql COMMIT + } {} + + do_execsql_test 1.$tn.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); + } + + set ret 1 + foreach x [list a b c d e f g h i j] { + do_execsql_test 1.$tn.3.$ret { + SELECT rowid FROM t1 WHERE t1 MATCH $x || '*'; + } $ret + incr ret + } +} + +for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} { + reset_db + do_test 2.$tn.1 { + execsql { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz); + BEGIN; + } + foreach x [list bbb ddd fff hhh jjj lll nnn ppp rrr ttt] { + set doc [string repeat "$x " 30] + execsql { INSERT INTO t1 VALUES($doc) } + } + execsql COMMIT + } {} + + do_execsql_test 1.$tn.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); + } + + set ret 1 + foreach x [list a c e g i k m o q s u] { + do_execsql_test 2.$tn.3.$ret { + SELECT rowid FROM t1 WHERE t1 MATCH $x || '*'; + } {} + incr ret + } +} + + +finish_test + + diff --git a/ext/fts5/test/fts5rank.test b/ext/fts5/test/fts5rank.test new file mode 100644 index 0000000..4961b42 --- /dev/null +++ b/ext/fts5/test/fts5rank.test @@ -0,0 +1,100 @@ +# 2014 Dec 20 +# +# 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 focuses on testing queries that use the "rank" column. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5rank + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + + +#------------------------------------------------------------------------- +# "ORDER BY rank" + highlight() + large poslists. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE xyz USING fts5(z); +} +do_test 1.1 { + set doc [string trim [string repeat "x y " 500]] + execsql { INSERT INTO xyz VALUES($doc) } +} {} +do_execsql_test 1.2 { + SELECT highlight(xyz, 0, '[', ']') FROM xyz WHERE xyz MATCH 'x' ORDER BY rank +} [list [string map {x [x]} $doc]] + +do_execsql_test 1.3 { + SELECT highlight(xyz, 0, '[', ']') FROM xyz + WHERE xyz MATCH 'x AND y' ORDER BY rank +} [list [string map {x [x] y [y]} $doc]] + +#------------------------------------------------------------------------- +# Check that the 'rank' option really is persistent. +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE tt USING fts5(a); + INSERT INTO tt VALUES('a x x x x'); + INSERT INTO tt VALUES('x x a a a'); + INSERT INTO tt VALUES('x a a x x'); +} + +proc firstinst {cmd} { + foreach {p c o} [$cmd xInst 0] {} + return $o +} +sqlite3_fts5_create_function db firstinst firstinst + +do_execsql_test 2.1 { + SELECT rowid FROM tt('a') ORDER BY rank; +} {2 3 1} + +do_execsql_test 2.2 { + SELECT rowid FROM tt('a', 'firstinst()') ORDER BY rank; +} {1 3 2} + +do_execsql_test 2.3 { + INSERT INTO tt(tt, rank) VALUES('rank', 'firstinst()'); + SELECT rowid FROM tt('a') ORDER BY rank; +} {1 3 2} + +do_test 2.4 { + sqlite3 db2 test.db + catchsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 {no such function: firstinst}} + +do_test 2.5 { + db2 close + sqlite3 db2 test.db + sqlite3_fts5_create_function db2 firstinst firstinst + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 3 2} + +do_test 2.6 { + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db2 +} {1 3 2} + +do_test 2.7 { + execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db +} {1 3 2} + + + + + + + +finish_test + diff --git a/ext/fts5/test/fts5rebuild.test b/ext/fts5/test/fts5rebuild.test new file mode 100644 index 0000000..1044421 --- /dev/null +++ b/ext/fts5/test/fts5rebuild.test @@ -0,0 +1,67 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5rebuild + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.1 { + CREATE VIRTUAL TABLE f1 USING fts5(a, b); + INSERT INTO f1(a, b) VALUES('one', 'o n e'); + INSERT INTO f1(a, b) VALUES('two', 't w o'); + INSERT INTO f1(a, b) VALUES('three', 't h r e e'); +} + +do_execsql_test 1.2 { + INSERT INTO f1(f1) VALUES('integrity-check'); +} {} + +do_execsql_test 1.3 { + INSERT INTO f1(f1) VALUES('rebuild'); +} {} + +do_execsql_test 1.4 { + INSERT INTO f1(f1) VALUES('integrity-check'); +} {} + +do_execsql_test 1.5 { + DELETE FROM f1_data; +} {} + +do_catchsql_test 1.6 { + INSERT INTO f1(f1) VALUES('integrity-check'); +} {1 {database disk image is malformed}} + +do_execsql_test 1.7 { + INSERT INTO f1(f1) VALUES('rebuild'); + INSERT INTO f1(f1) VALUES('integrity-check'); +} {} + + +#------------------------------------------------------------------------- +# Check that 'rebuild' may not be used with a contentless table. +# +do_execsql_test 2.1 { + CREATE VIRTUAL TABLE nc USING fts5(doc, content=); +} + +do_catchsql_test 2.2 { + INSERT INTO nc(nc) VALUES('rebuild'); +} {1 {'rebuild' may not be used with a contentless fts5 table}} +finish_test + diff --git a/ext/fts5/test/fts5restart.test b/ext/fts5/test/fts5restart.test new file mode 100644 index 0000000..0dd7d69 --- /dev/null +++ b/ext/fts5/test/fts5restart.test @@ -0,0 +1,152 @@ +# 2015 April 28 +# +# 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 focuses on testing the planner (xBestIndex function). +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5restart + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE f1 USING fts5(ff); +} + +#------------------------------------------------------------------------- +# Run the 'optimize' command. Check that it does not disturb ongoing +# full-text queries. +# +do_test 1.1 { + for {set i 1} {$i < 1000} {incr i} { + execsql { INSERT INTO f1 VALUES('a b c d e') } + lappend lRowid $i + } +} {} + +do_execsql_test 1.2 { + SELECT rowid FROM f1 WHERE f1 MATCH 'c'; +} $lRowid + +do_test 1.3 { + set res [list] + db eval { SELECT rowid FROM f1 WHERE f1 MATCH 'c' } { + if {$rowid == 100} { + execsql { INSERT INTO f1(f1) VALUES('optimize') } + } + lappend res $rowid + } + set res +} $lRowid + +do_test 1.4.1 { + sqlite3 db2 test.db + set res [list] + db2 eval { SELECT rowid FROM f1 WHERE f1 MATCH 'c' } { + if {$rowid == 100} { + set cres [catchsql { INSERT INTO f1(f1) VALUES('optimize') }] + } + lappend res $rowid + } + set res +} $lRowid + +do_test 1.4.2 { + db2 close + set cres +} {1 {database is locked}} + +#------------------------------------------------------------------------- +# Open a couple of cursors. Then close them in the same order. +# +do_test 2.1 { + set ::s1 [sqlite3_prepare db "SELECT rowid FROM f1 WHERE f1 MATCH 'b'" -1 X] + set ::s2 [sqlite3_prepare db "SELECT rowid FROM f1 WHERE f1 MATCH 'c'" -1 X] + + sqlite3_step $::s1 +} {SQLITE_ROW} +do_test 2.2 { + sqlite3_step $::s2 +} {SQLITE_ROW} + +do_test 2.1 { + sqlite3_finalize $::s1 + sqlite3_finalize $::s2 +} {SQLITE_OK} + +#------------------------------------------------------------------------- +# Copy data between two FTS5 tables. +# +do_execsql_test 3.1 { + CREATE VIRTUAL TABLE f2 USING fts5(gg); + INSERT INTO f2 SELECT ff FROM f1 WHERE f1 MATCH 'b+c+d'; +} +do_execsql_test 3.2 { + SELECT rowid FROM f2 WHERE f2 MATCH 'a+b+c+d+e' +} $lRowid + +#------------------------------------------------------------------------- +# Remove the row that an FTS5 cursor is currently pointing to. And +# various other similar things. Check that this does not disturb +# ongoing scans. +# +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE n4 USING fts5(n); + INSERT INTO n4(rowid, n) VALUES(100, '1 2 3 4 5'); + INSERT INTO n4(rowid, n) VALUES(200, '1 2 3 4'); + INSERT INTO n4(rowid, n) VALUES(300, '2 3 4'); + INSERT INTO n4(rowid, n) VALUES(400, '2 3'); + INSERT INTO n4(rowid, n) VALUES(500, '3'); +} + +do_test 4.1 { + set res [list] + db eval { SELECT rowid FROM n4 WHERE n4 MATCH '3' } { + if {$rowid==300} { + execsql { DELETE FROM n4 WHERE rowid=300 } + } + lappend res $rowid + } + set res +} {100 200 300 400 500} + +do_test 4.2 { + execsql { INSERT INTO n4(rowid, n) VALUES(300, '2 3 4') } + set res [list] + db eval { SELECT rowid FROM n4 WHERE n4 MATCH '3' ORDER BY rowid DESC} { + if {$rowid==300} { + execsql { DELETE FROM n4 WHERE rowid=300 } + } + lappend res $rowid + } + set res +} {500 400 300 200 100} + +do_test 4.3 { + execsql { INSERT INTO n4(rowid, n) VALUES(300, '2 3 4') } + set res [list] + db eval { SELECT rowid FROM n4 WHERE n4 MATCH '3' ORDER BY rowid DESC} { + if {$rowid==300} { + execsql { DELETE FROM n4 } + } + lappend res $rowid + } + set res +} {500 400 300} + + + +finish_test + diff --git a/ext/fts5/test/fts5rowid.test b/ext/fts5/test/fts5rowid.test new file mode 100644 index 0000000..19590cd --- /dev/null +++ b/ext/fts5/test/fts5rowid.test @@ -0,0 +1,219 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests of the scalar fts5_rowid() and fts5_decode() functions. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5rowid + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_catchsql_test 1.1 { + SELECT fts5_rowid() +} {1 {should be: fts5_rowid(subject, ....)}} + +do_catchsql_test 1.2 { + SELECT fts5_rowid('segment') +} {1 {should be: fts5_rowid('segment', segid, pgno))}} + +do_execsql_test 1.3 { + SELECT fts5_rowid('segment', 1, 1) +} {137438953473} + +do_catchsql_test 1.4 { + SELECT fts5_rowid('nosucharg'); +} {1 {first arg to fts5_rowid() must be 'segment'}} + + +#------------------------------------------------------------------------- +# Tests of the fts5_decode() function. +# +reset_db +do_execsql_test 2.1 { + CREATE VIRTUAL TABLE x1 USING fts5(a, b); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); +} {} + +proc rnddoc {n} { + set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j] + set doc [list] + for {set i 0} {$i < $n} {incr i} { + lappend doc [string map $map [format %.3d [expr int(rand()*100)]]] + } + set doc +} +db func rnddoc rnddoc + +do_execsql_test 2.2 { + WITH r(a, b) AS ( + SELECT rnddoc(6), rnddoc(6) UNION ALL + SELECT rnddoc(6), rnddoc(6) FROM r + ) + INSERT INTO x1 SELECT * FROM r LIMIT 10000; + DELETE FROM x1 WHERE (rowid%2); +} + +set res [db one {SELECT count(*) FROM x1_data}] +do_execsql_test 2.3 { + SELECT count(fts5_decode(rowid, block)) FROM x1_data; +} $res +do_execsql_test 2.4 { + UPDATE x1_data SET block = X''; + SELECT count(fts5_decode(rowid, block)) FROM x1_data; +} $res + +do_execsql_test 2.5 { + INSERT INTO x1(x1, rank) VALUES('pgsz', 1024); + INSERT INTO x1(x1) VALUES('rebuild'); +} + +set res [db one {SELECT count(*) FROM x1_data}] +do_execsql_test 2.6 { + SELECT count(fts5_decode(rowid, block)) FROM x1_data; +} $res + +# This is really a corruption test... +#do_execsql_test 2.7 { +# UPDATE x1_data SET block = X''; +# SELECT count(fts5_decode(rowid, block)) FROM x1_data; +#} $res + +do_execsql_test 2.8 { + SELECT fts5_decode(fts5_rowid('segment', 1000, 1), X'AB') +} {corrupt} + +#------------------------------------------------------------------------- +# Tests with very large tokens. +# +set strlist [list \ + "[string repeat x 400]" \ + "[string repeat x 300][string repeat w 100]" \ + "[string repeat x 300][string repeat y 100]" \ + "[string repeat x 300][string repeat z 600]" \ +] +do_test 3.0 { + execsql { + BEGIN; + CREATE VIRTUAL TABLE x2 USING fts5(a); + } + foreach str $strlist { execsql { INSERT INTO x2 VALUES($str) } } + execsql COMMIT +} {} + +for {set tn 0} {$tn<[llength $strlist]} {incr tn} { + set str [lindex $strlist $tn] + do_execsql_test 3.1.$tn { + SELECT rowid FROM x2 WHERE x2 MATCH $str + } [expr $tn+1] +} + +set res [db one {SELECT count(*) FROM x2_data}] +do_execsql_test 3.2 { + SELECT count(fts5_decode(rowid, block)) FROM x2_data; +} $res + +#------------------------------------------------------------------------- +# Leaf pages with no terms or rowids at all. +# +set strlist [list \ + "[string repeat {w } 400]" \ + "[string repeat {x } 400]" \ + "[string repeat {y } 400]" \ + "[string repeat {z } 400]" \ +] +do_test 4.0 { + execsql { + BEGIN; + CREATE VIRTUAL TABLE x3 USING fts5(a); + INSERT INTO x3(x3, rank) VALUES('pgsz', 32); + } + foreach str $strlist { execsql { INSERT INTO x3 VALUES($str) } } + execsql COMMIT +} {} + +for {set tn 0} {$tn<[llength $strlist]} {incr tn} { + set str [lindex $strlist $tn] + do_execsql_test 4.1.$tn { + SELECT rowid FROM x3 WHERE x3 MATCH $str + } [expr $tn+1] +} + +set res [db one {SELECT count(*) FROM x3_data}] +do_execsql_test 4.2 { + SELECT count(fts5_decode(rowid, block)) FROM x3_data; +} $res + +#------------------------------------------------------------------------- +# Position lists with large values. +# +set strlist [list \ + "[string repeat {w } 400]a" \ + "[string repeat {x } 400]a" \ + "[string repeat {y } 400]a" \ + "[string repeat {z } 400]a" \ +] +do_test 5.0 { + execsql { + BEGIN; + CREATE VIRTUAL TABLE x4 USING fts5(a); + INSERT INTO x4(x4, rank) VALUES('pgsz', 32); + } + foreach str $strlist { execsql { INSERT INTO x4 VALUES($str) } } + execsql COMMIT +} {} + +do_execsql_test 5.1 { + SELECT rowid FROM x4 WHERE x4 MATCH 'a' +} {1 2 3 4} + +set res [db one {SELECT count(*) FROM x4_data}] +do_execsql_test 5.2 { + SELECT count(fts5_decode(rowid, block)) FROM x4_data; +} $res + +#------------------------------------------------------------------------- +# + +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE x5 USING fts5(x, detail=none); + INSERT INTO x5(x5, rank) VALUES('pgsz', 32); + INSERT INTO x5 VALUES('a b c d e f'); + INSERT INTO x5 VALUES('a b c d e f'); + INSERT INTO x5 VALUES('a b c d e f'); + BEGIN; + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100 + ) INSERT INTO x5 SELECT 'a b c d e f' FROM s; + COMMIT; + SELECT count(fts5_decode_none(rowid, block)) FROM x5_data; +} {32} + +do_execsql_test 6.1 { + DELETE FROM x5 WHERE rowid <= 2; + SELECT count(fts5_decode_none(rowid, block)) FROM x5_data; +} {34} + +do_execsql_test 6.2 { + UPDATE x5 SET x='a b c d e f' WHERE rowid=3; + SELECT count(fts5_decode_none(rowid, block)) FROM x5_data; +} {36} + +#db eval {SELECT rowid, fts5_decode_none(rowid, block) aS r FROM x5_data} {puts $r} + + + +finish_test + diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test new file mode 100644 index 0000000..a095a16 --- /dev/null +++ b/ext/fts5/test/fts5simple.test @@ -0,0 +1,413 @@ +# 2015 September 05 +# +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5simple + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +if 1 { + +#------------------------------------------------------------------------- +# +set doc "x x [string repeat {y } 50]z z" +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + BEGIN; + INSERT INTO t1 VALUES($doc); + COMMIT; +} + +do_execsql_test 1.1 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + INSERT INTO t1 VALUES('a b c'); + INSERT INTO t1 VALUES('d e f'); + INSERT INTO t1(t1) VALUES('optimize'); +} + +do_execsql_test 2.1 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {} + + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t1 USING fts5(x, prefix='1,2'); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + BEGIN; + INSERT INTO t1 VALUES('one'); + SELECT * FROM t1 WHERE t1 MATCH 'o*'; +} {one} + +do_execsql_test 3.1 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.1 { + CREATE VIRTUAL TABLE t11 USING fts5(content); + INSERT INTO t11(t11, rank) VALUES('pgsz', 32); + INSERT INTO t11 VALUES('another'); + INSERT INTO t11 VALUES('string'); + INSERT INTO t11 VALUES('of'); + INSERT INTO t11 VALUES('text'); +} +do_test 4.2 { + execsql { INSERT INTO t11(t11) VALUES('optimize') } +} {} +do_execsql_test 4.3 { + INSERT INTO t11(t11) VALUES('integrity-check'); +} {} + +#db eval { SELECT fts5_decode(rowid, block) as x FROM t11_data } { puts $x } + +#------------------------------------------------------------------------- +reset_db +set doc [string repeat "x y " 5] +do_execsql_test 5.1 { + CREATE VIRTUAL TABLE yy USING fts5(content); + INSERT INTO yy(yy, rank) VALUES('pgsz', 32); + BEGIN; + INSERT INTO yy VALUES($doc); + INSERT INTO yy VALUES($doc); + INSERT INTO yy VALUES($doc); + INSERT INTO yy VALUES($doc); + INSERT INTO yy VALUES($doc); + INSERT INTO yy VALUES($doc); + INSERT INTO yy VALUES($doc); + INSERT INTO yy VALUES($doc); + COMMIT; +} + +do_execsql_test 5.2 { + SELECT rowid FROM yy WHERE yy MATCH 'y' ORDER BY rowid ASC +} {1 2 3 4 5 6 7 8} + +do_execsql_test 5.3 { + SELECT rowid FROM yy WHERE yy MATCH 'y' ORDER BY rowid DESC +} {8 7 6 5 4 3 2 1} + +#db eval { SELECT fts5_decode(rowid, block) as x FROM yy_data } { puts $x } + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.1 { + CREATE VIRTUAL TABLE tt USING fts5(content); + INSERT INTO tt(tt, rank) VALUES('pgsz', 32); + INSERT INTO tt VALUES('aa'); +} + +do_execsql_test 5.2 { + SELECT rowid FROM tt WHERE tt MATCH 'a*'; +} {1} + +do_execsql_test 5.3 { + DELETE FROM tt; + BEGIN; + INSERT INTO tt VALUES('aa'); + INSERT INTO tt VALUES('ab'); + COMMIT; +} {} + +do_execsql_test 5.4 { + SELECT rowid FROM tt WHERE tt MATCH 'a*'; +} {1 2} + +do_execsql_test 5.5 { + DELETE FROM tt; + BEGIN; + INSERT INTO tt VALUES('aa'); + INSERT INTO tt VALUES('ab'); + INSERT INTO tt VALUES('aa'); + INSERT INTO tt VALUES('ab'); + INSERT INTO tt VALUES('aa'); + INSERT INTO tt VALUES('ab'); + INSERT INTO tt VALUES('aa'); + INSERT INTO tt VALUES('ab'); + COMMIT; + SELECT rowid FROM tt WHERE tt MATCH 'a*'; +} {1 2 3 4 5 6 7 8} + +do_execsql_test 5.6 { + INSERT INTO tt(tt) VALUES('integrity-check'); +} + +reset_db +do_execsql_test 5.7 { + CREATE VIRTUAL TABLE tt USING fts5(content); + INSERT INTO tt(tt, rank) VALUES('pgsz', 32); + INSERT INTO tt VALUES('aa ab ac ad ae af'); +} + +do_execsql_test 5.8 { + SELECT rowid FROM tt WHERE tt MATCH 'a*'; +} {1} + +#------------------------------------------------------------------------- + +reset_db +do_execsql_test 6.1 { + CREATE VIRTUAL TABLE xyz USING fts5(x, y, z); + INSERT INTO xyz VALUES('x', 'y', 'z'); +} + +do_catchsql_test 6.2 { + SELECT * FROM xyz WHERE xyz MATCH '' +} {1 {fts5: syntax error near ""}} +do_catchsql_test 6.3 { + SELECT * FROM xyz WHERE xyz MATCH NULL +} {1 {fts5: syntax error near ""}} + +#------------------------------------------------------------------------- + +do_execsql_test 7.1 { + CREATE VIRTUAL TABLE ft2 USING fts5(content); + INSERT INTO ft2(rowid, content) VALUES(1, 'a b c'); + INSERT INTO ft2(rowid, content) VALUES(2, 'a b d'); +} + +do_catchsql_test 7.2 { + BEGIN; + UPDATE ft2 SET rowid=2 WHERE rowid=1; +} {1 {constraint failed}} + +do_execsql_test 7.3 { + COMMIT; + INSERT INTO ft2(ft2) VALUES('integrity-check'); +} {} + +do_execsql_test 7.4 { + SELECT * FROM ft2; +} {{a b c} {a b d}} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 8.1 { + CREATE VIRTUAL TABLE ft2 USING fts5(content); + INSERT INTO ft2(rowid, content) VALUES(1, 'a b'); +} + +do_execsql_test 8.2 { + BEGIN; + INSERT INTO ft2(rowid, content) VALUES(4, 'a x'); +} + +do_execsql_test 8.3 { + INSERT INTO ft2(ft2) VALUES('integrity-check'); +} + +#------------------------------------------------------------------------- +# Check that the "table function" syntax works. +# +reset_db +do_execsql_test 9.1 { + CREATE VIRTUAL TABLE ft2 USING fts5(content); + INSERT INTO ft2(rowid, content) VALUES(1, 'a b'); + INSERT INTO ft2(rowid, content) VALUES(2, 'a b c d'); + INSERT INTO ft2(rowid, content) VALUES(3, 'c d e f'); +} + +do_execsql_test 9.2 { + SELECT rowid FROM ft2('a'); +} {1 2} + +do_execsql_test 9.3 { + SELECT rowid FROM ft2('b AND c'); +} {2} + +#------------------------------------------------------------------------- +# +do_execsql_test 10.0 { + CREATE VIRTUAL TABLE t3 USING fts5(a, b, c); + INSERT INTO t3 VALUES('bac aab bab', 'c bac c', 'acb aba abb'); -- 1 + INSERT INTO t3 VALUES('bab abc c', 'acb c abb', 'c aaa c'); -- 2 +} + +do_execsql_test 10.1 { + SELECT rowid FROM t3('c: c*'); +} {2} + +do_execsql_test 10.2 { + SELECT rowid FROM t3('b: acb'); +} {2} + +#------------------------------------------------------------------------- +# Test that character 0x1A is allowed in fts5 barewords. +# +do_test 11.0 { + execsql "CREATE VIRTUAL TABLE t4 USING fts5(x, tokenize=\"ascii tokenchars '\x1A'\")" + execsql " + INSERT INTO t4 VALUES('a b c \x1A'); + INSERT INTO t4 VALUES('a b c d\x1A'); + INSERT INTO t4 VALUES('a b c \x1Ad'); + INSERT INTO t4 VALUES('a b c d'); + " +} {} + +do_test 11.1 { + execsql "SELECT rowid FROM t4('\x1A')" +} {1} +do_test 11.2 { + execsql "SELECT rowid FROM t4('\x1A*')" +} {1 3} +do_test 11.3 { + execsql "SELECT rowid FROM t4('d\x1A')" +} {2} + +do_test 11.4 { + catchsql "SELECT rowid FROM t4('d\x1B')" +} {/fts5: syntax error/} +do_test 11.5 { + catchsql "SELECT rowid FROM t4('d\x19')" +} {/fts5: syntax error/} + +#------------------------------------------------------------------------- +# +do_test 12.1 { + execsql { + CREATE VIRTUAL TABLE xx USING fts5(x,y); + BEGIN; + INSERT INTO xx VALUES('1 2 3', 'a b c'); + } +} {} + +do_execsql_test 12.2 { + SELECT rowid FROM xx('x:a'); + COMMIT; +} {} + +#------------------------------------------------------------------------- +# Try an UPDATE OR REPLACE query. +# +do_execsql_test 13.1 { + CREATE VIRTUAL TABLE xy USING fts5(x); + INSERT INTO xy(rowid, x) VALUES(1, '1 2 3'); + INSERT INTO xy(rowid, x) VALUES(2, '2 3 4'); + INSERT INTO xy(rowid, x) VALUES(3, '3 4 5'); +} + +do_execsql_test 13.2 { + UPDATE OR REPLACE xy SET rowid=3 WHERE rowid = 2; + SELECT rowid, x FROM xy; +} { + 1 {1 2 3} + 3 {2 3 4} +} + +do_execsql_test 13.3 { + INSERT INTO xy(xy) VALUES('integrity-check'); +} + +#------------------------------------------------------------------------- +# +do_execsql_test 14.1 { + CREATE VIRTUAL TABLE ttt USING fts5(x); + BEGIN; + INSERT INTO ttt(rowid, x) VALUES(1, 'a b c'); + INSERT INTO ttt(rowid, x) VALUES(2, 'a b c'); + INSERT INTO ttt(rowid, x) VALUES(3, 'a b c'); + COMMIT; +} +do_test 14.2 { + fts5_level_segs ttt +} {1} + +#------------------------------------------------------------------------- +db func rnddoc fts5_rnddoc +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x1, rank) VALUES('pgsz', 32); + + WITH ii(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<10 ) + INSERT INTO x1 SELECT rnddoc(5) FROM ii; +} + +do_execsql_test 4.1 { + SELECT rowid, x, x1 FROM x1 WHERE x1 MATCH '*reads' +} {0 {} 4} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 15.0 { + CREATE VIRTUAL TABLE x2 USING fts5(x, prefix=1); + INSERT INTO x2 VALUES('ab'); +} + +do_execsql_test 15.1 { + INSERT INTO x2(x2) VALUES('integrity-check'); +} + +#------------------------------------------------------------------------- +foreach_detail_mode $testprefix { + reset_db + fts5_aux_test_functions db + do_execsql_test 16.0 { + CREATE VIRTUAL TABLE x3 USING fts5(x, detail=%DETAIL%); + INSERT INTO x3 VALUES('a b c d e f'); + } + do_execsql_test 16.1 { + SELECT fts5_test_poslist(x3) FROM x3('(a NOT b) OR c'); + } {2.0.2} + + do_execsql_test 16.1 { + SELECT fts5_test_poslist(x3) FROM x3('a OR c'); + } {{0.0.0 1.0.2}} +} + +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 17.0 { + CREATE VIRTUAL TABLE x3 USING fts5(x); + INSERT INTO x3 VALUES('a b c'); +} + +do_execsql_test 17.1 { + SELECT rowid FROM x3('b AND d'); +} + +#------------------------------------------------------------------------- +do_execsql_test 18.1 { + CREATE VIRTUAL TABLE x4 USING fts5(x); + SELECT rowid FROM x4('""'); +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 19.1 { + CREATE VIRTUAL TABLE x1 USING fts5(a,b,c); +} + +do_catchsql_test 19.2 { + SELECT * FROM x1 WHERE x1 MATCH 'c0 AND (c1 AND (c2 AND (c3 AND (c4 AND (c5 AND (c6 AND (c7 AND (c8 AND (c9 AND (c10 AND (c11 AND (c12 AND (c13 AND (c14 AND (c15 AND (c16 AND (c17 AND (c18 AND (c19 AND (c20 AND (c21 AND (c22 AND (c23 AND (c24 AND (c25 AND (c26 AND (c27 AND (c28 AND (c29 AND (c30 AND (c31 AND (c32 AND (c33 AND (c34 AND (c35 AND (c36 AND (c37 AND (c38 AND (c39 AND (c40 AND (c41 AND (c42 AND (c43 AND (c44 AND (c45 AND (c46 AND (c47 AND (c48 AND (c49 AND (c50 AND (c51 AND (c52 AND (c53 AND (c54 AND (c55 AND (c56 AND (c57 AND (c58 AND (c59 AND (c60 AND (c61 AND (c62 AND (c63 AND (c64 AND (c65 AND (c66 AND (c67 AND (c68 AND (c69 AND (c70 AND (c71 AND (c72 AND (c73 AND (c74 AND (c75 AND (c76 AND (c77 AND (c78 AND (c79 AND (c80 AND (c81 AND (c82 AND (c83 AND (c84 AND (c85 AND (c86 AND (c87 AND (c88 AND (c89 AND (c90 AND (c91 AND (c92 AND (c93 AND (c94 AND (c95 AND (c96 AND (c97 AND (c98 AND (c99 AND (c100 AND (c101 AND (c102 AND (c103 AND (c104 AND (c105 AND (c106 AND (c107 AND (c108 AND (c109 AND (c110 AND (c111 AND (c112 AND (c113 AND (c114 AND (c115 AND (c116 AND (c117 AND (c118 AND (c119 AND (c120 AND (c121 AND (c122 AND (c123 AND (c124 AND (c125 AND (c126 AND (c127 AND (c128 AND (c129 AND (c130 AND (c131 AND (c132 AND (c133 AND (c134 AND (c135 AND (c136 AND (c137 AND (c138 AND (c139 AND (c140 AND (c141 AND (c142 AND (c143 AND (c144 AND (c145 AND (c146 AND (c147 AND (c148 AND (c149 AND (c150 AND (c151 AND (c152 AND (c153 AND (c154 AND (c155 AND (c156 AND (c157 AND (c158 AND (c159 AND (c160 AND (c161 AND (c162 AND (c163 AND (c164 AND (c165 AND (c166 AND (c167 AND (c168 AND (c169 AND (c170 AND (c171 AND (c172 AND (c173 AND (c174 AND (c175 AND (c176 AND (c177 AND (c178 AND (c179 AND (c180 AND (c181 AND (c182 AND (c183 AND (c184 AND (c185 AND (c186 AND (c187 AND (c188 AND (c189 AND (c190 AND (c191 AND (c192 AND (c193 AND (c194 AND (c195 AND (c196 AND (c197 AND (c198 AND (c199 AND c200)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))'; +} {1 {fts5: parser stack overflow}} + +finish_test + diff --git a/ext/fts5/test/fts5simple2.test b/ext/fts5/test/fts5simple2.test new file mode 100644 index 0000000..186d771 --- /dev/null +++ b/ext/fts5/test/fts5simple2.test @@ -0,0 +1,338 @@ +# 2015 September 05 +# +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5simple2 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + INSERT INTO t1 VALUES('a b c'); +} +do_execsql_test 1.1 { + SELECT rowid FROM t1('c a b') +} {1} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + BEGIN; + INSERT INTO t1 VALUES('b c d'); + INSERT INTO t1 VALUES('b c d'); + COMMIT; +} +do_execsql_test 2.1 { + SELECT rowid FROM t1('b c d') +} {1 2} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + BEGIN; + INSERT INTO t1 VALUES('b c d'); + INSERT INTO t1 VALUES('b c d'); +} +do_execsql_test 3.1 { + SELECT rowid FROM t1('b c d'); COMMIT; +} {1 2} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 4.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + BEGIN; + INSERT INTO t1 VALUES('a1 b1 c1'); + INSERT INTO t1 VALUES('a2 b2 c2'); + INSERT INTO t1 VALUES('a3 b3 c3'); + COMMIT; +} +do_execsql_test 4.1 { + SELECT rowid FROM t1('b*'); +} {1 2 3} + + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + BEGIN; + INSERT INTO t1 VALUES('a1 b1 c1'); + INSERT INTO t1 VALUES('a2 b2 c2'); + INSERT INTO t1 VALUES('a1 b1 c1'); + COMMIT; +} +do_execsql_test 5.1 { SELECT rowid FROM t1('b*') } {1 2 3} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=full); + BEGIN; + INSERT INTO t1 VALUES('a1 b1 c1'); + INSERT INTO t1 VALUES('a1 b1 c1'); + INSERT INTO t1 VALUES('a1 b1 c1'); + COMMIT; +} + +do_execsql_test 6.1 { SELECT rowid FROM t1('a1') ORDER BY rowid DESC } {3 2 1} +do_execsql_test 6.2 { SELECT rowid FROM t1('b1') ORDER BY rowid DESC } {3 2 1} +do_execsql_test 6.3 { SELECT rowid FROM t1('c1') ORDER BY rowid DESC } {3 2 1} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 7.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + BEGIN; + INSERT INTO t1 VALUES('a1 b1'); + INSERT INTO t1 VALUES('a1 b2'); + COMMIT; +} +do_execsql_test 7.1 { SELECT rowid FROM t1('b*') ORDER BY rowid DESC } {2 1} +do_execsql_test 7.2 { SELECT rowid FROM t1('a1') ORDER BY rowid DESC } {2 1} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + INSERT INTO t1 VALUES('a1 b1 c1'); + INSERT INTO t1 VALUES('a2 b2 c2'); + INSERT INTO t1 VALUES('a1 b1 c1'); +} +do_execsql_test 8.0.1 { SELECT rowid FROM t1('b*') } {1 2 3} +do_execsql_test 8.0.2 { SELECT rowid FROM t1('a1') } {1 3} +do_execsql_test 8.0.3 { SELECT rowid FROM t1('c2') } {2} + +do_execsql_test 8.0.4 { SELECT rowid FROM t1('b*') ORDER BY rowid DESC } {3 2 1} +do_execsql_test 8.0.5 { SELECT rowid FROM t1('a1') ORDER BY rowid DESC } {3 1} +do_execsql_test 8.0.8 { SELECT rowid FROM t1('c2') ORDER BY rowid DESC } {2} + +do_execsql_test 8.1.0 { INSERT INTO t1(t1) VALUES('optimize') } + +do_execsql_test 8.1.1 { SELECT rowid FROM t1('b*') } {1 2 3} +do_execsql_test 8.1.2 { SELECT rowid FROM t1('a1') } {1 3} +do_execsql_test 8.1.3 { SELECT rowid FROM t1('c2') } {2} + +do_execsql_test 8.2.1 { SELECT rowid FROM t1('b*') ORDER BY rowid DESC} {3 2 1} +do_execsql_test 8.2.2 { SELECT rowid FROM t1('a1') ORDER BY rowid DESC} {3 1} +do_execsql_test 8.2.3 { SELECT rowid FROM t1('c2') ORDER BY rowid DESC} {2} + +#-------------------------------------------------------------------------- +# +reset_db +do_execsql_test 9.0.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + INSERT INTO t1 VALUES('a1 b1 c1'); + INSERT INTO t1 VALUES('a2 b2 c2'); + INSERT INTO t1 VALUES('a1 b1 c1'); +} +do_execsql_test 9.0.1 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {} + +reset_db +do_execsql_test 9.1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=none); + INSERT INTO t1 VALUES('a1 b1 c1', 'x y z'); + INSERT INTO t1 VALUES('a2 b2 c2', '1 2 3'); + INSERT INTO t1 VALUES('a1 b1 c1', 'x 2 z'); +} +do_execsql_test 9.2.1 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {} + +#-------------------------------------------------------------------------- +# +reset_db +do_execsql_test 10.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + INSERT INTO t1 VALUES('b1'); + INSERT INTO t1 VALUES('b1'); + DELETE FROM t1 WHERE rowid=1; +} + +do_execsql_test 10.1 { + SELECT rowid FROM t1('b1'); +} {2} + +do_execsql_test 10.2 { + SELECT rowid FROM t1('b1') ORDER BY rowid DESC; +} {2} + +do_execsql_test 10.3 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} {} + +#-------------------------------------------------------------------------- +# +reset_db +do_execsql_test 11.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, y, detail=none); + INSERT INTO t1(t1, rank) VALUES('pgsz', 32); + WITH d(x,y) AS ( + SELECT NULL, 'xyz' UNION ALL SELECT NULL, 'xyz' FROM d + ) + INSERT INTO t1 SELECT * FROM d LIMIT 23; +} + +#db eval { SELECT rowid AS r, quote(block) AS b FROM t1_data } { puts "$r: $b" } +do_execsql_test 11.2 { + SELECT rowid FROM t1; +} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23} + +do_execsql_test 11.3 { + SELECT rowid FROM t1('xyz'); +} {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23} + +do_execsql_test 11.4 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 12.0 { + CREATE VIRTUAL TABLE yy USING fts5(x, detail=none); + INSERT INTO yy VALUES('in if'); + INSERT INTO yy VALUES('if'); +} {} + +do_execsql_test 12.1 { + SELECT rowid FROM yy('i*'); +} {1 2} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 13.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, prefix=1, detail=none); +} {} +foreach {rowid a} { + 0 {f} + 1 {u} + 2 {k} + 3 {a} + 4 {a} + 5 {u} + 6 {u} + 7 {u} + 8 {f} + 9 {f} + 10 {a} + 11 {p} + 12 {f} + 13 {u} + 14 {a} + 15 {a} +} { + do_execsql_test 13.1.$rowid { + INSERT INTO t1(rowid, a) VALUES($rowid, $a); + } +} + +#------------------------------------------------------------------------- +# +reset_db +fts5_aux_test_functions db +do_execsql_test 14.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, detail=none); + INSERT INTO t1 VALUES('a b c d'); +} {} + +do_execsql_test 14.1 { + SELECT fts5_test_poslist(t1) FROM t1('b') ORDER BY rank; +} {0.0.1} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 15.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=none); + BEGIN; + INSERT INTO t1(rowid, x) VALUES(1, 'sqlite'); + INSERT INTO t1(rowid, x) VALUES(2, 'sqlite'); + COMMIT; +} {} + +do_test 15.1 { + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } +} {} + +do_test 15.2 { + execsql { DELETE FROM t1 } +} {} + +do_execsql_test 15.3.1 { + SELECT rowid FROM t1('sqlite'); +} {} + +do_execsql_test 15.3.2 { + SELECT rowid FROM t1('sqlite') ORDER BY rowid DESC; +} {} + +do_test 15.4 { + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } +} {} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 16.0 { + CREATE VIRTUAL TABLE t2 USING fts5(x, detail=none); + BEGIN; + INSERT INTO t2(rowid, x) VALUES(1, 'a b c'); + INSERT INTO t2(rowid, x) VALUES(456, 'a b c'); + INSERT INTO t2(rowid, x) VALUES(1000, 'a b c'); + COMMIT; + UPDATE t2 SET x=x; +} + +do_execsql_test 16.1 { + INSERT INTO t2(t2) VALUES('integrity-check'); +} {} + +do_execsql_test 16.2 { + SELECT rowid FROM t2('b') ORDER BY rowid DESC +} {1000 456 1} + + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 16.0 { + CREATE VIRTUAL TABLE t2 USING fts5(x, detail=none); + BEGIN; + INSERT INTO t2(rowid, x) VALUES(1, 'a b c'); + INSERT INTO t2(rowid, x) VALUES(456, 'a b c'); + INSERT INTO t2(rowid, x) VALUES(1000, 'a b c'); + COMMIT; + UPDATE t2 SET x=x; + DELETE FROM t2; +} + +#db eval {SELECT rowid, fts5_decode_none(rowid, block) aS r FROM t2_data} {puts $r} + +finish_test + diff --git a/ext/fts5/test/fts5simple3.test b/ext/fts5/test/fts5simple3.test new file mode 100644 index 0000000..b6922f8 --- /dev/null +++ b/ext/fts5/test/fts5simple3.test @@ -0,0 +1,85 @@ +# 2015 September 05 +# +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5simple3 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +fts5_aux_test_functions db + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c, detail=col); + INSERT INTO t1 VALUES('a', 'b', 'c'); + INSERT INTO t1 VALUES('x', 'x', 'x'); +} + +do_execsql_test 1.1 { + SELECT rowid, fts5_test_collist(t1) FROM t1('a:a'); +} {1 0.0} + +do_execsql_test 1.2 { + SELECT rowid, fts5_test_collist(t1) FROM t1('b:x'); +} {2 0.1} + +do_execsql_test 1.3 { + SELECT rowid, fts5_test_collist(t1) FROM t1('b:a'); +} {} + +#------------------------------------------------------------------------- +# Create detail=col and detail=full tables with 998 columns. +# +foreach_detail_mode $testprefix { + if {[detail_is_none]} continue + + do_test 2.1 { + execsql { DROP TABLE IF EXISTS t2 } + set cols [list] + set vals [list] + for {set i 1} {$i <= 998} {incr i} { + lappend cols "c$i" + lappend vals "'val$i'" + } + execsql "CREATE VIRTUAL TABLE t2 USING fts5(detail=%DETAIL%,[join $cols ,])" + } {} + + do_test 2.2 { + execsql "INSERT INTO t2 VALUES([join $vals ,])" + } {} + + foreach {tn q res} { + 1 { c1:val1 } 1 + 2 { c300:val300 } 1 + 3 { c300:val1 } {} + 4 { c1:val300 } {} + } { + do_execsql_test 2.3.$tn { + SELECT rowid FROM t2($q) + } $res + } +} + +do_execsql_test 3.0 { + CREATE VIRTUAL TABLE x3 USING fts5(one); + INSERT INTO x3 VALUES('a b c'); + INSERT INTO x3 VALUES('c b a'); + INSERT INTO x3 VALUES('o t t'); + SELECT * FROM x3('x OR y OR z'); +} + + +finish_test + diff --git a/ext/fts5/test/fts5synonym.test b/ext/fts5/test/fts5synonym.test new file mode 100644 index 0000000..185dda3 --- /dev/null +++ b/ext/fts5/test/fts5synonym.test @@ -0,0 +1,424 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on custom tokenizers that support synonyms. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5synonym + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc tcl_create {args} { return "tcl_tokenize" } + +foreach_detail_mode $testprefix { + +#------------------------------------------------------------------------- +# Warm body test for the code in fts5_tcl.c. +# +fts5_tclnum_register db +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE ft USING fts5(x, tokenize = "tclnum document", detail=%DETAIL%); + INSERT INTO ft VALUES('abc def ghi'); + INSERT INTO ft VALUES('jkl mno pqr'); + SELECT rowid, x FROM ft WHERE ft MATCH 'def'; + SELECT x, rowid FROM ft WHERE ft MATCH 'pqr'; +} {1 {abc def ghi} {jkl mno pqr} 2} + +#------------------------------------------------------------------------- +# Test a tokenizer that supports synonyms by adding extra entries to the +# FTS index. +# +reset_db +fts5_tclnum_register db + +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE ft USING fts5( + x, tokenize = "tclnum document", detail=%DETAIL% + ); + INSERT INTO ft VALUES('one two three'); + INSERT INTO ft VALUES('four five six'); + INSERT INTO ft VALUES('eight nine ten'); +} {} + +foreach {tn expr res} { + 1 "3" 1 + 2 "eight OR 8 OR 5" {2 3} + 3 "10" {} + 4 "1*" {1} + 5 "1 + 2" {1} +} { + if {![fts5_expr_ok $expr ft]} continue + do_execsql_test 2.1.$tn { + SELECT rowid FROM ft WHERE ft MATCH $expr + } $res +} + +#------------------------------------------------------------------------- +# Test some broken tokenizers: +# +# 3.1.*: A tokenizer that declares the very first token to be colocated. +# +# 3.2.*: A tokenizer that reports two identical tokens at the same position. +# This is allowed. +# +reset_db +sqlite3_fts5_create_tokenizer db tcl tcl_create +proc tcl_tokenize {tflags text} { + set bColo 1 + foreach {w iStart iEnd} [fts5_tokenize_split $text] { + if {$bColo} { + sqlite3_fts5_token -colo $w $iStart $iEnd + set bColo 0 + } { + sqlite3_fts5_token $w $iStart $iEnd + } + } +} +do_execsql_test 3.1.0 { + CREATE VIRTUAL TABLE ft USING fts5(x, tokenize = tcl); + INSERT INTO ft VALUES('one two three'); + CREATE VIRTUAL TABLE vv USING fts5vocab(ft, row); + SELECT * FROM vv; +} { + one 1 1 three 1 1 two 1 1 +} + +do_execsql_test 3.1.1 { + INSERT INTO ft(ft) VALUES('integrity-check'); +} {} + +proc tcl_tokenize {tflags text} { + foreach {w iStart iEnd} [fts5_tokenize_split $text] { + sqlite3_fts5_token $w $iStart $iEnd + } +} + +do_execsql_test 3.1.2 { + SELECT rowid FROM ft WHERE ft MATCH 'one two three' +} {1} + +reset_db +sqlite3_fts5_create_tokenizer db tcl tcl_create +proc tcl_tokenize {tflags text} { + foreach {w iStart iEnd} [fts5_tokenize_split $text] { + sqlite3_fts5_token $w $iStart $iEnd + sqlite3_fts5_token -colo $w $iStart $iEnd + } +} +do_execsql_test 3.2.0 { + CREATE VIRTUAL TABLE ft USING fts5(x, tokenize = tcl); + INSERT INTO ft VALUES('one one two three'); + CREATE VIRTUAL TABLE vv USING fts5vocab(ft, row); + SELECT * FROM vv; +} { + one 1 4 three 1 2 two 1 2 +} +do_execsql_test 3.2.1 { + SELECT rowid FROM ft WHERE ft MATCH 'one'; +} {1} +do_execsql_test 3.2.2 { + SELECT rowid FROM ft WHERE ft MATCH 'one two three'; +} {1} +do_execsql_test 3.2.3 { + SELECT rowid FROM ft WHERE ft MATCH 'one + one + two + three'; +} {1} +do_execsql_test 3.2.4 { + SELECT rowid FROM ft WHERE ft MATCH 'one two two three'; +} {1} +do_execsql_test 3.2.5 { + SELECT rowid FROM ft WHERE ft MATCH 'one + two + two + three'; +} {} + +#------------------------------------------------------------------------- +# Check that expressions with synonyms can be parsed and executed. +# +reset_db +fts5_tclnum_register db + +foreach {tn expr res} { + 1 {abc} {"abc"} + 2 {one} {"one"|"i"|"1"} + 3 {3} {"3"|"iii"|"three"} + 4 {3*} {"3"|"iii"|"three" *} +} { + do_execsql_test 4.1.$tn { + SELECT fts5_expr($expr, 'tokenize=tclnum') + } [list $res] +} + +do_execsql_test 4.2.1 { + CREATE VIRTUAL TABLE xx USING fts5(x, tokenize=tclnum, detail=%DETAIL%); + INSERT INTO xx VALUES('one two'); + INSERT INTO xx VALUES('three four'); +} + +do_execsql_test 4.2.2 { + SELECT rowid FROM xx WHERE xx MATCH '2' +} {1} + +do_execsql_test 4.2.3 { + SELECT rowid FROM xx WHERE xx MATCH '3' +} {2} + +do_test 5.0 { + execsql { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, tokenize=tclnum, detail=%DETAIL%) + } + foreach {rowid a b} { + 1 {four v 4 i three} {1 3 five five 4 one} + 2 {5 1 3 4 i} {2 2 v two 4} + 3 {5 i 5 2 four 4 1} {iii ii five two 1} + 4 {ii four 4 one 5 three five} {one 5 1 iii 4 3} + 5 {three i v i four 4 1} {ii five five five iii} + 6 {4 2 ii two 2 iii} {three 1 four 4 iv 1 iv} + 7 {ii ii two three 2 5} {iii i ii iii iii one one} + 8 {2 ii i two 3 three 2} {two iv v iii 3 five} + 9 {i 2 iv 3 five four v} {iii 4 three i three ii 1} + } { + execsql { INSERT INTO t1(rowid, a, b) VALUES($rowid, $a, $b) } + } +} {} + + +foreach {tn q res} { + 1 {one} { + 1 {four v 4 [i] three} {[1] 3 five five 4 [one]} + 2 {5 [1] 3 4 [i]} {2 2 v two 4} + 3 {5 [i] 5 2 four 4 [1]} {iii ii five two [1]} + 4 {ii four 4 [one] 5 three five} {[one] 5 [1] iii 4 3} + 5 {three [i] v [i] four 4 [1]} {ii five five five iii} + 6 {4 2 ii two 2 iii} {three [1] four 4 iv [1] iv} + 7 {ii ii two three 2 5} {iii [i] ii iii iii [one] [one]} + 8 {2 ii [i] two 3 three 2} {two iv v iii 3 five} + 9 {[i] 2 iv 3 five four v} {iii 4 three [i] three ii [1]} + } + 2 {five four} { + 1 {[four] [v] [4] i three} {1 3 [five] [five] [4] one} + 2 {[5] 1 3 [4] i} {2 2 [v] two [4]} + 3 {[5] i [5] 2 [four] [4] 1} {iii ii [five] two 1} + 4 {ii [four] [4] one [5] three [five]} {one [5] 1 iii [4] 3} + 5 {three i [v] i [four] [4] 1} {ii [five] [five] [five] iii} + 8 {2 ii i two 3 three 2} {two [iv] [v] iii 3 [five]} + 9 {i 2 [iv] 3 [five] [four] [v]} {iii [4] three i three ii 1} + } + 3 {one OR two OR iii OR 4 OR v} { + 1 {[four] [v] [4] [i] [three]} {[1] [3] [five] [five] [4] [one]} + 2 {[5] [1] [3] [4] [i]} {[2] [2] [v] [two] [4]} + 3 {[5] [i] [5] [2] [four] [4] [1]} {[iii] [ii] [five] [two] [1]} + 4 {[ii] [four] [4] [one] [5] [three] [five]} {[one] [5] [1] [iii] [4] [3]} + 5 {[three] [i] [v] [i] [four] [4] [1]} {[ii] [five] [five] [five] [iii]} + 6 {[4] [2] [ii] [two] [2] [iii]} {[three] [1] [four] [4] [iv] [1] [iv]} + 7 {[ii] [ii] [two] [three] [2] [5]} {[iii] [i] [ii] [iii] [iii] [one] [one]} + 8 {[2] [ii] [i] [two] [3] [three] [2]} {[two] [iv] [v] [iii] [3] [five]} + 9 {[i] [2] [iv] [3] [five] [four] [v]} {[iii] [4] [three] [i] [three] [ii] [1]} + } + + 4 {5 + 1} { + 2 {[5 1] 3 4 i} {2 2 v two 4} + 3 {[5 i] 5 2 four 4 1} {iii ii five two 1} + 4 {ii four 4 one 5 three five} {one [5 1] iii 4 3} + 5 {three i [v i] four 4 1} {ii five five five iii} + } + + 5 {one + two + three} { + 7 {ii ii two three 2 5} {iii [i ii iii] iii one one} + 8 {2 ii [i two 3] three 2} {two iv v iii 3 five} + } + + 6 {"v v"} { + 1 {four v 4 i three} {1 3 [five five] 4 one} + 5 {three i v i four 4 1} {ii [five five five] iii} + } +} { + if {![fts5_expr_ok $q t1]} continue + do_execsql_test 5.1.$tn { + SELECT rowid, highlight(t1, 0, '[', ']'), highlight(t1, 1, '[', ']') + FROM t1 WHERE t1 MATCH $q + } $res +} + +# Test that the xQueryPhrase() API works with synonyms. +# +proc mit {blob} { + set scan(littleEndian) i* + set scan(bigEndian) I* + binary scan $blob $scan($::tcl_platform(byteOrder)) r + return $r +} +db func mit mit +sqlite3_fts5_register_matchinfo db + +foreach {tn q res} { + 1 {one} { + 1 {1 11 7 2 12 6} 2 {2 11 7 0 12 6} + 3 {2 11 7 1 12 6} 4 {1 11 7 2 12 6} + 5 {3 11 7 0 12 6} 6 {0 11 7 2 12 6} + 7 {0 11 7 3 12 6} 8 {1 11 7 0 12 6} + 9 {1 11 7 2 12 6} + } +} { + do_execsql_test 5.2.$tn { + SELECT rowid, mit(matchinfo(t1, 'x')) FROM t1 WHERE t1 MATCH $q + } $res +} + +#------------------------------------------------------------------------- +# Test terms with more than 4 synonyms. +# +reset_db +sqlite3_fts5_create_tokenizer db tcl tcl_create +proc tcl_tokenize {tflags text} { + foreach {w iStart iEnd} [fts5_tokenize_split $text] { + sqlite3_fts5_token $w $iStart $iEnd + if {$tflags=="query" && [string length $w]==1} { + for {set i 2} {$i<=10} {incr i} { + sqlite3_fts5_token -colo [string repeat $w $i] $iStart $iEnd + } + } + } +} + +do_execsql_test 6.0.1 { + CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize=tcl, detail=%DETAIL%); + INSERT INTO t1 VALUES('yy xx qq'); + INSERT INTO t1 VALUES('yy xx xx'); +} +if {[fts5_expr_ok "NEAR(y q)" t1]} { + do_execsql_test 6.0.2 { + SELECT * FROM t1 WHERE t1 MATCH 'NEAR(y q)'; + } {{yy xx qq}} +} + +do_test 6.0.3 { + execsql { + CREATE VIRTUAL TABLE t2 USING fts5(a, b, tokenize=tcl, detail=%DETAIL%) + } + foreach {rowid a b} { + 1 {yyyy vvvvv qq oo yyyyyy vvvv eee} {ffff uu r qq aaaa} + 2 {ww oooooo bbbbb ssssss mm} {ffffff yy iiii rr s ccc qqqqq} + 3 {zzzz llll gggggg cccc uu} {hhhhhh aaaa ppppp rr ee jjjj} + 4 {r f i rrrrrr ww hhh} {aa yyy t x aaaaa ii} + 5 {fffff mm vvvv ooo ffffff kkkk tttt} {cccccc bb e zzz d n} + 6 {iii dddd hh qqqq ddd ooo} {ttt d c b aaaaaa qqqq} + 7 {jjjj rrrr v zzzzz u tt t} {ppppp pp dddd mm hhh uuu} + 8 {gggg rrrrrr kkkk vvvv gggg jjjjjj b} {dddddd jj r w cccc wwwwww ss} + 9 {kkkkk qqq oooo e tttttt mmm} {e ss qqqqqq hhhh llllll gg} + } { + execsql { INSERT INTO t2(rowid, a, b) VALUES($rowid, $a, $b) } + } +} {} + +foreach {tn q res} { + 1 {a} { + 1 {yyyy vvvvv qq oo yyyyyy vvvv eee} {ffff uu r qq [aaaa]} + 3 {zzzz llll gggggg cccc uu} {hhhhhh [aaaa] ppppp rr ee jjjj} + 4 {r f i rrrrrr ww hhh} {[aa] yyy t x [aaaaa] ii} + 6 {iii dddd hh qqqq ddd ooo} {ttt d c b [aaaaaa] qqqq} + } + + 2 {a AND q} { + 1 {yyyy vvvvv [qq] oo yyyyyy vvvv eee} {ffff uu r [qq] [aaaa]} + 6 {iii dddd hh [qqqq] ddd ooo} {ttt d c b [aaaaaa] [qqqq]} + } + + 3 {o OR (q AND a)} { + 1 {yyyy vvvvv [qq] [oo] yyyyyy vvvv eee} {ffff uu r [qq] [aaaa]} + 2 {ww [oooooo] bbbbb ssssss mm} {ffffff yy iiii rr s ccc qqqqq} + 5 {fffff mm vvvv [ooo] ffffff kkkk tttt} {cccccc bb e zzz d n} + 6 {iii dddd hh [qqqq] ddd [ooo]} {ttt d c b [aaaaaa] [qqqq]} + 9 {kkkkk qqq [oooo] e tttttt mmm} {e ss qqqqqq hhhh llllll gg} + } + + 4 {NEAR(q y, 20)} { + 1 {[yyyy] vvvvv [qq] oo [yyyyyy] vvvv eee} {ffff uu r qq aaaa} + 2 {ww oooooo bbbbb ssssss mm} {ffffff [yy] iiii rr s ccc [qqqqq]} + } +} { + if {![fts5_expr_ok $q t2]} continue + + do_execsql_test 6.1.$tn.asc { + SELECT rowid, highlight(t2, 0, '[', ']'), highlight(t2, 1, '[', ']') + FROM t2 WHERE t2 MATCH $q + } $res + + set res2 [list] + foreach {rowid a b} $res { + set res2 [concat [list $rowid $a $b] $res2] + } + + do_execsql_test 6.1.$tn.desc { + SELECT rowid, highlight(t2, 0, '[', ']'), highlight(t2, 1, '[', ']') + FROM t2 WHERE t2 MATCH $q ORDER BY rowid DESC + } $res2 +} + +do_execsql_test 6.2.1 { + INSERT INTO t2(rowid, a, b) VALUES(13, + 'x xx xxx xxxx xxxxx xxxxxx xxxxxxx', 'y yy yyy yyyy yyyyy yyyyyy yyyyyyy' + ); + SELECT rowid, highlight(t2, 0, '<', '>'), highlight(t2, 1, '(', ')') + FROM t2 WHERE t2 MATCH 'x OR y' +} { + 1 { vvvvv qq oo vvvv eee} {ffff uu r qq aaaa} + 2 {ww oooooo bbbbb ssssss mm} {ffffff (yy) iiii rr s ccc qqqqq} + 4 {r f i rrrrrr ww hhh} {aa (yyy) t (x) aaaaa ii} + 13 { } + {(y) (yy) (yyy) (yyyy) (yyyyy) (yyyyyy) (yyyyyyy)} +} + +#------------------------------------------------------------------------- +# Test that the xColumnSize() API is not confused by colocated tokens. +# +reset_db +sqlite3_fts5_create_tokenizer db tcl tcl_create +fts5_aux_test_functions db +proc tcl_tokenize {tflags text} { + foreach {w iStart iEnd} [fts5_tokenize_split $text] { + sqlite3_fts5_token $w $iStart $iEnd + if {[string length $w]==1} { + for {set i 2} {$i<=10} {incr i} { + sqlite3_fts5_token -colo [string repeat $w $i] $iStart $iEnd + } + } + } +} + +do_execsql_test 7.0.1 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, columnsize=1, tokenize=tcl, detail=%DETAIL%); + INSERT INTO t1 VALUES('0 2 3', '4 5 6 7'); + INSERT INTO t1 VALUES('8 9', '0 0 0 0 0 0 0 0 0 0'); + SELECT fts5_test_columnsize(t1) FROM t1 WHERE t1 MATCH '000 AND 00 AND 0'; +} {{3 4} {2 10}} + +do_execsql_test 7.0.2 { + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +do_execsql_test 7.1.1 { + CREATE VIRTUAL TABLE t2 USING fts5(a, b, columnsize=0, tokenize=tcl, detail=%DETAIL%); + INSERT INTO t2 VALUES('0 2 3', '4 5 6 7'); + INSERT INTO t2 VALUES('8 9', '0 0 0 0 0 0 0 0 0 0'); + SELECT fts5_test_columnsize(t2) FROM t2 WHERE t2 MATCH '000 AND 00 AND 0'; +} {{3 4} {2 10}} + +do_execsql_test 7.1.2 { + INSERT INTO t2(t2) VALUES('integrity-check'); +} + +} ;# foreach_detail_mode + +finish_test + diff --git a/ext/fts5/test/fts5synonym2.test b/ext/fts5/test/fts5synonym2.test new file mode 100644 index 0000000..7e92822 --- /dev/null +++ b/ext/fts5/test/fts5synonym2.test @@ -0,0 +1,164 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on custom tokenizers that support synonyms. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5synonym2 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach tok {query document} { +foreach_detail_mode $testprefix { + +fts5_tclnum_register db +fts5_aux_test_functions db + +proc fts5_test_bothlist {cmd} { + + for {set i 0} {$i < [$cmd xPhraseCount]} {incr i} { + set bFirst 1 + $cmd xPhraseColumnForeach $i c { + lappend CL $i.$c + if {$bFirst} { $cmd xPhraseForeach $i c o { lappend PL $i.$c.$o } } + set bFirst 0 + } + } + + list [sort_poslist $PL] $CL +} +sqlite3_fts5_create_function db fts5_test_bothlist fts5_test_bothlist + +proc fts5_rowid {cmd} { expr [$cmd xColumnText -1] } +sqlite3_fts5_create_function db fts5_rowid fts5_rowid + +do_execsql_test 1.$tok.0.1 " + CREATE VIRTUAL TABLE ss USING fts5(a, b, + tokenize='tclnum $tok', detail=%DETAIL%); + INSERT INTO ss(ss, rank) VALUES('rank', 'fts5_rowid()'); +" + +do_execsql_test 1.$tok.0.2 { + INSERT INTO ss VALUES('5 5 five seven 3 seven i', '2 1 5 0 two 1 i'); + INSERT INTO ss VALUES('six ix iii 7 i vii iii', 'one seven nine 4 9 1 vi'); + INSERT INTO ss VALUES('6 viii i five six zero seven', '5 v iii iv iv 3'); + INSERT INTO ss VALUES('9 ii six 8 1 6', 'six 4 iv iv 7'); + INSERT INTO ss VALUES('1 5 4 eight ii iv iii', 'nine 2 eight ix v vii'); + INSERT INTO ss VALUES('one 7 seven six 2 two', '1 2 four 7 4 3 4'); + INSERT INTO ss VALUES('eight iv 4 nine vii six 1', '5 6 v one zero 4'); + INSERT INTO ss VALUES('v 9 8 iii 4', '9 4 seven two vi vii'); + INSERT INTO ss VALUES('3 ix two 9 0 nine i', 'five ii nine two viii i five'); + INSERT INTO ss VALUES('six iii 9 two eight 2', 'nine i nine vii nine'); + INSERT INTO ss VALUES('6 three zero seven vii five', '8 vii ix 0 7 seven'); + INSERT INTO ss VALUES('8 vii 8 7 3 4', 'eight iii four viii nine iv three'); + INSERT INTO ss VALUES('4 v 7 two 0 one 8', 'vii 1 two five i zero 9'); + INSERT INTO ss VALUES('3 ii vii vi eight', '8 4 ix one three eight'); + INSERT INTO ss VALUES('iv eight seven 6 9 seven', 'one vi two five seven'); + INSERT INTO ss VALUES('i i 5 i v vii eight', '2 seven i 2 2 four'); + INSERT INTO ss VALUES('0 i iii nine 3 ix five', '0 eight iv 0 six 2'); + INSERT INTO ss VALUES('iv vii three 3 9 one 8', '2 ii 6 eight ii six six'); + INSERT INTO ss VALUES('eight one two nine six', '8 9 3 viii vi'); + INSERT INTO ss VALUES('one 0 four ii eight one 3', 'iii eight vi vi vi'); + INSERT INTO ss VALUES('4 0 eight 0 0', '1 four one vii seven ii'); + INSERT INTO ss VALUES('1 zero nine 2 2', 'viii iv two vi nine v iii'); + INSERT INTO ss VALUES('5 five viii four four vi', '8 five 7 vii 6 4'); + INSERT INTO ss VALUES('7 ix four 8 vii', 'nine three nine ii ix vii'); + INSERT INTO ss VALUES('nine iv v i 0 v', 'two iv vii six i ix 4'); + INSERT INTO ss VALUES('one v v one viii 3 8', '2 1 3 five iii'); + INSERT INTO ss VALUES('six ii 5 nine 4 viii seven', 'eight i ix ix 7 four'); + INSERT INTO ss VALUES('9 ii two seven three 7 0', 'six viii seven 7 five'); + INSERT INTO ss VALUES('five two 4 viii nine', '9 7 nine zero 1 two one'); + INSERT INTO ss VALUES('viii 8 iii i ii 8 3', '4 2 7 v 8 8'); + INSERT INTO ss VALUES('four vii 4 iii zero 0 vii', '3 viii iii zero 9 i'); + INSERT INTO ss VALUES('0 seven v five i five v', 'one 4 2 ix 9'); + INSERT INTO ss VALUES('two 5 two two ix 4 1', '3 nine ii v nine 3 five'); + INSERT INTO ss VALUES('five 5 7 4 6 vii', 'three 2 ix 2 8 6'); + INSERT INTO ss VALUES('six iii vi iv seven eight', '8 six 7 0 4'); + INSERT INTO ss VALUES('vi vi iv 3 0 one one', '9 6 eight ix iv'); + INSERT INTO ss VALUES('7 2 2 iii 0', '0 0 seven 1 nine'); + INSERT INTO ss VALUES('8 6 iv six ii', 'iv 6 3 4 ii five'); + INSERT INTO ss VALUES('0 two two seven ii', 'vii ix four 4 zero vi vi'); + INSERT INTO ss VALUES('2 one eight 8 9 7', 'vi 3 0 3 vii'); + INSERT INTO ss VALUES('iii ii ix iv three', 'vi i 6 1 two'); + INSERT INTO ss VALUES('eight four nine 8 seven', 'one three i nine iii one'); + INSERT INTO ss VALUES('iii seven five ix 8', 'ii 7 seven 0 four ii'); + INSERT INTO ss VALUES('four 0 1 5 two', 'iii 9 5 ii ii 2 4'); + INSERT INTO ss VALUES('iii nine four vi 8 five six', 'i i ii seven vi vii'); + INSERT INTO ss VALUES('eight vii eight six 3', 'i vii 1 six 9 vii'); + INSERT INTO ss VALUES('9 0 viii viii five', 'i 1 viii ix 3 4'); + INSERT INTO ss VALUES('three nine 5 nine viii four zero', 'ii i 1 5 2 viii'); + INSERT INTO ss VALUES('5 vii three 9 four', 'three five one 7 2 eight one'); +} + +foreach {tn expr} { + 2.1 "one OR two OR three OR four" + + 1.1 "one" 1.2 "two" 1.3 "three" 1.4 "four" + 1.5 "v" 1.6 "vi" 1.7 "vii" 1.8 "viii" + 1.9 "9" 1.10 "0" 1.11 "1" 1.12 "2" + + 2.1 "one OR two OR three OR four" + 2.2 "(one AND two) OR (three AND four)" + 2.3 "(one AND two) OR (three AND four) NOT five" + 2.4 "(one AND two) NOT 6" + + 3.1 "b:one AND a:two" + 3.2 "b:one OR a:two" + 3.3 "a:one OR b:1 OR {a b} : i" + + 4.1 "NEAR(one two, 2)" + 4.2 "NEAR(one two three, 2)" + 4.3 "NEAR(eight nine, 1) OR NEAR(six seven, 1)" +} { + if {[fts5_expr_ok $expr ss]==0} { + do_test 1.$tok.$tn.OMITTED { list } [list] + continue + } + + set res [fts5_query_data $expr ss ASC ::tclnum_syn] + do_execsql_test 1.$tok.$tn.[llength $res].asc.1 { + SELECT rowid, fts5_test_poslist2(ss), fts5_test_collist(ss) FROM ss($expr) + } $res + + do_execsql_test 1.$tok.$tn.[llength $res].asc.2 { + SELECT rowid, fts5_test_poslist(ss), fts5_test_collist(ss) FROM ss($expr) + } $res + + do_execsql_test 1.$tok.$tn.[llength $res].asc.2 { + SELECT rowid, fts5_test_poslist2(ss), fts5_test_collist(ss) FROM ss($expr) + ORDER BY rank ASC + } $res + + set res2 [list] + foreach {a b c} $res { lappend res2 $a $c $b } + do_execsql_test 1.$tok.$tn.[llength $res].asc.3 { + SELECT rowid, fts5_test_collist(ss), fts5_test_poslist2(ss) FROM ss($expr) + } $res2 + + set res3 [list] + foreach {a b c} $res { lappend res3 $a [list $b $c] } + do_execsql_test 1.$tok.$tn.[llength $res].asc.3 { + SELECT rowid, fts5_test_bothlist(ss) FROM ss($expr) + } $res3 + + +} + +} +} + +finish_test + diff --git a/ext/fts5/test/fts5tok1.test b/ext/fts5/test/fts5tok1.test new file mode 100644 index 0000000..6ba1700 --- /dev/null +++ b/ext/fts5/test/fts5tok1.test @@ -0,0 +1,115 @@ +# 2016 Jan 15 +# +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +ifcapable !fts5 { finish_test ; return } +set ::testprefix fts5tok1 + + +sqlite3_fts5_register_fts5tokenize db + +#------------------------------------------------------------------------- +# Simple test cases. Using the default (ascii) tokenizer. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5tokenize(ascii); + CREATE VIRTUAL TABLE t2 USING fts5tokenize(); + CREATE VIRTUAL TABLE t3 USING fts5tokenize( + ascii, 'separators', 'xyz', tokenchars, '''' + ); +} + +foreach {tn tbl} {1 t1 2 t2 3 t3} { + do_execsql_test 1.$tn.1 "SELECT input, * FROM $tbl ('one two three')" { + {one two three} one 0 3 0 + {one two three} two 4 7 1 + {one two three} three 8 13 2 + } + + do_execsql_test 1.$tn.2 " + SELECT token FROM $tbl WHERE input = 'OnE tWo tHrEe' + " { + one two three + } +} + +do_execsql_test 1.4 { + SELECT token FROM t3 WHERE input = '1x2x3x' +} {1 2 3} + +do_execsql_test 1.5 { + SELECT token FROM t1 WHERE input = '1x2x3x' +} {1x2x3x} + +do_execsql_test 1.6 { + SELECT token FROM t3 WHERE input = '1''2x3x' +} {1'2 3} + +do_execsql_test 1.7 { + SELECT token FROM t3 WHERE input = '' +} {} + +do_execsql_test 1.8 { + SELECT token FROM t3 WHERE input = NULL +} {} + +do_execsql_test 1.9 { + SELECT input, * FROM t3 WHERE input = 123 +} {123 123 0 3 0} + +do_execsql_test 1.10 { + SELECT input, * FROM t1 WHERE input = 'a b c' AND token = 'b'; +} { + {a b c} b 2 3 1 +} + +do_execsql_test 1.11 { + SELECT input, * FROM t1 WHERE token = 'b' AND input = 'a b c'; +} { + {a b c} b 2 3 1 +} + +do_execsql_test 1.12 { + SELECT input, * FROM t1 WHERE input < 'b' AND input = 'a b c'; +} { + {a b c} a 0 1 0 + {a b c} b 2 3 1 + {a b c} c 4 5 2 +} + +do_execsql_test 1.13.1 { + CREATE TABLE c1(x); + INSERT INTO c1(x) VALUES('a b c'); + INSERT INTO c1(x) VALUES('d e f'); +} +do_execsql_test 1.13.2 { + SELECT c1.*, input, t1.* FROM c1, t1 WHERE input = x AND c1.rowid=t1.rowid; +} { + {a b c} {a b c} a 0 1 0 + {d e f} {d e f} e 2 3 1 +} + + +#------------------------------------------------------------------------- +# Error cases. +# +do_catchsql_test 2.0 { + CREATE VIRTUAL TABLE tX USING fts5tokenize(nosuchtokenizer); +} {1 {vtable constructor failed: tX}} + +do_catchsql_test 2.1 { + CREATE VIRTUAL TABLE t4 USING fts5tokenize; + SELECT * FROM t4; +} {1 {SQL logic error or missing database}} + + +finish_test diff --git a/ext/fts5/test/fts5tok2.test b/ext/fts5/test/fts5tok2.test new file mode 100644 index 0000000..77c7e1e --- /dev/null +++ b/ext/fts5/test/fts5tok2.test @@ -0,0 +1,47 @@ +# 2016 Jan 15 +# +# 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. +# +#************************************************************************* +# + +source [file join [file dirname [info script]] fts5_common.tcl] +ifcapable !fts5||!fts3 { finish_test ; return } +set ::testprefix fts5tok2 + +sqlite3_fts5_register_fts5tokenize db + +#------------------------------------------------------------------------- +# Simple test cases. Using the default (ascii) tokenizer. +# +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t5 USING fts5tokenize(unicode61); + CREATE VIRTUAL TABLE t3 USING fts3tokenize(unicode61); +} + +do_test 1.1 { + array unset -nocomplain A + + for {set i 1} {$i < 65536} {incr i} { + set input [format "abc%cxyz" $i] + set expect [execsql { + SELECT input, token, start, end FROM t3 WHERE input=$input + }] + + incr A([llength $expect]) + + set res [execsql { + SELECT input, token, start, end FROM t5($input) + }] + if {$res != $expect} {error "failed at i=$i"} + } +} {} + +do_test 1.1.nTokenChars=$A(4).nSeparators=$A(8) {} {} + +finish_test diff --git a/ext/fts5/test/fts5tokenizer.test b/ext/fts5/test/fts5tokenizer.test new file mode 100644 index 0000000..9316d3c --- /dev/null +++ b/ext/fts5/test/fts5tokenizer.test @@ -0,0 +1,266 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on the built-in fts5 tokenizers. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5tokenizer + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, tokenize=porter); + DROP TABLE ft1; +} +do_execsql_test 1.1 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, tokenize='porter'); + DROP TABLE ft1; +} +do_execsql_test 1.2 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, tokenize = porter); + DROP TABLE ft1; +} +do_execsql_test 1.3 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, tokenize = 'porter'); + DROP TABLE ft1; +} +do_execsql_test 1.4 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, tokenize = 'porter ascii'); + DROP TABLE ft1; +} + +do_catchsql_test 1.5 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, tokenize = 'nosuch'); +} {1 {no such tokenizer: nosuch}} + +do_catchsql_test 1.6 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, tokenize = 'porter nosuch'); +} {1 {error in tokenizer constructor}} + +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE ft1 USING fts5(x, tokenize=porter); + INSERT INTO ft1 VALUES('embedded databases'); +} +do_execsql_test 2.1 { SELECT rowid FROM ft1 WHERE ft1 MATCH 'embedding' } 1 +do_execsql_test 2.2 { SELECT rowid FROM ft1 WHERE ft1 MATCH 'database' } 1 +do_execsql_test 2.3 { + SELECT rowid FROM ft1 WHERE ft1 MATCH 'database embedding' +} 1 + +proc tcl_create {args} { + set ::targs $args + error "failed" +} +sqlite3_fts5_create_tokenizer db tcl tcl_create + +foreach {tn directive expected} { + 1 {tokenize='tcl a b c'} {a b c} + 2 {tokenize='tcl ''d'' ''e'' ''f'''} {d e f} + 3 {tokenize="tcl 'g' 'h' 'i'"} {g h i} + 4 {tokenize = tcl} {} +} { + do_catchsql_test 3.$tn.1 " + CREATE VIRTUAL TABLE ft2 USING fts5(x, $directive) + " {1 {error in tokenizer constructor}} + do_test 3.$tn.2 { set ::targs } $expected +} + +do_catchsql_test 4.1 { + CREATE VIRTUAL TABLE ft2 USING fts5(x, tokenize = tcl abc); +} {1 {parse error in "tokenize = tcl abc"}} +do_catchsql_test 4.2 { + CREATE VIRTUAL TABLE ft2 USING fts5(x y) +} {1 {unrecognized column option: y}} + +#------------------------------------------------------------------------- +# Test the "separators" and "tokenchars" options a bit. +# +foreach {tn tokenizer} {1 ascii 2 unicode61} { + reset_db + set T "$tokenizer tokenchars ',.:' separators 'xyz'" + execsql "CREATE VIRTUAL TABLE t1 USING fts5(x, tokenize = \"$T\")" + do_execsql_test 5.$tn.1 { + INSERT INTO t1 VALUES('abcxdefyghizjkl.mno,pqr:stu/vwx+yz'); + } + foreach {tn2 token res} { + 1 abc 1 2 def 1 3 ghi 1 4 jkl {} + 5 mno {} 6 pqr {} 7 stu {} 8 jkl.mno,pqr:stu 1 + 9 vw 1 + } { + do_execsql_test 5.$tn.2.$tn2 " + SELECT rowid FROM t1 WHERE t1 MATCH '\"$token\"' + " $res + } +} + +#------------------------------------------------------------------------- +# Miscellaneous tests for the ascii tokenizer. +# +# 5.1.*: Test that the ascii tokenizer ignores non-ASCII characters in the +# 'separators' option. But unicode61 does not. +# +# 5.2.*: An option without an argument is an error. +# + +do_test 5.1.1 { + execsql " + CREATE VIRTUAL TABLE a1 USING fts5(x, tokenize=`ascii separators '\u1234'`); + INSERT INTO a1 VALUES('abc\u1234def'); + " + execsql { SELECT rowid FROM a1 WHERE a1 MATCH 'def' } +} {} + +do_test 5.1.2 { + execsql " + CREATE VIRTUAL TABLE a2 USING fts5( + x, tokenize=`unicode61 separators '\u1234'`); + INSERT INTO a2 VALUES('abc\u1234def'); + " + execsql { SELECT rowid FROM a2 WHERE a2 MATCH 'def' } +} {1} + +do_catchsql_test 5.2 { + CREATE VIRTUAL TABLE a3 USING fts5(x, y, tokenize = 'ascii tokenchars'); +} {1 {error in tokenizer constructor}} +do_catchsql_test 5.3 { + CREATE VIRTUAL TABLE a3 USING fts5(x, y, tokenize = 'ascii opt arg'); +} {1 {error in tokenizer constructor}} + +#------------------------------------------------------------------------- +# Test that the ASCII and unicode61 tokenizers both handle SQLITE_DONE +# correctly. +# + +proc test_token_cb {varname token iStart iEnd} { + upvar $varname var + lappend var $token + if {[llength $var]==3} { return "SQLITE_DONE" } + return "SQLITE_OK" +} + +proc tokenize {cmd} { + set res [list] + $cmd xTokenize [$cmd xColumnText 0] [list test_token_cb res] + set res +} +sqlite3_fts5_create_function db tokenize tokenize + +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE x1 USING fts5(a, tokenize=ascii); + INSERT INTO x1 VALUES('q w e r t y'); + INSERT INTO x1 VALUES('y t r e w q'); + SELECT tokenize(x1) FROM x1 WHERE x1 MATCH 'e AND r'; +} { + {q w e} {y t r} +} + +do_execsql_test 6.1 { + CREATE VIRTUAL TABLE x2 USING fts5(a, tokenize=unicode61); + INSERT INTO x2 VALUES('q w e r t y'); + INSERT INTO x2 VALUES('y t r e w q'); + SELECT tokenize(x2) FROM x2 WHERE x2 MATCH 'e AND r'; +} { + {q w e} {y t r} +} + + +#------------------------------------------------------------------------- +# Miscellaneous tests for the unicode tokenizer. +# +do_catchsql_test 6.1 { + CREATE VIRTUAL TABLE a3 USING fts5(x, y, tokenize = 'unicode61 tokenchars'); +} {1 {error in tokenizer constructor}} +do_catchsql_test 6.2 { + CREATE VIRTUAL TABLE a3 USING fts5(x, y, tokenize = 'unicode61 a b'); +} {1 {error in tokenizer constructor}} +do_catchsql_test 6.3 { + CREATE VIRTUAL TABLE a3 USING fts5( + x, y, tokenize = 'unicode61 remove_diacritics 2' + ); +} {1 {error in tokenizer constructor}} +do_catchsql_test 6.4 { + CREATE VIRTUAL TABLE a3 USING fts5( + x, y, tokenize = 'unicode61 remove_diacritics 10' + ); +} {1 {error in tokenizer constructor}} + +#------------------------------------------------------------------------- +# Porter tokenizer with very large tokens. +# +set a [string repeat a 100] +set b [string repeat b 500] +set c [string repeat c 1000] +do_execsql_test 7.0 { + CREATE VIRTUAL TABLE e5 USING fts5(x, tokenize=porter); + INSERT INTO e5 VALUES($a || ' ' || $b); + INSERT INTO e5 VALUES($b || ' ' || $c); + INSERT INTO e5 VALUES($c || ' ' || $a); +} + +do_execsql_test 7.1 {SELECT rowid FROM e5 WHERE e5 MATCH $a} { 1 3 } +do_execsql_test 7.2 {SELECT rowid FROM e5 WHERE e5 MATCH $b} { 1 2 } +do_execsql_test 7.3 {SELECT rowid FROM e5 WHERE e5 MATCH $c} { 2 3 } + +#------------------------------------------------------------------------- +# Test the 'separators' option with the unicode61 tokenizer. +# +do_execsql_test 8.1 { + BEGIN; + CREATE VIRTUAL TABLE e6 USING fts5(x, + tokenize="unicode61 separators ABCDEFGHIJKLMNOPQRSTUVWXYZ" + ); + INSERT INTO e6 VALUES('theAquickBbrownCfoxDjumpedWoverXtheYlazyZdog'); + CREATE VIRTUAL TABLE e7 USING fts5vocab(e6, 'row'); + SELECT term FROM e7; + ROLLBACK; +} { + brown dog fox jumped lazy over quick the +} + +do_execsql_test 8.2 [subst { + BEGIN; + CREATE VIRTUAL TABLE e6 USING fts5(x, + tokenize="unicode61 separators '\u0E01\u0E02\u0E03\u0E04\u0E05\u0E06\u0E07'" + ); + INSERT INTO e6 VALUES('the\u0E01quick\u0E01brown\u0E01fox\u0E01' + || 'jumped\u0E01over\u0E01the\u0E01lazy\u0E01dog' + ); + INSERT INTO e6 VALUES('\u0E08\u0E07\u0E09'); + CREATE VIRTUAL TABLE e7 USING fts5vocab(e6, 'row'); + SELECT term FROM e7; + ROLLBACK; +}] [subst { + brown dog fox jumped lazy over quick the \u0E08 \u0E09 +}] + +# Test that the porter tokenizer correctly passes arguments through to +# its parent tokenizer. +do_execsql_test 8.3 { + BEGIN; + CREATE VIRTUAL TABLE e6 USING fts5(x, + tokenize="porter unicode61 separators ABCDEFGHIJKLMNOPQRSTUVWXYZ" + ); + INSERT INTO e6 VALUES('theAquickBbrownCfoxDjumpedWoverXtheYlazyZdog'); + CREATE VIRTUAL TABLE e7 USING fts5vocab(e6, 'row'); + SELECT term FROM e7; + ROLLBACK; +} { + brown dog fox jump lazi over quick the +} + +finish_test + diff --git a/ext/fts5/test/fts5unicode.test b/ext/fts5/test/fts5unicode.test new file mode 100644 index 0000000..46f4c4f --- /dev/null +++ b/ext/fts5/test/fts5unicode.test @@ -0,0 +1,62 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on the fts5 tokenizers +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5unicode + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc tokenize_test {tn tokenizer input output} { + uplevel [list do_test $tn [subst -nocommands { + set ret {} + foreach {z s e} [sqlite3_fts5_tokenize db {$tokenizer} {$input}] { + lappend ret [set z] + } + set ret + }] [list {*}$output]] +} + +foreach {tn t} {1 ascii 2 unicode61} { + tokenize_test 1.$tn.0 $t {A B C D} {a b c d} + tokenize_test 1.$tn.1 $t {May you share freely,} {may you share freely} + tokenize_test 1.$tn.2 $t {..May...you.shAre.freely} {may you share freely} + tokenize_test 1.$tn.3 $t {} {} +} + +#------------------------------------------------------------------------- +# Check that "unicode61" really is the default tokenizer. +# + +do_execsql_test 2.0 " + CREATE VIRTUAL TABLE t1 USING fts5(x); + CREATE VIRTUAL TABLE t2 USING fts5(x, tokenize = unicode61); + CREATE VIRTUAL TABLE t3 USING fts5(x, tokenize = ascii); + INSERT INTO t1 VALUES('\xC0\xC8\xCC'); + INSERT INTO t2 VALUES('\xC0\xC8\xCC'); + INSERT INTO t3 VALUES('\xC0\xC8\xCC'); +" +breakpoint +do_execsql_test 2.1 " + SELECT 't1' FROM t1 WHERE t1 MATCH '\xE0\xE8\xEC'; + SELECT 't2' FROM t2 WHERE t2 MATCH '\xE0\xE8\xEC'; + SELECT 't3' FROM t3 WHERE t3 MATCH '\xE0\xE8\xEC'; +" {t1 t2} + + +finish_test + diff --git a/ext/fts5/test/fts5unicode2.test b/ext/fts5/test/fts5unicode2.test new file mode 100644 index 0000000..d3ff512 --- /dev/null +++ b/ext/fts5/test/fts5unicode2.test @@ -0,0 +1,589 @@ +# 2012 May 25 +# +# 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 tests in this file focus on testing the "unicode" FTS tokenizer. +# +# This is a modified copy of FTS4 test file "fts4_unicode.test". +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5unicode2 + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc do_unicode_token_test {tn input res} { + uplevel [list do_test $tn [list \ + sqlite3_fts5_tokenize -subst db "unicode61 remove_diacritics 0" $input + ] [list {*}$res]] +} + +proc do_unicode_token_test2 {tn input res} { + uplevel [list do_test $tn [list \ + sqlite3_fts5_tokenize -subst db "unicode61" $input + ] [list {*}$res]] +} + +proc do_unicode_token_test3 {tn args} { + set tokenizer [concat unicode61 {*}[lrange $args 0 end-2]] + set input [lindex $args end-1] + set res [lindex $args end] + uplevel [list do_test $tn [list \ + sqlite3_fts5_tokenize -subst db $tokenizer $input + ] [list {*}$res]] +} + +do_unicode_token_test 1.0 {a B c D} {a a b B c c d D} + +do_unicode_token_test 1.1 "\uC4 \uD6 \uDC" \ + "\uE4 \uC4 \uF6 \uD6 \uFC \uDC" + +do_unicode_token_test 1.2 "x\uC4x x\uD6x x\uDCx" \ + "x\uE4x x\uC4x x\uF6x x\uD6x x\uFCx x\uDCx" + +# 0x00DF is a small "sharp s". 0x1E9E is a capital sharp s. +do_unicode_token_test 1.3 "\uDF" "\uDF \uDF" +do_unicode_token_test 1.4 "\u1E9E" "\uDF \u1E9E" + +do_unicode_token_test 1.5 "The quick brown fox" { + the The quick quick brown brown fox fox +} +do_unicode_token_test 1.6 "The\u00bfquick\u224ebrown\u2263fox" { + the The quick quick brown brown fox fox +} + +do_unicode_token_test2 1.7 {a B c D} {a a b B c c d D} +do_unicode_token_test2 1.8 "\uC4 \uD6 \uDC" "a \uC4 o \uD6 u \uDC" + +do_unicode_token_test2 1.9 "x\uC4x x\uD6x x\uDCx" \ + "xax x\uC4x xox x\uD6x xux x\uDCx" + +# Check that diacritics are removed if remove_diacritics=1 is specified. +# And that they do not break tokens. +do_unicode_token_test2 1.10 "xx\u0301xx" "xxxx xx\u301xx" + +# Title-case mappings work +do_unicode_token_test 1.11 "\u01c5" "\u01c6 \u01c5" + +do_unicode_token_test 1.12 "\u00C1abc\u00C2 \u00D1def\u00C3" \ + "\u00E1abc\u00E2 \u00C1abc\u00C2 \u00F1def\u00E3 \u00D1def\u00C3" + +do_unicode_token_test 1.13 "\u00A2abc\u00A3 \u00A4def\u00A5" \ + "abc abc def def" + +#------------------------------------------------------------------------- +# +set docs [list { + Enhance the INSERT syntax to allow multiple rows to be inserted via the + VALUES clause. +} { + Enhance the CREATE VIRTUAL TABLE command to support the IF NOT EXISTS clause. +} { + Added the sqlite3_stricmp() interface as a counterpart to sqlite3_strnicmp(). +} { + Added the sqlite3_db_readonly() interface. +} { + Added the SQLITE_FCNTL_PRAGMA file control, giving VFS implementations the + ability to add new PRAGMA statements or to override built-in PRAGMAs. +} { + Queries of the form: "SELECT max(x), y FROM table" returns the value of y on + the same row that contains the maximum x value. +} { + Added support for the FTS4 languageid option. +} { + Documented support for the FTS4 content option. This feature has actually + been in the code since version 3.7.9 but is only now considered to be + officially supported. +} { + Pending statements no longer block ROLLBACK. Instead, the pending statement + will return SQLITE_ABORT upon next access after the ROLLBACK. +} { + Improvements to the handling of CSV inputs in the command-line shell +} { + Fix a bug introduced in version 3.7.10 that might cause a LEFT JOIN to be + incorrectly converted into an INNER JOIN if the WHERE clause indexable terms + connected by OR. +}] + +set map(a) [list "\u00C4" "\u00E4"] ; # LATIN LETTER A WITH DIAERESIS +set map(e) [list "\u00CB" "\u00EB"] ; # LATIN LETTER E WITH DIAERESIS +set map(i) [list "\u00CF" "\u00EF"] ; # LATIN LETTER I WITH DIAERESIS +set map(o) [list "\u00D6" "\u00F6"] ; # LATIN LETTER O WITH DIAERESIS +set map(u) [list "\u00DC" "\u00FC"] ; # LATIN LETTER U WITH DIAERESIS +set map(y) [list "\u0178" "\u00FF"] ; # LATIN LETTER Y WITH DIAERESIS +set map(h) [list "\u1E26" "\u1E27"] ; # LATIN LETTER H WITH DIAERESIS +set map(w) [list "\u1E84" "\u1E85"] ; # LATIN LETTER W WITH DIAERESIS +set map(x) [list "\u1E8C" "\u1E8D"] ; # LATIN LETTER X WITH DIAERESIS +foreach k [array names map] { + lappend mappings [string toupper $k] [lindex $map($k) 0] + lappend mappings $k [lindex $map($k) 1] +} +proc mapdoc {doc} { + set doc [regsub -all {[[:space:]]+} $doc " "] + string map $::mappings [string trim $doc] +} + +do_test 2.0 { + execsql { CREATE VIRTUAL TABLE t2 USING fts5(tokenize=unicode61, x); } + foreach doc $docs { + set d [mapdoc $doc] + execsql { INSERT INTO t2 VALUES($d) } + } +} {} + +do_test 2.1 { + set q [mapdoc "row"] + execsql { SELECT * FROM t2 WHERE t2 MATCH $q } +} [list [mapdoc { + Queries of the form: "SELECT max(x), y FROM table" returns the value of y on + the same row that contains the maximum x value. +}]] + +foreach {tn query snippet} { + 2 "row" { + ...returns the value of y on the same [row] that contains + the maximum x value. + } + 3 "ROW" { + ...returns the value of y on the same [row] that contains + the maximum x value. + } + 4 "rollback" { + ...[ROLLBACK]. Instead, the pending statement + will return SQLITE_ABORT upon next access after the [ROLLBACK]. + } + 5 "rOllback" { + ...[ROLLBACK]. Instead, the pending statement + will return SQLITE_ABORT upon next access after the [ROLLBACK]. + } + 6 "lang*" { + Added support for the FTS4 [languageid] option. + } +} { + do_test 2.$tn { + set q [mapdoc $query] + execsql { + SELECT snippet(t2, -1, '[', ']', '...', 15) FROM t2 WHERE t2 MATCH $q + } + } [list [mapdoc $snippet]] +} + +#------------------------------------------------------------------------- +# Make sure the unicode61 tokenizer does not crash if it is passed a +# NULL pointer. +reset_db +do_execsql_test 3.1 { + CREATE VIRTUAL TABLE t1 USING fts5(tokenize=unicode61, x, y); + INSERT INTO t1 VALUES(NULL, 'a b c'); +} + +do_execsql_test 3.2 { + SELECT snippet(t1, -1, '[', ']', '...', 15) FROM t1 WHERE t1 MATCH 'b' +} {{a [b] c}} + +do_execsql_test 3.3 { + BEGIN; + DELETE FROM t1; + INSERT INTO t1 VALUES('b b b b b b b b b b b', 'b b b b b b b b b b b b b'); + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 SELECT * FROM t1; + INSERT INTO t1 VALUES('a b c', NULL); + INSERT INTO t1 VALUES('a x c', NULL); + COMMIT; +} + +do_execsql_test 3.4 { + SELECT * FROM t1 WHERE t1 MATCH 'a b'; +} {{a b c} {}} + +#------------------------------------------------------------------------- +# +reset_db + +do_test 4.1 { + set a "abc\uFFFEdef" + set b "abc\uD800def" + set c "\uFFFEdef" + set d "\uD800def" + execsql { + CREATE VIRTUAL TABLE t1 USING fts5(tokenize=unicode61, x); + INSERT INTO t1 VALUES($a); + INSERT INTO t1 VALUES($b); + INSERT INTO t1 VALUES($c); + INSERT INTO t1 VALUES($d); + } + + execsql "CREATE VIRTUAL TABLE t8 USING fts5( + a, b, tokenize=\"unicode61 separators '\uFFFE\uD800\u00BF'\" + )" +} {} + +do_test 4.2 { + set a [binary format c* {0x61 0xF7 0xBF 0xBF 0xBF 0x62}] + set b [binary format c* {0x61 0xF7 0xBF 0xBF 0xBF 0xBF 0x62}] + set c [binary format c* {0x61 0xF7 0xBF 0xBF 0xBF 0xBF 0xBF 0x62}] + set d [binary format c* {0x61 0xF7 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0x62}] + execsql { + INSERT INTO t1 VALUES($a); + INSERT INTO t1 VALUES($b); + INSERT INTO t1 VALUES($c); + INSERT INTO t1 VALUES($d); + } +} {} + +do_test 4.3 { + set a [binary format c* {0xF7 0xBF 0xBF 0xBF}] + set b [binary format c* {0xF7 0xBF 0xBF 0xBF 0xBF}] + set c [binary format c* {0xF7 0xBF 0xBF 0xBF 0xBF 0xBF}] + set d [binary format c* {0xF7 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF}] + execsql { + INSERT INTO t1 VALUES($a); + INSERT INTO t1 VALUES($b); + INSERT INTO t1 VALUES($c); + INSERT INTO t1 VALUES($d); + } +} {} + +do_test 4.4 { + sqlite3_exec_hex db { + CREATE VIRTUAL TABLE t9 USING fts5(a, b, + tokenize="unicode61 separators '%C09004'" + ); + INSERT INTO t9(a) VALUES('abc%88def %89ghi%90'); + } +} {0 {}} + + +#------------------------------------------------------------------------- + +breakpoint +do_unicode_token_test3 5.1 {tokenchars {}} { + sqlite3_reset sqlite3_column_int +} { + sqlite3 sqlite3 + reset reset + sqlite3 sqlite3 + column column + int int +} + +do_unicode_token_test3 5.2 {tokenchars _} { + sqlite3_reset sqlite3_column_int +} { + sqlite3_reset sqlite3_reset + sqlite3_column_int sqlite3_column_int +} + +do_unicode_token_test3 5.3 {separators xyz} { + Laotianxhorseyrunszfast +} { + laotian Laotian + horse horse + runs runs + fast fast +} + +do_unicode_token_test3 5.4 {tokenchars xyz} { + Laotianxhorseyrunszfast +} { + laotianxhorseyrunszfast Laotianxhorseyrunszfast +} + +do_unicode_token_test3 5.5 {tokenchars _} {separators zyx} { + sqlite3_resetxsqlite3_column_intyhonda_phantom +} { + sqlite3_reset sqlite3_reset + sqlite3_column_int sqlite3_column_int + honda_phantom honda_phantom +} + +do_unicode_token_test3 5.6 "separators \u05D1" "abc\u05D1def" { + abc abc def def +} + +do_unicode_token_test3 5.7 \ + "tokenchars \u2444\u2445" \ + "separators \u05D0\u05D1\u05D2" \ + "\u2444fre\u2445sh\u05D0water\u05D2fish.\u2445timer" \ + [list \ + \u2444fre\u2445sh \u2444fre\u2445sh \ + water water \ + fish fish \ + \u2445timer \u2445timer \ + ] + +# Check that it is not possible to add a standalone diacritic codepoint +# to either separators or tokenchars. +do_unicode_token_test3 5.8 "separators \u0301" \ + "hello\u0301world \u0301helloworld" \ + "helloworld hello\u0301world helloworld helloworld" + +do_unicode_token_test3 5.9 "tokenchars \u0301" \ + "hello\u0301world \u0301helloworld" \ + "helloworld hello\u0301world helloworld helloworld" + +do_unicode_token_test3 5.10 "separators \u0301" \ + "remove_diacritics 0" \ + "hello\u0301world \u0301helloworld" \ + "hello\u0301world hello\u0301world helloworld helloworld" + +do_unicode_token_test3 5.11 "tokenchars \u0301" \ + "remove_diacritics 0" \ + "hello\u0301world \u0301helloworld" \ + "hello\u0301world hello\u0301world helloworld helloworld" + +#------------------------------------------------------------------------- + +proc do_tokenize {tokenizer txt} { + set res [list] + foreach {b c} [sqlite3_fts5_tokenize -subst db $tokenizer $txt] { + lappend res $b + } + set res +} + +# Argument $lCodepoint must be a list of codepoints (integers) that +# correspond to whitespace characters. This command creates a string +# $W from the codepoints, then tokenizes "${W}hello{$W}world${W}" +# using tokenizer $tokenizer. The test passes if the tokenizer successfully +# extracts the two 5 character tokens. +# +proc do_isspace_test {tn tokenizer lCp} { + set whitespace [format [string repeat %c [llength $lCp]] {*}$lCp] + set txt "${whitespace}hello${whitespace}world${whitespace}" + uplevel [list do_test $tn [list do_tokenize $tokenizer $txt] {hello world}] +} + +set tokenizers [list unicode61] +#ifcapable icu { lappend tokenizers icu } + +# Some tests to check that the tokenizers can both identify white-space +# codepoints. All codepoints tested below are of type "Zs" in the +# UnicodeData.txt file. +foreach T $tokenizers { + do_isspace_test 6.$T.1 $T 32 + do_isspace_test 6.$T.2 $T 160 + do_isspace_test 6.$T.3 $T 5760 + do_isspace_test 6.$T.4 $T 6158 + do_isspace_test 6.$T.5 $T 8192 + do_isspace_test 6.$T.6 $T 8193 + do_isspace_test 6.$T.7 $T 8194 + do_isspace_test 6.$T.8 $T 8195 + do_isspace_test 6.$T.9 $T 8196 + do_isspace_test 6.$T.10 $T 8197 + do_isspace_test 6.$T.11 $T 8198 + do_isspace_test 6.$T.12 $T 8199 + do_isspace_test 6.$T.13 $T 8200 + do_isspace_test 6.$T.14 $T 8201 + do_isspace_test 6.$T.15 $T 8202 + do_isspace_test 6.$T.16 $T 8239 + do_isspace_test 6.$T.17 $T 8287 + do_isspace_test 6.$T.18 $T 12288 + + do_isspace_test 6.$T.19 $T {32 160 5760 6158} + do_isspace_test 6.$T.20 $T {8192 8193 8194 8195} + do_isspace_test 6.$T.21 $T {8196 8197 8198 8199} + do_isspace_test 6.$T.22 $T {8200 8201 8202 8239} + do_isspace_test 6.$T.23 $T {8287 12288} +} + + +#------------------------------------------------------------------------- +# Test that the private use ranges are treated as alphanumeric. +# +foreach {tn1 c} { + 1 \ue000 2 \ue001 3 \uf000 4 \uf8fe 5 \uf8ff +} { + foreach {tn2 config res} { + 1 "" "hello*world hello*world" + 2 "separators *" "hello hello world world" + } { + set config [string map [list * $c] $config] + set input [string map [list * $c] "hello*world"] + set output [string map [list * $c] $res] + do_unicode_token_test3 7.$tn1.$tn2 {*}$config $input $output + } +} + +#------------------------------------------------------------------------- +# Cursory test of remove_diacritics=0. +# +# 00C4;LATIN CAPITAL LETTER A WITH DIAERESIS +# 00D6;LATIN CAPITAL LETTER O WITH DIAERESIS +# 00E4;LATIN SMALL LETTER A WITH DIAERESIS +# 00F6;LATIN SMALL LETTER O WITH DIAERESIS +# +do_execsql_test 8.1.1 " + CREATE VIRTUAL TABLE t3 USING fts5( + content, tokenize='unicode61 remove_diacritics 1' + ); + INSERT INTO t3 VALUES('o'); + INSERT INTO t3 VALUES('a'); + INSERT INTO t3 VALUES('O'); + INSERT INTO t3 VALUES('A'); + INSERT INTO t3 VALUES('\xD6'); + INSERT INTO t3 VALUES('\xC4'); + INSERT INTO t3 VALUES('\xF6'); + INSERT INTO t3 VALUES('\xE4'); +" +do_execsql_test 8.1.2 { + SELECT rowid FROM t3 WHERE t3 MATCH 'o' ORDER BY rowid ASC; +} {1 3 5 7} +do_execsql_test 8.1.3 { + SELECT rowid FROM t3 WHERE t3 MATCH 'a' ORDER BY rowid ASC; +} {2 4 6 8} +do_execsql_test 8.2.1 { + CREATE VIRTUAL TABLE t4 USING fts5( + content, tokenize='unicode61 remove_diacritics 0' + ); + INSERT INTO t4 SELECT * FROM t3 ORDER BY rowid ASC; +} +do_execsql_test 8.2.2 { + SELECT rowid FROM t4 WHERE t4 MATCH 'o' ORDER BY rowid ASC; +} {1 3} +do_execsql_test 8.2.3 { + SELECT rowid FROM t4 WHERE t4 MATCH 'a' ORDER BY rowid ASC; +} {2 4} + +#------------------------------------------------------------------------- +# +if 0 { +foreach {tn sql} { + 1 { + CREATE VIRTUAL TABLE t5 USING fts4(tokenize=unicode61 [tokenchars= .]); + CREATE VIRTUAL TABLE t6 USING fts4( + tokenize=unicode61 [tokenchars=="] "tokenchars=[]"); + CREATE VIRTUAL TABLE t7 USING fts4(tokenize=unicode61 [separators=x\xC4]); + } + 2 { + CREATE VIRTUAL TABLE t5 USING fts4(tokenize=unicode61 "tokenchars= ."); + CREATE VIRTUAL TABLE t6 USING fts4(tokenize=unicode61 "tokenchars=[=""]"); + CREATE VIRTUAL TABLE t7 USING fts4(tokenize=unicode61 "separators=x\xC4"); + } + 3 { + CREATE VIRTUAL TABLE t5 USING fts4(tokenize=unicode61 'tokenchars= .'); + CREATE VIRTUAL TABLE t6 USING fts4(tokenize=unicode61 'tokenchars=="[]'); + CREATE VIRTUAL TABLE t7 USING fts4(tokenize=unicode61 'separators=x\xC4'); + } + 4 { + CREATE VIRTUAL TABLE t5 USING fts4(tokenize=unicode61 `tokenchars= .`); + CREATE VIRTUAL TABLE t6 USING fts4(tokenize=unicode61 `tokenchars=[="]`); + CREATE VIRTUAL TABLE t7 USING fts4(tokenize=unicode61 `separators=x\xC4`); + } +} { + do_execsql_test 9.$tn.0 { + DROP TABLE IF EXISTS t5; + DROP TABLE IF EXISTS t5aux; + DROP TABLE IF EXISTS t6; + DROP TABLE IF EXISTS t6aux; + DROP TABLE IF EXISTS t7; + DROP TABLE IF EXISTS t7aux; + } + do_execsql_test 9.$tn.1 $sql + + do_execsql_test 9.$tn.2 { + CREATE VIRTUAL TABLE t5aux USING fts4aux(t5); + INSERT INTO t5 VALUES('one two three/four.five.six'); + SELECT * FROM t5aux; + } { + four.five.six * 1 1 four.five.six 0 1 1 + {one two three} * 1 1 {one two three} 0 1 1 + } + + do_execsql_test 9.$tn.3 { + CREATE VIRTUAL TABLE t6aux USING fts4aux(t6); + INSERT INTO t6 VALUES('alpha=beta"gamma/delta[epsilon]zeta'); + SELECT * FROM t6aux; + } { + {alpha=beta"gamma} * 1 1 {alpha=beta"gamma} 0 1 1 + {delta[epsilon]zeta} * 1 1 {delta[epsilon]zeta} 0 1 1 + } + + do_execsql_test 9.$tn.4 { + CREATE VIRTUAL TABLE t7aux USING fts4aux(t7); + INSERT INTO t7 VALUES('alephxbeth\xC4gimel'); + SELECT * FROM t7aux; + } { + aleph * 1 1 aleph 0 1 1 + beth * 1 1 beth 0 1 1 + gimel * 1 1 gimel 0 1 1 + } +} + +# Check that multiple options are handled correctly. +# +do_execsql_test 10.1 { + DROP TABLE IF EXISTS t1; + CREATE VIRTUAL TABLE t1 USING fts4(tokenize=unicode61 + "tokenchars=xyz" "tokenchars=.=" "separators=.=" "separators=xy" + "separators=a" "separators=a" "tokenchars=a" "tokenchars=a" + ); + + INSERT INTO t1 VALUES('oneatwoxthreeyfour'); + INSERT INTO t1 VALUES('a.single=word'); + CREATE VIRTUAL TABLE t1aux USING fts4aux(t1); + SELECT * FROM t1aux; +} { + .single=word * 1 1 .single=word 0 1 1 + four * 1 1 four 0 1 1 + one * 1 1 one 0 1 1 + three * 1 1 three 0 1 1 + two * 1 1 two 0 1 1 +} + +# Test that case folding happens after tokenization, not before. +# +do_execsql_test 10.2 { + DROP TABLE IF EXISTS t2; + CREATE VIRTUAL TABLE t2 USING fts4(tokenize=unicode61 "separators=aB"); + INSERT INTO t2 VALUES('oneatwoBthree'); + INSERT INTO t2 VALUES('onebtwoAthree'); + CREATE VIRTUAL TABLE t2aux USING fts4aux(t2); + SELECT * FROM t2aux; +} { + one * 1 1 one 0 1 1 + onebtwoathree * 1 1 onebtwoathree 0 1 1 + three * 1 1 three 0 1 1 + two * 1 1 two 0 1 1 +} + +# Test that the tokenchars and separators options work with the +# fts3tokenize table. +# +do_execsql_test 11.1 { + CREATE VIRTUAL TABLE ft1 USING fts3tokenize( + "unicode61", "tokenchars=@.", "separators=1234567890" + ); + SELECT token FROM ft1 WHERE input = 'berlin@street123sydney.road'; +} { + berlin@street sydney.road +} + +} + +finish_test diff --git a/ext/fts5/test/fts5unicode3.test b/ext/fts5/test/fts5unicode3.test new file mode 100644 index 0000000..876ad27 --- /dev/null +++ b/ext/fts5/test/fts5unicode3.test @@ -0,0 +1,129 @@ +# 2014 Dec 20 +# +# 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. +# +#*********************************************************************** +# +# Tests focusing on the fts5 tokenizers +# + +source [file join [file dirname [info script]] fts5_common.tcl] + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +proc fts3_unicode_path {file} { + file join [file dirname [info script]] .. .. fts3 unicode $file +} + +source [fts3_unicode_path parseunicode.tcl] +set testprefix fts5unicode3 + +set CF [fts3_unicode_path CaseFolding.txt] +set UD [fts3_unicode_path UnicodeData.txt] + +tl_load_casefolding_txt $CF +foreach x [an_load_unicodedata_text $UD] { + set aNotAlnum($x) 1 +} + +foreach {y} [rd_load_unicodedata_text $UD] { + foreach {code ascii} $y {} + if {$ascii==""} { + set int 0 + } else { + binary scan $ascii c int + } + set aDiacritic($code) $int +} + +proc tcl_fold {i {bRemoveDiacritic 0}} { + global tl_lookup_table + global aDiacritic + + if {[info exists tl_lookup_table($i)]} { + set i $tl_lookup_table($i) + } + if {$bRemoveDiacritic && [info exists aDiacritic($i)]} { + set i $aDiacritic($i) + } + expr $i +} +db func tcl_fold tcl_fold + +proc tcl_isalnum {i} { + global aNotAlnum + expr {![info exists aNotAlnum($i)]} +} +db func tcl_isalnum tcl_isalnum + + +do_catchsql_test 1.0.1 { + SELECT fts5_isalnum(1, 2, 3); +} {1 {wrong number of arguments to function fts5_isalnum}} +do_catchsql_test 1.0.2 { + SELECT fts5_fold(); +} {1 {wrong number of arguments to function fts5_fold}} +do_catchsql_test 1.0.3 { + SELECT fts5_fold(1,2,3); +} {1 {wrong number of arguments to function fts5_fold}} + +do_execsql_test 1.1 { + WITH ii(i) AS ( + SELECT -1 + UNION ALL + SELECT i+1 FROM ii WHERE i<100000 + ) + SELECT count(*), min(i) FROM ii WHERE fts5_fold(i)!=CAST(tcl_fold(i) AS int); +} {0 {}} + +do_execsql_test 1.2 { + WITH ii(i) AS ( + SELECT -1 + UNION ALL + SELECT i+1 FROM ii WHERE i<100000 + ) + SELECT count(*), min(i) FROM ii + WHERE fts5_fold(i,1)!=CAST(tcl_fold(i,1) AS int); +} {0 {}} + +do_execsql_test 1.3 { + WITH ii(i) AS ( + SELECT -1 + UNION ALL + SELECT i+1 FROM ii WHERE i<100000 + ) + SELECT count(*), min(i) FROM ii + WHERE fts5_isalnum(i)!=CAST(tcl_isalnum(i) AS int); +} {0 {}} + +do_test 1.4 { + set str {CREATE VIRTUAL TABLE f3 USING fts5(a, tokenize=} + append str {"unicode61 separators '} + for {set i 700} {$i<900} {incr i} { + append str [format %c $i] + } + append str {'");} + execsql $str +} {} +do_test 1.5 { + set str {CREATE VIRTUAL TABLE f5 USING fts5(a, tokenize=} + append str {"unicode61 tokenchars '} + for {set i 700} {$i<900} {incr i} { + append str [format %c $i] + } + append str {'");} + execsql $str +} {} + + +finish_test + diff --git a/ext/fts5/test/fts5unindexed.test b/ext/fts5/test/fts5unindexed.test new file mode 100644 index 0000000..16d43f8 --- /dev/null +++ b/ext/fts5/test/fts5unindexed.test @@ -0,0 +1,79 @@ +# 2015 Apr 24 +# +# 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 tests in this file focus on "unindexed" columns. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5unindexed + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + + +do_execsql_test 1.1 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b UNINDEXED); + INSERT INTO t1 VALUES('a b c', 'd e f'); + INSERT INTO t1 VALUES('g h i', 'j k l'); +} {} + +do_execsql_test 1.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'b' } {1} +do_execsql_test 1.3 { SELECT rowid FROM t1 WHERE t1 MATCH 'e' } {} + +do_execsql_test 1.4 { INSERT INTO t1(t1) VALUES('integrity-check') } {} +do_execsql_test 1.5 { INSERT INTO t1(t1) VALUES('rebuild') } {} +do_execsql_test 1.6 { INSERT INTO t1(t1) VALUES('integrity-check') } {} + +do_execsql_test 1.7 { SELECT rowid FROM t1 WHERE t1 MATCH 'b' } {1} +do_execsql_test 1.8 { SELECT rowid FROM t1 WHERE t1 MATCH 'e' } {} + +do_execsql_test 1.9 { DELETE FROM t1 WHERE t1 MATCH 'b' } {} + +do_execsql_test 1.10 { INSERT INTO t1(t1) VALUES('integrity-check') } {} +do_execsql_test 1.11 { INSERT INTO t1(t1) VALUES('rebuild') } {} +do_execsql_test 1.12 { INSERT INTO t1(t1) VALUES('integrity-check') } {} + +do_execsql_test 1.13 { SELECT rowid FROM t1 WHERE t1 MATCH 'i' } {2} +do_execsql_test 1.14 { SELECT rowid FROM t1 WHERE t1 MATCH 'l' } {} + +do_execsql_test 2.1 { + CREATE VIRTUAL TABLE t2 USING fts5(a UNINDEXED, b UNINDEXED); + INSERT INTO t1 VALUES('a b c', 'd e f'); + INSERT INTO t1 VALUES('g h i', 'j k l'); + SELECT rowid FROM t2_data; +} {1 10} +do_execsql_test 2.2 { + INSERT INTO t2(t2) VALUES('rebuild'); + INSERT INTO t2(t2) VALUES('integrity-check'); + SELECT rowid FROM t2_data; +} {1 10} + +do_execsql_test 3.1 { + CREATE TABLE x4(i INTEGER PRIMARY KEY, a, b, c); + CREATE VIRTUAL TABLE t4 USING fts5(a, b UNINDEXED, c, content=x4); + INSERT INTO x4 VALUES(10, 'a b c', 'd e f', 'g h i'); + INSERT INTO x4 VALUES(20, 'j k l', 'm n o', 'p q r'); + INSERT INTO t4(t4) VALUES('rebuild'); + INSERT INTO t4(t4) VALUES('integrity-check'); +} {} + +do_execsql_test 3.2 { + INSERT INTO t4(t4, rowid, a, b, c) VALUES('delete', 20, 'j k l', '', 'p q r'); + DELETE FROM x4 WHERE rowid=20; + INSERT INTO t4(t4) VALUES('integrity-check'); +} {} + + +finish_test + diff --git a/ext/fts5/test/fts5update.test b/ext/fts5/test/fts5update.test new file mode 100644 index 0000000..399c7ff --- /dev/null +++ b/ext/fts5/test/fts5update.test @@ -0,0 +1,121 @@ +# 2016 Jan 16 +# +# 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 fts5update + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +set docs { + "eight zero iv eight 7" "ix one 8 one three ii one" + "1 9 9 three viii" "5 zero ii 6 nine ix 3" + "3 zero 5 2 seven nine" "two eight viii eight 1" + "4 six two 5 9 vii" "viii ii four 8 i i iv" + "vii 0 iv seven 7 viii" "five 1 nine vi seven" + "1 zero zero iii 1" "one one six 6 nine seven" + "one v 4 zero 4 iii ii" "2 3 eight six ix" + "six iv 7 three 5" "ix zero 0 8 ii 7 3" + "four six nine 2 vii 3" "five viii 5 8 0 7" +} + +foreach_detail_mode $::testprefix { + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=%DETAIL%); +} {} + +do_test 1.1 { + foreach {a b} $docs { + execsql {INSERT INTO t1 VALUES($a, $b)} + } +} {} + +proc update {iRowid iA iB} { + set a [lindex $::docs $iA] + set b [lindex $::docs $iB] + execsql { UPDATE t1 SET a=$a, b=$b WHERE rowid=$iRowid } +} + +set nDoc [llength $::docs] +foreach n {1 5 10 50 100} { + do_test 1.2.$n { + execsql BEGIN + for {set i 1} {$i <= 1000} {incr i} { + set iRowid [expr {int(rand() * ($nDoc/2)) + 1}] + set iA [expr {int(rand() * $nDoc)}] + set iB [expr {int(rand() * $nDoc)}] + update $iRowid $iA $iB + + if {($i % $n)==0} { + execsql { COMMIT; BEGIN } + } + + if {($i % $n)==100} { + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } + } + } + execsql COMMIT + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } + } {} +} + +do_execsql_test 1.3 { + UPDATE t1 SET a=a AND b=b; + INSERT INTO t1(t1) VALUES('integrity-check'); +} + +do_test 1.4 { + execsql { INSERT INTO t1(t1, rank) VALUES('pgsz', 32) } + for {set i 0} {$i < 50} {incr i} { + execsql { UPDATE t1 SET a=a AND b=b } + execsql { INSERT INTO t1(t1) VALUES('integrity-check') } + } +} {} + +#------------------------------------------------------------------------- +# Lots of deletes/inserts of the same document with the same rowid. +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE x2 USING fts5(x, detail=%DETAIL%); + INSERT INTO x2(x2, rank) VALUES('crisismerge', 2); + INSERT INTO x2 VALUES('a b c'); + INSERT INTO x2 VALUES('a b c'); +} +do_test 2.1 { + for {set i 0} {$i < 1000} {incr i} { + execsql { DELETE FROM x2 WHERE rowid = 2 } + execsql { INSERT INTO x2(rowid, x) VALUES(2, 'a b c') } + } +} {} +do_execsql_test 2.1.integrity { + INSERT INTO x2(x2) VALUES('integrity-check'); +} + +do_test 2.2 { + for {set i 0} {$i < 1000} {incr i} { + execsql { UPDATE x2 SET x=x WHERE rowid=2 } + } +} {} +do_execsql_test 2.2.integrity { + INSERT INTO x2(x2) VALUES('integrity-check'); +} + +} +finish_test + + diff --git a/ext/fts5/test/fts5version.test b/ext/fts5/test/fts5version.test new file mode 100644 index 0000000..7e4d74d --- /dev/null +++ b/ext/fts5/test/fts5version.test @@ -0,0 +1,64 @@ +# 2015 Apr 24 +# +# 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 tests in this file focus on testing that unrecognized file-format +# versions are detected and reported. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5version + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + + +do_execsql_test 1.1 { + CREATE VIRTUAL TABLE t1 USING fts5(one); + INSERT INTO t1 VALUES('a b c d'); +} {} + +do_execsql_test 1.2 { + SELECT * FROM t1_config WHERE k='version' +} {version 4} + +do_execsql_test 1.3 { + SELECT rowid FROM t1 WHERE t1 MATCH 'a'; +} {1} + +do_execsql_test 1.4 { + UPDATE t1_config set v=5 WHERE k='version'; +} + +do_test 1.5 { + db close + sqlite3 db test.db + catchsql { SELECT * FROM t1 WHERE t1 MATCH 'a' } +} {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}} + +do_test 1.6 { + db close + sqlite3 db test.db + catchsql { INSERT INTO t1 VALUES('x y z') } +} {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}} + +do_test 1.7 { + execsql { DELETE FROM t1_config WHERE k='version' } + db close + sqlite3 db test.db + catchsql { SELECT * FROM t1 WHERE t1 MATCH 'a' } +} {1 {invalid fts5 file format (found 0, expected 4) - run 'rebuild'}} + + +finish_test + diff --git a/ext/fts5/test/fts5vocab.test b/ext/fts5/test/fts5vocab.test new file mode 100644 index 0000000..f7278dd --- /dev/null +++ b/ext/fts5/test/fts5vocab.test @@ -0,0 +1,449 @@ +# 2015 Apr 24 +# +# 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 tests in this file focus on testing the fts5vocab module. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5vocab + +# If SQLITE_ENABLE_FTS5 is defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +foreach_detail_mode $testprefix { + +proc null_list_entries {iFirst nInterval L} { + for {set i $iFirst} {$i < [llength $L]} {incr i $nInterval} { + lset L $i {} + } + return $L +} + +proc star_from_row {L} { + if {[detail_is_full]==0} { + set L [null_list_entries 2 3 $L] + } + return $L +} + +proc star_from_col {L} { + if {[detail_is_col]} { + set L [null_list_entries 3 4 $L] + } + if {[detail_is_none]} { + set L [null_list_entries 1 4 $L] + set L [null_list_entries 3 4 $L] + } + return $L +} + +proc row_to_col {L} { + if {[detail_is_none]==0} { error "this is for detail=none mode" } + set ret [list] + foreach {a b c} $L { + lappend ret $a {} $b {} + } + set ret +} + +if 1 { + +do_execsql_test 1.1.1 { + CREATE VIRTUAL TABLE t1 USING fts5(one, prefix=1, detail=%DETAIL%); + CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, 'row'); + PRAGMA table_info = v1; +} { + 0 term {} 0 {} 0 + 1 doc {} 0 {} 0 + 2 cnt {} 0 {} 0 +} + +do_execsql_test 1.1.2 { + CREATE VIRTUAL TABLE v2 USING fts5vocab(t1, 'col'); + PRAGMA table_info = v2; +} { + 0 term {} 0 {} 0 + 1 col {} 0 {} 0 + 2 doc {} 0 {} 0 + 3 cnt {} 0 {} 0 +} + +do_execsql_test 1.2.1 { SELECT * FROM v1 } { } +do_execsql_test 1.2.2 { SELECT * FROM v2 } { } + +do_execsql_test 1.3 { + INSERT INTO t1 VALUES('x y z'); + INSERT INTO t1 VALUES('x x x'); +} + +do_execsql_test 1.4.1 { + SELECT * FROM v1; +} [star_from_row {x 2 4 y 1 1 z 1 1}] + +do_execsql_test 1.4.2 { + SELECT * FROM v2; +} [star_from_col {x one 2 4 y one 1 1 z one 1 1}] + +do_execsql_test 1.5.1 { + BEGIN; + INSERT INTO t1 VALUES('a b c'); + SELECT * FROM v1 WHERE term<'d'; +} [star_from_row {a 1 1 b 1 1 c 1 1}] + +do_execsql_test 1.5.2 { + SELECT * FROM v2 WHERE term<'d'; + COMMIT; +} [star_from_col {a one 1 1 b one 1 1 c one 1 1}] + +do_execsql_test 1.6 { + DELETE FROM t1 WHERE one = 'a b c'; + SELECT * FROM v1; +} [star_from_row {x 2 4 y 1 1 z 1 1}] + +#------------------------------------------------------------------------- +# +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE tt USING fts5(a, b, detail=%DETAIL%); + INSERT INTO tt VALUES('d g b f d f', 'f c e c d a'); + INSERT INTO tt VALUES('f a e a a b', 'e d c f d d'); + INSERT INTO tt VALUES('b c a a a b', 'f f c c b c'); + INSERT INTO tt VALUES('f d c a c e', 'd g d e g d'); + INSERT INTO tt VALUES('g d e f a g x', 'f f d a a b'); + INSERT INTO tt VALUES('g c f b c g', 'a g f d c b'); + INSERT INTO tt VALUES('c e c f g b', 'f e d b g a'); + INSERT INTO tt VALUES('g d e f d e', 'a c d b a g'); + INSERT INTO tt VALUES('e f a c c b', 'b f e a f d y'); + INSERT INTO tt VALUES('c c a a c f', 'd g a e b g'); +} + +set res_row [star_from_row { + a 10 20 b 9 14 c 9 20 d 9 19 + e 8 13 f 10 20 g 7 14 x 1 1 + y 1 1 +}] +set res_col [star_from_col { + a a 6 11 a b 7 9 + b a 6 7 b b 7 7 + c a 6 12 c b 5 8 + d a 4 6 d b 9 13 + e a 6 7 e b 6 6 + f a 9 10 f b 7 10 + g a 5 7 g b 5 7 + x a 1 1 y b 1 1 +}] +if {[detail_is_none]} { + set res_col [row_to_col $res_row] +} + +foreach {tn tbl resname} { + 1 "fts5vocab(tt, 'col')" res_col + 2 "fts5vocab(tt, 'row')" res_row + 3 "fts5vocab(tt, \"row\")" res_row + 4 "fts5vocab(tt, [row])" res_row + 5 "fts5vocab(tt, `row`)" res_row + + 6 "fts5vocab('tt', 'row')" res_row + 7 "fts5vocab(\"tt\", \"row\")" res_row + 8 "fts5vocab([tt], [row])" res_row + 9 "fts5vocab(`tt`, `row`)" res_row +} { + do_execsql_test 2.$tn " + DROP TABLE IF EXISTS tv; + CREATE VIRTUAL TABLE tv USING $tbl; + SELECT * FROM tv; + " [set $resname] +} + +#------------------------------------------------------------------------- +# Test errors in the CREATE VIRTUAL TABLE statement. +# +foreach {tn sql} { + 1 { CREATE VIRTUAL TABLE aa USING fts5vocab() } + 2 { CREATE VIRTUAL TABLE aa USING fts5vocab(x) } + 3 { CREATE VIRTUAL TABLE aa USING fts5vocab(x,y,z) } + 4 { CREATE VIRTUAL TABLE temp.aa USING fts5vocab(x,y,z,y) } +} { + do_catchsql_test 3.$tn $sql {1 {wrong number of vtable arguments}} +} + +do_catchsql_test 4.0 { + CREATE VIRTUAL TABLE cc USING fts5vocab(tbl, unknown); +} {1 {fts5vocab: unknown table type: 'unknown'}} + +do_catchsql_test 4.1 { + ATTACH 'test.db' AS aux; + CREATE VIRTUAL TABLE aux.cc USING fts5vocab(main, tbl, row); +} {1 {wrong number of vtable arguments}} + +#------------------------------------------------------------------------- +# Test fts5vocab tables created in the temp schema. +# +reset_db +forcedelete test.db2 +do_execsql_test 5.0 { + ATTACH 'test.db2' AS aux; + CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%); + CREATE VIRTUAL TABLE temp.t1 USING fts5(x, detail=%DETAIL%); + CREATE VIRTUAL TABLE aux.t1 USING fts5(x, detail=%DETAIL%); + + INSERT INTO main.t1 VALUES('a b c'); + INSERT INTO main.t1 VALUES('d e f'); + INSERT INTO main.t1 VALUES('a e c'); + + INSERT INTO temp.t1 VALUES('1 2 3'); + INSERT INTO temp.t1 VALUES('4 5 6'); + INSERT INTO temp.t1 VALUES('1 5 3'); + + INSERT INTO aux.t1 VALUES('x y z'); + INSERT INTO aux.t1 VALUES('m n o'); + INSERT INTO aux.t1 VALUES('x n z'); +} + +breakpoint +do_execsql_test 5.1 { + CREATE VIRTUAL TABLE temp.vm USING fts5vocab(main, t1, row); + CREATE VIRTUAL TABLE temp.vt1 USING fts5vocab(t1, row); + CREATE VIRTUAL TABLE temp.vt2 USING fts5vocab(temp, t1, row); + CREATE VIRTUAL TABLE temp.va USING fts5vocab(aux, t1, row); +} + +do_execsql_test 5.2 { SELECT * FROM vm } [star_from_row { + a 2 2 b 1 1 c 2 2 d 1 1 e 2 2 f 1 1 +}] +do_execsql_test 5.3 { SELECT * FROM vt1 } [star_from_row { + 1 2 2 2 1 1 3 2 2 4 1 1 5 2 2 6 1 1 +}] +do_execsql_test 5.4 { SELECT * FROM vt2 } [star_from_row { + 1 2 2 2 1 1 3 2 2 4 1 1 5 2 2 6 1 1 +}] +do_execsql_test 5.5 { SELECT * FROM va } [star_from_row { + m 1 1 n 2 2 o 1 1 x 2 2 y 1 1 z 2 2 +}] + +#------------------------------------------------------------------------- +# +do_execsql_test 6.0 { + CREATE TABLE iii(iii); + CREATE TABLE jjj(x); +} + +do_catchsql_test 6.1 { + CREATE VIRTUAL TABLE vocab1 USING fts5vocab(iii, row); + SELECT * FROM vocab1; +} {1 {no such fts5 table: main.iii}} + +do_catchsql_test 6.2 { + CREATE VIRTUAL TABLE vocab2 USING fts5vocab(jjj, row); + SELECT * FROM vocab2; +} {1 {no such fts5 table: main.jjj}} + +do_catchsql_test 6.2 { + CREATE VIRTUAL TABLE vocab3 USING fts5vocab(lll, row); + SELECT * FROM vocab3; +} {1 {no such fts5 table: main.lll}} + +#------------------------------------------------------------------------- +# Test single term queries on fts5vocab tables (i.e. those with term=? +# constraints in the WHERE clause). +# +do_execsql_test 7.0 { + CREATE VIRTUAL TABLE tx USING fts5(one, two, detail=%DETAIL%); + INSERT INTO tx VALUES('g a ggg g a b eee', 'cc d aa ff g ee'); + INSERT INTO tx VALUES('dd fff i a i jjj', 'f fff hh jj e f'); + INSERT INTO tx VALUES('ggg a f f fff dd aa', 'd ggg f f j gg ddd'); + INSERT INTO tx VALUES('e bb h jjj ii gg', 'e aa e f c fff'); + INSERT INTO tx VALUES('j ff aa a h', 'h a j bbb bb'); + INSERT INTO tx VALUES('cc i ff c d f', 'dd ii fff f c cc d'); + INSERT INTO tx VALUES('jjj g i bb cc eee', 'hhh iii aaa b bbb aaa'); + INSERT INTO tx VALUES('hhh hhh hhh bb fff f', 'fff gg aa ii h a'); + INSERT INTO tx VALUES('b c cc aaa iii ggg f', 'iii ff ee a ff c cc'); + INSERT INTO tx VALUES('hhh b hhh aaa j i i', 'dd ee ee aa bbb iii'); + INSERT INTO tx VALUES('hh dd h b g ff i', 'ccc bb cc ccc f a d'); + INSERT INTO tx VALUES('g d b ggg jj', 'fff jj ff jj g gg ee'); + INSERT INTO tx VALUES('g ee ggg ggg cc bb eee', 'aa j jjj bbb dd eee ff'); + INSERT INTO tx VALUES('c jjj hh ddd dd h', 'e aaa h jjj gg'); + + CREATE VIRTUAL TABLE txr USING fts5vocab(tx, row); + CREATE VIRTUAL TABLE txc USING fts5vocab(tx, col); +} + +proc cont {L elem} { + set n 0 + foreach e $L { if {$elem==$e} {incr n} } + set n +} +db func cont cont + +foreach {term} { + a aa aaa + b bb bbb + c cc ccc + d dd ddd + e ee eee + f ff fff + g gg ggg + h hh hhh + i ii iii + j jj jjj +} { + set resr [db eval { + SELECT $term, + sum(cont(one || ' ' || two, $term) > 0), + sum(cont(one || ' ' || two, $term)) + FROM tx + }] + if {[lindex $resr 1]==0} {set resr [list]} + + set r1 [db eval { + SELECT $term, 'one', sum(cont(one, $term)>0), sum(cont(one, $term)) FROM tx + }] + if {[lindex $r1 2]==0} {set r1 [list]} + + set r2 [db eval { + SELECT $term, 'two', sum(cont(two, $term)>0), sum(cont(two, $term)) FROM tx + }] + if {[lindex $r2 2]==0} {set r2 [list]} + + set resc [concat $r1 $r2] + + set resc [star_from_col $resc] + set resr [star_from_row $resr] + if {[detail_is_none]} { set resc [row_to_col $resr] } + do_execsql_test 7.$term.1 {SELECT * FROM txc WHERE term=$term} $resc + do_execsql_test 7.$term.2 {SELECT * FROM txr WHERE term=$term} $resr +} + +do_execsql_test 7.1 { + CREATE TABLE txr_c AS SELECT * FROM txr; + CREATE TABLE txc_c AS SELECT * FROM txc; +} + +# Test range queries on the fts5vocab tables created above. +# +foreach {tn a b} { + 1 a jjj + 2 bb j + 3 ccc ddd + 4 dd xyz + 5 xzy dd + 6 h hh +} { + do_execsql_test 7.2.$tn.1 { + SELECT * FROM txr WHERE term>=$a + } [db eval {SELECT * FROM txr_c WHERE term>=$a}] + do_execsql_test 7.2.$tn.2 { + SELECT * FROM txr WHERE term<=$b + } [db eval {SELECT * FROM txr_c WHERE term <=$b}] + do_execsql_test 7.2.$tn.3 { + SELECT * FROM txr WHERE term>=$a AND term<=$b + } [db eval {SELECT * FROM txr_c WHERE term>=$a AND term <=$b}] + + do_execsql_test 7.2.$tn.4 { + SELECT * FROM txc WHERE term>=$a + } [db eval {SELECT * FROM txc_c WHERE term>=$a}] + do_execsql_test 7.2.$tn.5 { + SELECT * FROM txc WHERE term<=$b + } [db eval {SELECT * FROM txc_c WHERE term <=$b}] + do_execsql_test 7.2.$tn.6 { + SELECT * FROM txc WHERE term>=$a AND term<=$b + } [db eval {SELECT * FROM txc_c WHERE term>=$a AND term <=$b}] + + do_execsql_test 7.2.$tn.7 { + SELECT * FROM txr WHERE term>$a + } [db eval {SELECT * FROM txr_c WHERE term>$a}] + do_execsql_test 7.2.$tn.8 { + SELECT * FROM txr WHERE term<$b + } [db eval {SELECT * FROM txr_c WHERE term<$b}] + do_execsql_test 7.2.$tn.9 { + SELECT * FROM txr WHERE term>$a AND term<$b + } [db eval {SELECT * FROM txr_c WHERE term>$a AND term <$b}] + + do_execsql_test 7.2.$tn.10 { + SELECT * FROM txc WHERE term>$a + } [db eval {SELECT * FROM txc_c WHERE term>$a}] + do_execsql_test 7.2.$tn.11 { + SELECT * FROM txc WHERE term<$b + } [db eval {SELECT * FROM txc_c WHERE term<$b}] + do_execsql_test 7.2.$tn.12 { + SELECT * FROM txc WHERE term>$a AND term<$b + } [db eval {SELECT * FROM txc_c WHERE term>$a AND term <$b}] +} + +do_execsql_test 7.3.1 { + SELECT count(*) FROM txr, txr_c WHERE txr.term = txr_c.term; +} {30} + +if {![detail_is_none]} { + do_execsql_test 7.3.2 { + SELECT count(*) FROM txc, txc_c + WHERE txc.term = txc_c.term AND txc.col=txc_c.col; + } {57} +} + +} + +#------------------------------------------------------------------------- +# Test the fts5vocab tables response to a specific types of corruption: +# where the fts5 index contains hits for columns that do not exist. +# +do_execsql_test 8.0 { + CREATE VIRTUAL TABLE x1 USING fts5(a, b, c, detail=%DETAIL%); + INSERT INTO x1 VALUES('a b c', 'd e f', 'g h i'); + INSERT INTO x1 VALUES('g h i', 'a b c', 'd e f'); + INSERT INTO x1 VALUES('d e f', 'g h i', 'a b c'); + CREATE VIRTUAL TABLE x1_r USING fts5vocab(x1, row); + CREATE VIRTUAL TABLE x1_c USING fts5vocab(x1, col); +} + +set resr [star_from_row {a 3 3 b 3 3 c 3 3 d 3 3 e 3 3 f 3 3 g 3 3 h 3 3 i 3 3}] +set resc [star_from_col { + a a 1 1 a b 1 1 a c 1 1 b a 1 1 + b b 1 1 b c 1 1 c a 1 1 c b 1 1 + c c 1 1 d a 1 1 d b 1 1 d c 1 1 + e a 1 1 e b 1 1 e c 1 1 f a 1 1 + f b 1 1 f c 1 1 g a 1 1 g b 1 1 + g c 1 1 h a 1 1 h b 1 1 h c 1 1 + i a 1 1 i b 1 1 i c 1 1 +}] +if {[detail_is_none]} { set resc [row_to_col $resr] } + +do_execsql_test 8.1.1 { SELECT * FROM x1_r; } $resr +do_execsql_test 8.1.2 { SELECT * FROM x1_c } $resc + +do_execsql_test 8.2 { + PRAGMA writable_schema = 1; + UPDATE sqlite_master + SET sql = 'CREATE VIRTUAL TABLE x1 USING fts5(a, detail=%DETAIL%)' + WHERE name = 'x1'; +} +db close +sqlite3 db test.db +sqlite3_fts5_may_be_corrupt 1 + +do_execsql_test 8.2.1 { SELECT * FROM x1_r } $resr + +if {[detail_is_none]} { + do_execsql_test 8.2.2 { SELECT * FROM x1_c } $resc +} else { + do_catchsql_test 8.2.2 { + SELECT * FROM x1_c + } {1 {database disk image is malformed}} +} + +sqlite3_fts5_may_be_corrupt 0 + +} + +finish_test + diff --git a/ext/fts5/tool/fts5speed.tcl b/ext/fts5/tool/fts5speed.tcl new file mode 100644 index 0000000..0f38638 --- /dev/null +++ b/ext/fts5/tool/fts5speed.tcl @@ -0,0 +1,64 @@ + + +set Q { + {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'enron'"} + {25 "SELECT count(*) FROM t1 WHERE t1 MATCH 'hours'"} + {300 "SELECT count(*) FROM t1 WHERE t1 MATCH 'acid'"} + {100 "SELECT count(*) FROM t1 WHERE t1 MATCH 'loaned OR mobility OR popcore OR sunk'"} + {100 "SELECT count(*) FROM t1 WHERE t1 MATCH 'enron AND myapps'"} + {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'en* AND my*'"} + + {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:t*'"} + {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t* OR b:t* OR c:t* OR d:t* OR e:t* OR f:t* OR g:t*'"} + {1 "SELECT count(*) FROM t1 WHERE t1 MATCH 'a:t*'"} + {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'c:the'"} + + {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes OR e:holmes OR f:holmes OR g:holmes'" } + {2 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes AND e:holmes AND f:holmes AND g:holmes'" } + {4 "SELECT count(*) FROM t1 WHERE t1 MATCH 'd:holmes NOT e:holmes'" } +} + +proc usage {} { + global Q + puts stderr "Usage: $::argv0 DATABASE QUERY" + puts stderr "" + for {set i 1} {$i <= [llength $Q]} {incr i} { + puts stderr " $i. [lindex $Q [expr $i-1]]" + } + puts stderr "" + exit -1 +} + + +set nArg [llength $argv] +if {$nArg!=2 && $nArg!=3} usage +set database [lindex $argv 0] +set iquery [lindex $argv 1] +if {$iquery<1 || $iquery>[llength $Q]} usage +set nRepeat 0 +if {$nArg==3} { set nRepeat [lindex $argv 2] } + + +sqlite3 db $database +catch { load_static_extension db fts5 } + +incr iquery -1 +set sql [lindex $Q $iquery 1] +if {$nRepeat==0} { + set nRepeat [lindex $Q $iquery 0] +} + +puts "sql: $sql" +puts "nRepeat: $nRepeat" +if {[regexp matchinfo $sql]} { + sqlite3_fts5_register_matchinfo db + db eval $sql +} else { + puts "result: [db eval $sql]" +} + +for {set i 1} {$i < $nRepeat} {incr i} { + db eval $sql +} + + diff --git a/ext/fts5/tool/fts5txt2db.tcl b/ext/fts5/tool/fts5txt2db.tcl new file mode 100644 index 0000000..d5df971 --- /dev/null +++ b/ext/fts5/tool/fts5txt2db.tcl @@ -0,0 +1,228 @@ +########################################################################## +# 2016 Jan 27 +# +# 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. +# +proc process_cmdline {} { + cmdline::process ::A $::argv { + {fts5 "use fts5 (this is the default)"} + {fts4 "use fts4"} + {colsize "10 10 10" "list of column sizes"} + {tblname "t1" "table name to create"} + {detail "full" "Fts5 detail mode to use"} + {repeat 1 "Load each file this many times"} + {prefix "" "Fts prefix= option"} + database + file... + } { + This script is designed to create fts4/5 tables with more than one column. + The -colsize option should be set to a Tcl list of integer values, one for + each column in the table. Each value is the number of tokens that will be + inserted into the column value for each row. For example, setting the -colsize + option to "5 10" creates an FTS table with 2 columns, with roughly 5 and 10 + tokens per row in each, respectively. + + Each "FILE" argument should be a text file. The contents of these text files + is split on whitespace characters to form a list of tokens. The first N1 + tokens are used for the first column of the first row, where N1 is the first + element of the -colsize list. The next N2 are used for the second column of + the first row, and so on. Rows are added to the table until the entire list + of tokens is exhausted. + } +} + +########################################################################### +########################################################################### +# Command line options processor. This is generic code that can be copied +# between scripts. +# +namespace eval cmdline { + proc cmdline_error {O E {msg ""}} { + if {$msg != ""} { + puts stderr "Error: $msg" + puts stderr "" + } + + set L [list] + foreach o $O { + if {[llength $o]==1} { + lappend L [string toupper $o] + } + } + + puts stderr "Usage: $::argv0 ?SWITCHES? $L" + puts stderr "" + puts stderr "Switches are:" + foreach o $O { + if {[llength $o]==3} { + foreach {a b c} $o {} + puts stderr [format " -%-15s %s (default \"%s\")" "$a VAL" $c $b] + } elseif {[llength $o]==2} { + foreach {a b} $o {} + puts stderr [format " -%-15s %s" $a $b] + } + } + puts stderr "" + puts stderr $E + exit -1 + } + + proc process {avar lArgs O E} { + upvar $avar A + set zTrailing "" ;# True if ... is present in $O + set lPosargs [list] + + # Populate A() with default values. Also, for each switch in the command + # line spec, set an entry in the idx() array as follows: + # + # {tblname t1 "table name to use"} + # -> [set idx(-tblname) {tblname t1 "table name to use"} + # + # For each position parameter, append its name to $lPosargs. If the ... + # specifier is present, set $zTrailing to the name of the prefix. + # + foreach o $O { + set nm [lindex $o 0] + set nArg [llength $o] + switch -- $nArg { + 1 { + if {[string range $nm end-2 end]=="..."} { + set zTrailing [string range $nm 0 end-3] + } else { + lappend lPosargs $nm + } + } + 2 { + set A($nm) 0 + set idx(-$nm) $o + } + 3 { + set A($nm) [lindex $o 1] + set idx(-$nm) $o + } + default { + error "Error in command line specification" + } + } + } + + # Set explicitly specified option values + # + set nArg [llength $lArgs] + for {set i 0} {$i < $nArg} {incr i} { + set opt [lindex $lArgs $i] + if {[string range $opt 0 0]!="-" || $opt=="--"} break + set c [array names idx "${opt}*"] + if {[llength $c]==0} { cmdline_error $O $E "Unrecognized option: $opt"} + if {[llength $c]>1} { cmdline_error $O $E "Ambiguous option: $opt"} + + if {[llength $idx($c)]==3} { + if {$i==[llength $lArgs]-1} { + cmdline_error $O $E "Option requires argument: $c" + } + incr i + set A([lindex $idx($c) 0]) [lindex $lArgs $i] + } else { + set A([lindex $idx($c) 0]) 1 + } + } + + # Deal with position arguments. + # + set nPosarg [llength $lPosargs] + set nRem [expr $nArg - $i] + if {$nRem < $nPosarg || ($zTrailing=="" && $nRem > $nPosarg)} { + cmdline_error $O $E + } + for {set j 0} {$j < $nPosarg} {incr j} { + set A([lindex $lPosargs $j]) [lindex $lArgs [expr $j+$i]] + } + if {$zTrailing!=""} { + set A($zTrailing) [lrange $lArgs [expr $j+$i] end] + } + } +} ;# namespace eval cmdline +# End of command line options processor. +########################################################################### +########################################################################### + +process_cmdline + +# If -fts4 was specified, use fts4. Otherwise, fts5. +if {$A(fts4)} { + set A(fts) fts4 +} else { + set A(fts) fts5 +} + +sqlite3 db $A(database) + +# Create the FTS table in the db. Return a list of the table columns. +# +proc create_table {} { + global A + set cols [list a b c d e f g h i j k l m n o p q r s t u v w x y z] + + set nCol [llength $A(colsize)] + set cols [lrange $cols 0 [expr $nCol-1]] + + set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $A(tblname) USING $A(fts) (" + append sql [join $cols ,] + if {$A(fts)=="fts5"} { append sql ",detail=$A(detail)" } + append sql ", prefix='$A(prefix)');" + + db eval $sql + return $cols +} + +# Return a list of tokens from the named file. +# +proc readfile {file} { + set fd [open $file] + set data [read $fd] + close $fd + split $data +} + +proc repeat {L n} { + set res [list] + for {set i 0} {$i < $n} {incr i} { + set res [concat $res $L] + } + set res +} + + +# Load all the data into a big list of tokens. +# +set tokens [list] +foreach f $A(file) { + set tokens [concat $tokens [repeat [readfile $f] $A(repeat)]] +} + +set N [llength $tokens] +set i 0 +set cols [create_table] +set sql "INSERT INTO $A(tblname) VALUES(\$R([lindex $cols 0])" +foreach c [lrange $cols 1 end] { + append sql ", \$R($c)" +} +append sql ")" + +db eval BEGIN + while {$i < $N} { + foreach c $cols s $A(colsize) { + set R($c) [lrange $tokens $i [expr $i+$s-1]] + incr i $s + } + db eval $sql + } +db eval COMMIT + + + diff --git a/ext/fts5/tool/loadfts5.tcl b/ext/fts5/tool/loadfts5.tcl new file mode 100644 index 0000000..96fd692 --- /dev/null +++ b/ext/fts5/tool/loadfts5.tcl @@ -0,0 +1,172 @@ + + +proc loadfile {f} { + set fd [open $f] + set data [read $fd] + close $fd + return $data +} + +set ::nRow 0 +set ::nRowPerDot 1000 + +proc load_hierachy {dir} { + foreach f [glob -nocomplain -dir $dir *] { + if {$::O(limit) && $::nRow>=$::O(limit)} break + if {[file isdir $f]} { + load_hierachy $f + } else { + db eval { INSERT INTO t1 VALUES($f, loadfile($f)) } + incr ::nRow + + if {$::O(trans) && ($::nRow % $::O(trans))==0} { + db eval { COMMIT } + db eval { INSERT INTO t1(t1) VALUES('integrity-check') } + db eval { BEGIN } + } + + if {($::nRow % $::nRowPerDot)==0} { + puts -nonewline . + if {($::nRow % (65*$::nRowPerDot))==0} { puts "" } + flush stdout + } + + } + } +} + +proc usage {} { + puts stderr "Usage: $::argv0 ?SWITCHES? DATABASE PATH" + puts stderr "" + puts stderr "Switches are:" + puts stderr " -fts4 (use fts4 instead of fts5)" + puts stderr " -fts5 (use fts5)" + puts stderr " -porter (use porter tokenizer)" + puts stderr " -delete (delete the database file before starting)" + puts stderr " -limit N (load no more than N documents)" + puts stderr " -automerge N (set the automerge parameter to N)" + puts stderr " -crisismerge N (set the crisismerge parameter to N)" + puts stderr " -prefix PREFIX (comma separated prefix= argument)" + puts stderr " -trans N (commit after N inserts - 0 == never)" + puts stderr " -hashsize N (set the fts5 hashsize parameter to N)" + puts stderr " -detail MODE (detail mode for fts5 tables)" + exit 1 +} + +set O(vtab) fts5 +set O(tok) "" +set O(limit) 0 +set O(delete) 0 +set O(automerge) -1 +set O(crisismerge) -1 +set O(prefix) "" +set O(trans) 0 +set O(hashsize) -1 +set O(detail) full + +if {[llength $argv]<2} usage +set nOpt [expr {[llength $argv]-2}] +for {set i 0} {$i < $nOpt} {incr i} { + set arg [lindex $argv $i] + switch -- [lindex $argv $i] { + -fts4 { + set O(vtab) fts4 + } + + -fts5 { + set O(vtab) fts5 + } + + -porter { + set O(tok) ", tokenize=porter" + } + + -delete { + set O(delete) 1 + } + + -limit { + if { [incr i]>=$nOpt } usage + set O(limit) [lindex $argv $i] + } + + -trans { + if { [incr i]>=$nOpt } usage + set O(trans) [lindex $argv $i] + } + + -automerge { + if { [incr i]>=$nOpt } usage + set O(automerge) [lindex $argv $i] + } + + -crisismerge { + if { [incr i]>=$nOpt } usage + set O(crisismerge) [lindex $argv $i] + } + + -prefix { + if { [incr i]>=$nOpt } usage + set O(prefix) [lindex $argv $i] + } + + -hashsize { + if { [incr i]>=$nOpt } usage + set O(hashsize) [lindex $argv $i] + } + + -detail { + if { [incr i]>=$nOpt } usage + set O(detail) [lindex $argv $i] + } + + default { + usage + } + } +} + +set dbfile [lindex $argv end-1] +if {$O(delete)} { file delete -force $dbfile } +sqlite3 db $dbfile +catch { load_static_extension db fts5 } +db func loadfile loadfile +db eval "PRAGMA page_size=4096" + +db eval BEGIN + set pref "" + if {$O(prefix)!=""} { set pref ", prefix='$O(prefix)'" } + if {$O(vtab)=="fts5"} { + append pref ", detail=$O(detail)" + } + catch { + db eval "CREATE VIRTUAL TABLE t1 USING $O(vtab) (path, content$O(tok)$pref)" + db eval "INSERT INTO t1(t1, rank) VALUES('pgsz', 4050);" + } + + if {$O(hashsize)>=0} { + catch { + db eval "INSERT INTO t1(t1, rank) VALUES('hashsize', $O(hashsize));" + } + } + + + if {$O(automerge)>=0} { + if {$O(vtab) == "fts5"} { + db eval { INSERT INTO t1(t1, rank) VALUES('automerge', $O(automerge)) } + } else { + db eval { INSERT INTO t1(t1) VALUES('automerge=' || $O(automerge)) } + } + } + if {$O(crisismerge)>=0} { + if {$O(vtab) == "fts5"} { + db eval {INSERT INTO t1(t1, rank) VALUES('crisismerge', $O(crisismerge))} + } else { + } + } + load_hierachy [lindex $argv end] +db eval COMMIT +puts "" + + + diff --git a/ext/fts5/tool/mkfts5c.tcl b/ext/fts5/tool/mkfts5c.tcl new file mode 100644 index 0000000..797811d --- /dev/null +++ b/ext/fts5/tool/mkfts5c.tcl @@ -0,0 +1,113 @@ +#!/bin/sh +# restart with tclsh \ +exec tclsh "$0" "$@" + +set srcdir [file dirname [file dirname [info script]]] +set G(src) [string map [list %dir% $srcdir] { + %dir%/fts5.h + %dir%/fts5Int.h + fts5parse.h + fts5parse.c + %dir%/fts5_aux.c + %dir%/fts5_buffer.c + %dir%/fts5_config.c + %dir%/fts5_expr.c + %dir%/fts5_hash.c + %dir%/fts5_index.c + %dir%/fts5_main.c + %dir%/fts5_storage.c + %dir%/fts5_tokenize.c + %dir%/fts5_unicode2.c + %dir%/fts5_varint.c + %dir%/fts5_vocab.c +}] + +set G(hdr) { + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) + +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif +#if defined(NDEBUG) && defined(SQLITE_DEBUG) +# undef NDEBUG +#endif + +} + +set G(footer) { + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */ +} + +#------------------------------------------------------------------------- +# Read and return the entire contents of text file $zFile from disk. +# +proc readfile {zFile} { + set fd [open $zFile] + set data [read $fd] + close $fd + return $data +} + +#------------------------------------------------------------------------- +# This command returns a string identifying the current sqlite version - +# the equivalent of the SQLITE_SOURCE_ID string. +# +proc fts5_source_id {zDir} { + set top [file dirname [file dirname $zDir]] + set uuid [string trim [readfile [file join $top manifest.uuid]]] + + set L [split [readfile [file join $top manifest]]] + set date [lindex $L [expr [lsearch -exact $L D]+1]] + set date [string range $date 0 [string last . $date]-1] + set date [string map {T { }} $date] + + return "fts5: $date $uuid" +} + +proc fts5c_init {zOut} { + global G + set G(fd) stdout + set G(fd) [open $zOut w] + + puts -nonewline $G(fd) $G(hdr) +} + +proc fts5c_printfile {zIn} { + global G + set data [readfile $zIn] + set zTail [file tail $zIn] + puts $G(fd) "#line 1 \"$zTail\"" + + set sub_map [list --FTS5-SOURCE-ID-- [fts5_source_id $::srcdir]] + if {$zTail=="fts5parse.c"} { + lappend sub_map yy fts5yy YY fts5YY TOKEN FTS5TOKEN + } + + foreach line [split $data "\n"] { + if {[regexp {^#include.*fts5} $line]} { + set line "/* $line */" + } elseif { + ![regexp { sqlite3Fts5Init\(} $line] + && [regexp {^(const )?[a-zA-Z][a-zA-Z0-9]* [*]?sqlite3Fts5} $line] + } { + set line "static $line" + } + set line [string map $sub_map $line] + puts $G(fd) $line + } +} + +proc fts5c_close {} { + global G + puts -nonewline $G(fd) $G(footer) + if {$G(fd)!="stdout"} { + close $G(fd) + } +} + + +fts5c_init fts5.c +foreach f $G(src) { fts5c_printfile $f } +fts5c_close diff --git a/ext/fts5/tool/showfts5.tcl b/ext/fts5/tool/showfts5.tcl new file mode 100644 index 0000000..75ac0f1 --- /dev/null +++ b/ext/fts5/tool/showfts5.tcl @@ -0,0 +1,97 @@ + + + +#------------------------------------------------------------------------- +# Process command line arguments. +# +proc usage {} { + puts stderr "usage: $::argv0 ?OPTIONS? database table" + puts stderr "" + puts stderr " -nterm (count number of terms in each segment)" + puts stderr " -segments (output segment contents)" + puts stderr "" + exit 1 +} + +set O(nterm) 0 +set O(segments) 0 + +if {[llength $argv]<2} usage +foreach a [lrange $argv 0 end-2] { + switch -- $a { + -nterm { + set O(nterm) 1 + } + + -segments { + set O(segments) 1 + } + + default { + usage + } + } +} + +set database [lindex $argv end-1] +set tbl [lindex $argv end] + + +#------------------------------------------------------------------------- +# Count the number of terms in each segment of fts5 table $tbl. Store the +# counts in the array variable in the parent context named by parameter +# $arrayname, indexed by segment-id. Example: +# +# count_terms fts_tbl A +# foreach {k v} [array get A] { puts "segid=$k nTerm=$v" } +# +proc count_terms {tbl arrayname} { + upvar A $arrayname + array unset A + db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data" { + set desc [lindex $d 0] + if {[regexp {^segid=([0-9]*)} $desc -> id]} { + foreach i [lrange $d 1 end] { + if {[string match {term=*} $i]} { incr A($id) } + } + } + } +} + + +#------------------------------------------------------------------------- +# Start of main program. +# +sqlite3 db $database +catch { load_static_extension db fts5 } + +if {$O(nterm)} { count_terms $tbl A } + +db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id=10" { + foreach lvl [lrange $d 1 end] { + puts [lrange $lvl 0 2] + + foreach seg [lrange $lvl 3 end] { + if {$::O(nterm)} { + regexp {^id=([0-9]*)} $seg -> id + set nTerm 0 + catch { set nTerm $A($id) } + puts [format " % -28s nTerm=%d" $seg $nTerm] + } else { + puts [format " % -28s" $seg] + } + } + } +} + +if {$O(segments)} { + puts "" + db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id>10" { + puts $d + } +} + + + + + diff --git a/ext/icu/icu.c b/ext/icu/icu.c index 1ce1e0c..a2ff492 100644 --- a/ext/icu/icu.c +++ b/ext/icu/icu.c @@ -83,7 +83,6 @@ static int icuLikeCompare( /* Read (and consume) the next character from the input pattern. */ UChar32 uPattern; U8_NEXT_UNSAFE(zPattern, iPattern, uPattern); - assert(uPattern!=0); /* There are now 4 possibilities: ** @@ -422,6 +421,7 @@ static void icuLoadCollation( int rc; /* Return code from sqlite3_create_collation_x() */ assert(nArg==2); + (void)nArg; /* Unused parameter */ zLocale = (const char *)sqlite3_value_text(apArg[0]); zName = (const char *)sqlite3_value_text(apArg[1]); diff --git a/ext/misc/amatch.c b/ext/misc/amatch.c index d08ef57..8524919 100644 --- a/ext/misc/amatch.c +++ b/ext/misc/amatch.c @@ -816,10 +816,10 @@ static const char *amatchValueOfKey(const char *zKey, const char *zStr){ int i; if( nStr>= 1; e++; } - while( ((m>>32)&0xfff00000)==0 ){ + while( m!=0 && ((m>>32)&0xfff00000)==0 ){ m <<= 1; e--; } e += 1075; if( e<0 ) e = m = 0; - if( e>0x7ff ) m = 0; + if( e>0x7ff ) e = 0x7ff; a = m & ((((sqlite3_int64)1)<<52)-1); a |= e<<52; - if( isNeg ) a |= ((sqlite3_int64)1)<<63; + if( isNeg ) a |= ((sqlite3_uint64)1)<<63; memcpy(&r, &a, sizeof(r)); sqlite3_result_double(context, r); } diff --git a/ext/misc/json1.c b/ext/misc/json1.c new file mode 100644 index 0000000..99d299c --- /dev/null +++ b/ext/misc/json1.c @@ -0,0 +1,2192 @@ +/* +** 2015-08-12 +** +** 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 SQLite extension implements JSON functions. The interface is +** modeled after MySQL JSON functions: +** +** https://dev.mysql.com/doc/refman/5.7/en/json.html +** +** For the time being, all JSON is stored as pure text. (We might add +** a JSONB type in the future which stores a binary encoding of JSON in +** a BLOB, but there is no support for JSONB in the current implementation. +** This implementation parses JSON text at 250 MB/s, so it is hard to see +** how JSONB might improve on that.) +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) +#if !defined(_SQLITEINT_H_) +#include "sqlite3ext.h" +#endif +SQLITE_EXTENSION_INIT1 +#include +#include +#include +#include + +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAM +# define UNUSED_PARAM(X) (void)(X) +#endif + +#ifndef LARGEST_INT64 +# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) +# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) +#endif + +/* +** Versions of isspace(), isalnum() and isdigit() to which it is safe +** to pass signed char values. +*/ +#ifdef sqlite3Isdigit + /* Use the SQLite core versions if this routine is part of the + ** SQLite amalgamation */ +# define safe_isdigit(x) sqlite3Isdigit(x) +# define safe_isalnum(x) sqlite3Isalnum(x) +#else + /* Use the standard library for separate compilation */ +#include /* amalgamator: keep */ +# define safe_isdigit(x) isdigit((unsigned char)(x)) +# define safe_isalnum(x) isalnum((unsigned char)(x)) +#endif + +/* +** Growing our own isspace() routine this way is twice as fast as +** the library isspace() function, resulting in a 7% overall performance +** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). +*/ +static const char jsonIsSpace[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#define safe_isspace(x) (jsonIsSpace[(unsigned char)x]) + +#ifndef SQLITE_AMALGAMATION + /* Unsigned integer types. These are already defined in the sqliteInt.h, + ** but the definitions need to be repeated for separate compilation. */ + typedef sqlite3_uint64 u64; + typedef unsigned int u32; + typedef unsigned char u8; +#endif + +/* Objects */ +typedef struct JsonString JsonString; +typedef struct JsonNode JsonNode; +typedef struct JsonParse JsonParse; + +/* An instance of this object represents a JSON string +** under construction. Really, this is a generic string accumulator +** that can be and is used to create strings other than JSON. +*/ +struct JsonString { + sqlite3_context *pCtx; /* Function context - put error messages here */ + char *zBuf; /* Append JSON content here */ + u64 nAlloc; /* Bytes of storage available in zBuf[] */ + u64 nUsed; /* Bytes of zBuf[] currently used */ + u8 bStatic; /* True if zBuf is static space */ + u8 bErr; /* True if an error has been encountered */ + char zSpace[100]; /* Initial static space */ +}; + +/* JSON type values +*/ +#define JSON_NULL 0 +#define JSON_TRUE 1 +#define JSON_FALSE 2 +#define JSON_INT 3 +#define JSON_REAL 4 +#define JSON_STRING 5 +#define JSON_ARRAY 6 +#define JSON_OBJECT 7 + +/* The "subtype" set for JSON values */ +#define JSON_SUBTYPE 74 /* Ascii for "J" */ + +/* +** Names of the various JSON types: +*/ +static const char * const jsonType[] = { + "null", "true", "false", "integer", "real", "text", "array", "object" +}; + +/* Bit values for the JsonNode.jnFlag field +*/ +#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */ +#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */ +#define JNODE_REMOVE 0x04 /* Do not output */ +#define JNODE_REPLACE 0x08 /* Replace with JsonNode.iVal */ +#define JNODE_APPEND 0x10 /* More ARRAY/OBJECT entries at u.iAppend */ +#define JNODE_LABEL 0x20 /* Is a label of an object */ + + +/* A single node of parsed JSON +*/ +struct JsonNode { + u8 eType; /* One of the JSON_ type values */ + u8 jnFlags; /* JNODE flags */ + u8 iVal; /* Replacement value when JNODE_REPLACE */ + u32 n; /* Bytes of content, or number of sub-nodes */ + union { + const char *zJContent; /* Content for INT, REAL, and STRING */ + u32 iAppend; /* More terms for ARRAY and OBJECT */ + u32 iKey; /* Key for ARRAY objects in json_tree() */ + } u; +}; + +/* A completely parsed JSON string +*/ +struct JsonParse { + u32 nNode; /* Number of slots of aNode[] used */ + u32 nAlloc; /* Number of slots of aNode[] allocated */ + JsonNode *aNode; /* Array of nodes containing the parse */ + const char *zJson; /* Original JSON string */ + u32 *aUp; /* Index of parent of each node */ + u8 oom; /* Set to true if out of memory */ + u8 nErr; /* Number of errors seen */ +}; + +/************************************************************************** +** Utility routines for dealing with JsonString objects +**************************************************************************/ + +/* Set the JsonString object to an empty string +*/ +static void jsonZero(JsonString *p){ + p->zBuf = p->zSpace; + p->nAlloc = sizeof(p->zSpace); + p->nUsed = 0; + p->bStatic = 1; +} + +/* Initialize the JsonString object +*/ +static void jsonInit(JsonString *p, sqlite3_context *pCtx){ + p->pCtx = pCtx; + p->bErr = 0; + jsonZero(p); +} + + +/* Free all allocated memory and reset the JsonString object back to its +** initial state. +*/ +static void jsonReset(JsonString *p){ + if( !p->bStatic ) sqlite3_free(p->zBuf); + jsonZero(p); +} + + +/* Report an out-of-memory (OOM) condition +*/ +static void jsonOom(JsonString *p){ + p->bErr = 1; + sqlite3_result_error_nomem(p->pCtx); + jsonReset(p); +} + +/* Enlarge pJson->zBuf so that it can hold at least N more bytes. +** Return zero on success. Return non-zero on an OOM error +*/ +static int jsonGrow(JsonString *p, u32 N){ + u64 nTotal = NnAlloc ? p->nAlloc*2 : p->nAlloc+N+10; + char *zNew; + if( p->bStatic ){ + if( p->bErr ) return 1; + zNew = sqlite3_malloc64(nTotal); + if( zNew==0 ){ + jsonOom(p); + return SQLITE_NOMEM; + } + memcpy(zNew, p->zBuf, (size_t)p->nUsed); + p->zBuf = zNew; + p->bStatic = 0; + }else{ + zNew = sqlite3_realloc64(p->zBuf, nTotal); + if( zNew==0 ){ + jsonOom(p); + return SQLITE_NOMEM; + } + p->zBuf = zNew; + } + p->nAlloc = nTotal; + return SQLITE_OK; +} + +/* Append N bytes from zIn onto the end of the JsonString string. +*/ +static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ + if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return; + memcpy(p->zBuf+p->nUsed, zIn, N); + p->nUsed += N; +} + +/* Append formatted text (not to exceed N bytes) to the JsonString. +*/ +static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ + va_list ap; + if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return; + va_start(ap, zFormat); + sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); + va_end(ap); + p->nUsed += (int)strlen(p->zBuf+p->nUsed); +} + +/* Append a single character +*/ +static void jsonAppendChar(JsonString *p, char c){ + if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return; + p->zBuf[p->nUsed++] = c; +} + +/* Append a comma separator to the output buffer, if the previous +** character is not '[' or '{'. +*/ +static void jsonAppendSeparator(JsonString *p){ + char c; + if( p->nUsed==0 ) return; + c = p->zBuf[p->nUsed-1]; + if( c!='[' && c!='{' ) jsonAppendChar(p, ','); +} + +/* Append the N-byte string in zIn to the end of the JsonString string +** under construction. Enclose the string in "..." and escape +** any double-quotes or backslash characters contained within the +** string. +*/ +static void jsonAppendString(JsonString *p, const char *zIn, u32 N){ + u32 i; + if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return; + p->zBuf[p->nUsed++] = '"'; + for(i=0; inUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + }else if( c<=0x1f ){ + static const char aSpecial[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + assert( sizeof(aSpecial)==32 ); + assert( aSpecial['\b']=='b' ); + assert( aSpecial['\f']=='f' ); + assert( aSpecial['\n']=='n' ); + assert( aSpecial['\r']=='r' ); + assert( aSpecial['\t']=='t' ); + if( aSpecial[c] ){ + c = aSpecial[c]; + goto json_simple_escape; + } + if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + p->zBuf[p->nUsed++] = 'u'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0' + (c>>4); + c = "0123456789abcdef"[c&0xf]; + } + p->zBuf[p->nUsed++] = c; + } + p->zBuf[p->nUsed++] = '"'; + assert( p->nUsednAlloc ); +} + +/* +** Append a function parameter value to the JSON string under +** construction. +*/ +static void jsonAppendValue( + JsonString *p, /* Append to this JSON string */ + sqlite3_value *pValue /* Value to append */ +){ + switch( sqlite3_value_type(pValue) ){ + case SQLITE_NULL: { + jsonAppendRaw(p, "null", 4); + break; + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + const char *z = (const char*)sqlite3_value_text(pValue); + u32 n = (u32)sqlite3_value_bytes(pValue); + jsonAppendRaw(p, z, n); + break; + } + case SQLITE_TEXT: { + const char *z = (const char*)sqlite3_value_text(pValue); + u32 n = (u32)sqlite3_value_bytes(pValue); + if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){ + jsonAppendRaw(p, z, n); + }else{ + jsonAppendString(p, z, n); + } + break; + } + default: { + if( p->bErr==0 ){ + sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1); + p->bErr = 2; + jsonReset(p); + } + break; + } + } +} + + +/* Make the JSON in p the result of the SQL function. +*/ +static void jsonResult(JsonString *p){ + if( p->bErr==0 ){ + sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, + p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, + SQLITE_UTF8); + jsonZero(p); + } + assert( p->bStatic ); +} + +/************************************************************************** +** Utility routines for dealing with JsonNode and JsonParse objects +**************************************************************************/ + +/* +** Return the number of consecutive JsonNode slots need to represent +** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and +** OBJECT types, the number might be larger. +** +** Appended elements are not counted. The value returned is the number +** by which the JsonNode counter should increment in order to go to the +** next peer value. +*/ +static u32 jsonNodeSize(JsonNode *pNode){ + return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1; +} + +/* +** Reclaim all memory allocated by a JsonParse object. But do not +** delete the JsonParse object itself. +*/ +static void jsonParseReset(JsonParse *pParse){ + sqlite3_free(pParse->aNode); + pParse->aNode = 0; + pParse->nNode = 0; + pParse->nAlloc = 0; + sqlite3_free(pParse->aUp); + pParse->aUp = 0; +} + +/* +** Convert the JsonNode pNode into a pure JSON string and +** append to pOut. Subsubstructure is also included. Return +** the number of JsonNode objects that are encoded. +*/ +static void jsonRenderNode( + JsonNode *pNode, /* The node to render */ + JsonString *pOut, /* Write JSON here */ + sqlite3_value **aReplace /* Replacement values */ +){ + switch( pNode->eType ){ + default: { + assert( pNode->eType==JSON_NULL ); + jsonAppendRaw(pOut, "null", 4); + break; + } + case JSON_TRUE: { + jsonAppendRaw(pOut, "true", 4); + break; + } + case JSON_FALSE: { + jsonAppendRaw(pOut, "false", 5); + break; + } + case JSON_STRING: { + if( pNode->jnFlags & JNODE_RAW ){ + jsonAppendString(pOut, pNode->u.zJContent, pNode->n); + break; + } + /* Fall through into the next case */ + } + case JSON_REAL: + case JSON_INT: { + jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case JSON_ARRAY: { + u32 j = 1; + jsonAppendChar(pOut, '['); + for(;;){ + while( j<=pNode->n ){ + if( pNode[j].jnFlags & (JNODE_REMOVE|JNODE_REPLACE) ){ + if( pNode[j].jnFlags & JNODE_REPLACE ){ + jsonAppendSeparator(pOut); + jsonAppendValue(pOut, aReplace[pNode[j].iVal]); + } + }else{ + jsonAppendSeparator(pOut); + jsonRenderNode(&pNode[j], pOut, aReplace); + } + j += jsonNodeSize(&pNode[j]); + } + if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + pNode = &pNode[pNode->u.iAppend]; + j = 1; + } + jsonAppendChar(pOut, ']'); + break; + } + case JSON_OBJECT: { + u32 j = 1; + jsonAppendChar(pOut, '{'); + for(;;){ + while( j<=pNode->n ){ + if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){ + jsonAppendSeparator(pOut); + jsonRenderNode(&pNode[j], pOut, aReplace); + jsonAppendChar(pOut, ':'); + if( pNode[j+1].jnFlags & JNODE_REPLACE ){ + jsonAppendValue(pOut, aReplace[pNode[j+1].iVal]); + }else{ + jsonRenderNode(&pNode[j+1], pOut, aReplace); + } + } + j += 1 + jsonNodeSize(&pNode[j+1]); + } + if( (pNode->jnFlags & JNODE_APPEND)==0 ) break; + pNode = &pNode[pNode->u.iAppend]; + j = 1; + } + jsonAppendChar(pOut, '}'); + break; + } + } +} + +/* +** Return a JsonNode and all its descendents as a JSON string. +*/ +static void jsonReturnJson( + JsonNode *pNode, /* Node to return */ + sqlite3_context *pCtx, /* Return value for this function */ + sqlite3_value **aReplace /* Array of replacement values */ +){ + JsonString s; + jsonInit(&s, pCtx); + jsonRenderNode(pNode, &s, aReplace); + jsonResult(&s); + sqlite3_result_subtype(pCtx, JSON_SUBTYPE); +} + +/* +** Make the JsonNode the return value of the function. +*/ +static void jsonReturn( + JsonNode *pNode, /* Node to return */ + sqlite3_context *pCtx, /* Return value for this function */ + sqlite3_value **aReplace /* Array of replacement values */ +){ + switch( pNode->eType ){ + default: { + assert( pNode->eType==JSON_NULL ); + sqlite3_result_null(pCtx); + break; + } + case JSON_TRUE: { + sqlite3_result_int(pCtx, 1); + break; + } + case JSON_FALSE: { + sqlite3_result_int(pCtx, 0); + break; + } + case JSON_INT: { + sqlite3_int64 i = 0; + const char *z = pNode->u.zJContent; + if( z[0]=='-' ){ z++; } + while( z[0]>='0' && z[0]<='9' ){ + unsigned v = *(z++) - '0'; + if( i>=LARGEST_INT64/10 ){ + if( i>LARGEST_INT64/10 ) goto int_as_real; + if( z[0]>='0' && z[0]<='9' ) goto int_as_real; + if( v==9 ) goto int_as_real; + if( v==8 ){ + if( pNode->u.zJContent[0]=='-' ){ + sqlite3_result_int64(pCtx, SMALLEST_INT64); + goto int_done; + }else{ + goto int_as_real; + } + } + } + i = i*10 + v; + } + if( pNode->u.zJContent[0]=='-' ){ i = -i; } + sqlite3_result_int64(pCtx, i); + int_done: + break; + int_as_real: /* fall through to real */; + } + case JSON_REAL: { + double r; +#ifdef SQLITE_AMALGAMATION + const char *z = pNode->u.zJContent; + sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); +#else + r = strtod(pNode->u.zJContent, 0); +#endif + sqlite3_result_double(pCtx, r); + break; + } + case JSON_STRING: { +#if 0 /* Never happens because JNODE_RAW is only set by json_set(), + ** json_insert() and json_replace() and those routines do not + ** call jsonReturn() */ + if( pNode->jnFlags & JNODE_RAW ){ + sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n, + SQLITE_TRANSIENT); + }else +#endif + assert( (pNode->jnFlags & JNODE_RAW)==0 ); + if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){ + /* JSON formatted without any backslash-escapes */ + sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2, + SQLITE_TRANSIENT); + }else{ + /* Translate JSON formatted string into raw text */ + u32 i; + u32 n = pNode->n; + const char *z = pNode->u.zJContent; + char *zOut; + u32 j; + zOut = sqlite3_malloc( n+1 ); + if( zOut==0 ){ + sqlite3_result_error_nomem(pCtx); + break; + } + for(i=1, j=0; i='0' && c<='9' ) v = v*16 + c - '0'; + else if( c>='A' && c<='F' ) v = v*16 + c - 'A' + 10; + else if( c>='a' && c<='f' ) v = v*16 + c - 'a' + 10; + else break; + } + if( v==0 ) break; + if( v<=0x7f ){ + zOut[j++] = (char)v; + }else if( v<=0x7ff ){ + zOut[j++] = (char)(0xc0 | (v>>6)); + zOut[j++] = 0x80 | (v&0x3f); + }else{ + zOut[j++] = (char)(0xe0 | (v>>12)); + zOut[j++] = 0x80 | ((v>>6)&0x3f); + zOut[j++] = 0x80 | (v&0x3f); + } + }else{ + if( c=='b' ){ + c = '\b'; + }else if( c=='f' ){ + c = '\f'; + }else if( c=='n' ){ + c = '\n'; + }else if( c=='r' ){ + c = '\r'; + }else if( c=='t' ){ + c = '\t'; + } + zOut[j++] = c; + } + } + } + zOut[j] = 0; + sqlite3_result_text(pCtx, zOut, j, sqlite3_free); + } + break; + } + case JSON_ARRAY: + case JSON_OBJECT: { + jsonReturnJson(pNode, pCtx, aReplace); + break; + } + } +} + +/* Forward reference */ +static int jsonParseAddNode(JsonParse*,u32,u32,const char*); + +/* +** A macro to hint to the compiler that a function should not be +** inlined. +*/ +#if defined(__GNUC__) +# define JSON_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) && _MSC_VER>=1310 +# define JSON_NOINLINE __declspec(noinline) +#else +# define JSON_NOINLINE +#endif + + +static JSON_NOINLINE int jsonParseAddNodeExpand( + JsonParse *pParse, /* Append the node to this object */ + u32 eType, /* Node type */ + u32 n, /* Content size or sub-node count */ + const char *zContent /* Content */ +){ + u32 nNew; + JsonNode *pNew; + assert( pParse->nNode>=pParse->nAlloc ); + if( pParse->oom ) return -1; + nNew = pParse->nAlloc*2 + 10; + pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew); + if( pNew==0 ){ + pParse->oom = 1; + return -1; + } + pParse->nAlloc = nNew; + pParse->aNode = pNew; + assert( pParse->nNodenAlloc ); + return jsonParseAddNode(pParse, eType, n, zContent); +} + +/* +** Create a new JsonNode instance based on the arguments and append that +** instance to the JsonParse. Return the index in pParse->aNode[] of the +** new node, or -1 if a memory allocation fails. +*/ +static int jsonParseAddNode( + JsonParse *pParse, /* Append the node to this object */ + u32 eType, /* Node type */ + u32 n, /* Content size or sub-node count */ + const char *zContent /* Content */ +){ + JsonNode *p; + if( pParse->nNode>=pParse->nAlloc ){ + return jsonParseAddNodeExpand(pParse, eType, n, zContent); + } + p = &pParse->aNode[pParse->nNode]; + p->eType = (u8)eType; + p->jnFlags = 0; + p->iVal = 0; + p->n = n; + p->u.zJContent = zContent; + return pParse->nNode++; +} + +/* +** Parse a single JSON value which begins at pParse->zJson[i]. Return the +** index of the first character past the end of the value parsed. +** +** Return negative for a syntax error. Special cases: return -2 if the +** first non-whitespace character is '}' and return -3 if the first +** non-whitespace character is ']'. +*/ +static int jsonParseValue(JsonParse *pParse, u32 i){ + char c; + u32 j; + int iThis; + int x; + JsonNode *pNode; + while( safe_isspace(pParse->zJson[i]) ){ i++; } + if( (c = pParse->zJson[i])=='{' ){ + /* Parse object */ + iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); + if( iThis<0 ) return -1; + for(j=i+1;;j++){ + while( safe_isspace(pParse->zJson[j]) ){ j++; } + x = jsonParseValue(pParse, j); + if( x<0 ){ + if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1; + return -1; + } + if( pParse->oom ) return -1; + pNode = &pParse->aNode[pParse->nNode-1]; + if( pNode->eType!=JSON_STRING ) return -1; + pNode->jnFlags |= JNODE_LABEL; + j = x; + while( safe_isspace(pParse->zJson[j]) ){ j++; } + if( pParse->zJson[j]!=':' ) return -1; + j++; + x = jsonParseValue(pParse, j); + if( x<0 ) return -1; + j = x; + while( safe_isspace(pParse->zJson[j]) ){ j++; } + c = pParse->zJson[j]; + if( c==',' ) continue; + if( c!='}' ) return -1; + break; + } + pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; + return j+1; + }else if( c=='[' ){ + /* Parse array */ + iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); + if( iThis<0 ) return -1; + for(j=i+1;;j++){ + while( safe_isspace(pParse->zJson[j]) ){ j++; } + x = jsonParseValue(pParse, j); + if( x<0 ){ + if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1; + return -1; + } + j = x; + while( safe_isspace(pParse->zJson[j]) ){ j++; } + c = pParse->zJson[j]; + if( c==',' ) continue; + if( c!=']' ) return -1; + break; + } + pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; + return j+1; + }else if( c=='"' ){ + /* Parse string */ + u8 jnFlags = 0; + j = i+1; + for(;;){ + c = pParse->zJson[j]; + if( c==0 ) return -1; + if( c=='\\' ){ + c = pParse->zJson[++j]; + if( c==0 ) return -1; + jnFlags = JNODE_ESCAPE; + }else if( c=='"' ){ + break; + } + j++; + } + jsonParseAddNode(pParse, JSON_STRING, j+1-i, &pParse->zJson[i]); + if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags; + return j+1; + }else if( c=='n' + && strncmp(pParse->zJson+i,"null",4)==0 + && !safe_isalnum(pParse->zJson[i+4]) ){ + jsonParseAddNode(pParse, JSON_NULL, 0, 0); + return i+4; + }else if( c=='t' + && strncmp(pParse->zJson+i,"true",4)==0 + && !safe_isalnum(pParse->zJson[i+4]) ){ + jsonParseAddNode(pParse, JSON_TRUE, 0, 0); + return i+4; + }else if( c=='f' + && strncmp(pParse->zJson+i,"false",5)==0 + && !safe_isalnum(pParse->zJson[i+5]) ){ + jsonParseAddNode(pParse, JSON_FALSE, 0, 0); + return i+5; + }else if( c=='-' || (c>='0' && c<='9') ){ + /* Parse number */ + u8 seenDP = 0; + u8 seenE = 0; + j = i+1; + for(;; j++){ + c = pParse->zJson[j]; + if( c>='0' && c<='9' ) continue; + if( c=='.' ){ + if( pParse->zJson[j-1]=='-' ) return -1; + if( seenDP ) return -1; + seenDP = 1; + continue; + } + if( c=='e' || c=='E' ){ + if( pParse->zJson[j-1]<'0' ) return -1; + if( seenE ) return -1; + seenDP = seenE = 1; + c = pParse->zJson[j+1]; + if( c=='+' || c=='-' ){ + j++; + c = pParse->zJson[j+1]; + } + if( c<'0' || c>'9' ) return -1; + continue; + } + break; + } + if( pParse->zJson[j-1]<'0' ) return -1; + jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT, + j - i, &pParse->zJson[i]); + return j; + }else if( c=='}' ){ + return -2; /* End of {...} */ + }else if( c==']' ){ + return -3; /* End of [...] */ + }else if( c==0 ){ + return 0; /* End of file */ + }else{ + return -1; /* Syntax error */ + } +} + +/* +** Parse a complete JSON string. Return 0 on success or non-zero if there +** are any errors. If an error occurs, free all memory associated with +** pParse. +** +** pParse is uninitialized when this routine is called. +*/ +static int jsonParse( + JsonParse *pParse, /* Initialize and fill this JsonParse object */ + sqlite3_context *pCtx, /* Report errors here */ + const char *zJson /* Input JSON text to be parsed */ +){ + int i; + memset(pParse, 0, sizeof(*pParse)); + if( zJson==0 ) return 1; + pParse->zJson = zJson; + i = jsonParseValue(pParse, 0); + if( pParse->oom ) i = -1; + if( i>0 ){ + while( safe_isspace(zJson[i]) ) i++; + if( zJson[i] ) i = -1; + } + if( i<=0 ){ + if( pCtx!=0 ){ + if( pParse->oom ){ + sqlite3_result_error_nomem(pCtx); + }else{ + sqlite3_result_error(pCtx, "malformed JSON", -1); + } + } + jsonParseReset(pParse); + return 1; + } + return 0; +} + +/* Mark node i of pParse as being a child of iParent. Call recursively +** to fill in all the descendants of node i. +*/ +static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){ + JsonNode *pNode = &pParse->aNode[i]; + u32 j; + pParse->aUp[i] = iParent; + switch( pNode->eType ){ + case JSON_ARRAY: { + for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){ + jsonParseFillInParentage(pParse, i+j, i); + } + break; + } + case JSON_OBJECT: { + for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){ + pParse->aUp[i+j] = i; + jsonParseFillInParentage(pParse, i+j+1, i); + } + break; + } + default: { + break; + } + } +} + +/* +** Compute the parentage of all nodes in a completed parse. +*/ +static int jsonParseFindParents(JsonParse *pParse){ + u32 *aUp; + assert( pParse->aUp==0 ); + aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode ); + if( aUp==0 ){ + pParse->oom = 1; + return SQLITE_NOMEM; + } + jsonParseFillInParentage(pParse, 0, 0); + return SQLITE_OK; +} + +/* +** Compare the OBJECT label at pNode against zKey,nKey. Return true on +** a match. +*/ +static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ + if( pNode->jnFlags & JNODE_RAW ){ + if( pNode->n!=nKey ) return 0; + return strncmp(pNode->u.zJContent, zKey, nKey)==0; + }else{ + if( pNode->n!=nKey+2 ) return 0; + return strncmp(pNode->u.zJContent+1, zKey, nKey)==0; + } +} + +/* forward declaration */ +static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**); + +/* +** Search along zPath to find the node specified. Return a pointer +** to that node, or NULL if zPath is malformed or if there is no such +** node. +** +** If pApnd!=0, then try to append new nodes to complete zPath if it is +** possible to do so and if no existing node corresponds to zPath. If +** new nodes are appended *pApnd is set to 1. +*/ +static JsonNode *jsonLookupStep( + JsonParse *pParse, /* The JSON to search */ + u32 iRoot, /* Begin the search at this node */ + const char *zPath, /* The path to search */ + int *pApnd, /* Append nodes to complete path if not NULL */ + const char **pzErr /* Make *pzErr point to any syntax error in zPath */ +){ + u32 i, j, nKey; + const char *zKey; + JsonNode *pRoot = &pParse->aNode[iRoot]; + if( zPath[0]==0 ) return pRoot; + if( zPath[0]=='.' ){ + if( pRoot->eType!=JSON_OBJECT ) return 0; + zPath++; + if( zPath[0]=='"' ){ + zKey = zPath + 1; + for(i=1; zPath[i] && zPath[i]!='"'; i++){} + nKey = i-1; + if( zPath[i] ){ + i++; + }else{ + *pzErr = zPath; + return 0; + } + }else{ + zKey = zPath; + for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} + nKey = i; + } + if( nKey==0 ){ + *pzErr = zPath; + return 0; + } + j = 1; + for(;;){ + while( j<=pRoot->n ){ + if( jsonLabelCompare(pRoot+j, zKey, nKey) ){ + return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); + } + j++; + j += jsonNodeSize(&pRoot[j]); + } + if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; + iRoot += pRoot->u.iAppend; + pRoot = &pParse->aNode[iRoot]; + j = 1; + } + if( pApnd ){ + u32 iStart, iLabel; + JsonNode *pNode; + iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); + iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath); + zPath += i; + pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); + if( pParse->oom ) return 0; + if( pNode ){ + pRoot = &pParse->aNode[iRoot]; + pRoot->u.iAppend = iStart - iRoot; + pRoot->jnFlags |= JNODE_APPEND; + pParse->aNode[iLabel].jnFlags |= JNODE_RAW; + } + return pNode; + } + }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){ + if( pRoot->eType!=JSON_ARRAY ) return 0; + i = 0; + j = 1; + while( safe_isdigit(zPath[j]) ){ + i = i*10 + zPath[j] - '0'; + j++; + } + if( zPath[j]!=']' ){ + *pzErr = zPath; + return 0; + } + zPath += j + 1; + j = 1; + for(;;){ + while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){ + if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--; + j += jsonNodeSize(&pRoot[j]); + } + if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break; + iRoot += pRoot->u.iAppend; + pRoot = &pParse->aNode[iRoot]; + j = 1; + } + if( j<=pRoot->n ){ + return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); + } + if( i==0 && pApnd ){ + u32 iStart; + JsonNode *pNode; + iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0); + pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr); + if( pParse->oom ) return 0; + if( pNode ){ + pRoot = &pParse->aNode[iRoot]; + pRoot->u.iAppend = iStart - iRoot; + pRoot->jnFlags |= JNODE_APPEND; + } + return pNode; + } + }else{ + *pzErr = zPath; + } + return 0; +} + +/* +** Append content to pParse that will complete zPath. Return a pointer +** to the inserted node, or return NULL if the append fails. +*/ +static JsonNode *jsonLookupAppend( + JsonParse *pParse, /* Append content to the JSON parse */ + const char *zPath, /* Description of content to append */ + int *pApnd, /* Set this flag to 1 */ + const char **pzErr /* Make this point to any syntax error */ +){ + *pApnd = 1; + if( zPath[0]==0 ){ + jsonParseAddNode(pParse, JSON_NULL, 0, 0); + return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; + } + if( zPath[0]=='.' ){ + jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); + }else if( strncmp(zPath,"[0]",3)==0 ){ + jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); + }else{ + return 0; + } + if( pParse->oom ) return 0; + return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); +} + +/* +** Return the text of a syntax error message on a JSON path. Space is +** obtained from sqlite3_malloc(). +*/ +static char *jsonPathSyntaxError(const char *zErr){ + return sqlite3_mprintf("JSON path error near '%q'", zErr); +} + +/* +** Do a node lookup using zPath. Return a pointer to the node on success. +** Return NULL if not found or if there is an error. +** +** On an error, write an error message into pCtx and increment the +** pParse->nErr counter. +** +** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if +** nodes are appended. +*/ +static JsonNode *jsonLookup( + JsonParse *pParse, /* The JSON to search */ + const char *zPath, /* The path to search */ + int *pApnd, /* Append nodes to complete path if not NULL */ + sqlite3_context *pCtx /* Report errors here, if not NULL */ +){ + const char *zErr = 0; + JsonNode *pNode = 0; + char *zMsg; + + if( zPath==0 ) return 0; + if( zPath[0]!='$' ){ + zErr = zPath; + goto lookup_err; + } + zPath++; + pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr); + if( zErr==0 ) return pNode; + +lookup_err: + pParse->nErr++; + assert( zErr!=0 && pCtx!=0 ); + zMsg = jsonPathSyntaxError(zErr); + if( zMsg ){ + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); + }else{ + sqlite3_result_error_nomem(pCtx); + } + return 0; +} + + +/* +** Report the wrong number of arguments for json_insert(), json_replace() +** or json_set(). +*/ +static void jsonWrongNumArgs( + sqlite3_context *pCtx, + const char *zFuncName +){ + char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments", + zFuncName); + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); +} + + +/**************************************************************************** +** SQL functions used for testing and debugging +****************************************************************************/ + +#ifdef SQLITE_DEBUG +/* +** The json_parse(JSON) function returns a string which describes +** a parse of the JSON provided. Or it returns NULL if JSON is not +** well-formed. +*/ +static void jsonParseFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonString s; /* Output string - not real JSON */ + JsonParse x; /* The parse */ + u32 i; + + assert( argc==1 ); + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + jsonParseFindParents(&x); + jsonInit(&s, ctx); + for(i=0; ieType==JSON_ARRAY ){ + assert( (pNode->jnFlags & JNODE_APPEND)==0 ); + for(i=1; i<=pNode->n; n++){ + i += jsonNodeSize(&pNode[i]); + } + } + if( x.nErr==0 ) sqlite3_result_int64(ctx, n); + jsonParseReset(&x); +} + +/* +** json_extract(JSON, PATH, ...) +** +** Return the element described by PATH. Return NULL if there is no +** PATH element. If there are multiple PATHs, then return a JSON array +** with the result from each path. Throw an error if the JSON or any PATH +** is malformed. +*/ +static void jsonExtractFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + JsonNode *pNode; + const char *zPath; + JsonString jx; + int i; + + if( argc<2 ) return; + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + jsonInit(&jx, ctx); + jsonAppendChar(&jx, '['); + for(i=1; i2 ){ + jsonAppendSeparator(&jx); + if( pNode ){ + jsonRenderNode(pNode, &jx, 0); + }else{ + jsonAppendRaw(&jx, "null", 4); + } + }else if( pNode ){ + jsonReturn(pNode, ctx, 0); + } + } + if( argc>2 && i==argc ){ + jsonAppendChar(&jx, ']'); + jsonResult(&jx); + sqlite3_result_subtype(ctx, JSON_SUBTYPE); + } + jsonReset(&jx); + jsonParseReset(&x); +} + +/* +** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON +** object that contains all name/value given in arguments. Or if any name +** is not a string or if any value is a BLOB, throw an error. +*/ +static void jsonObjectFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + int i; + JsonString jx; + const char *z; + u32 n; + + if( argc&1 ){ + sqlite3_result_error(ctx, "json_object() requires an even number " + "of arguments", -1); + return; + } + jsonInit(&jx, ctx); + jsonAppendChar(&jx, '{'); + for(i=0; ijnFlags |= JNODE_REMOVE; + } + if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){ + jsonReturnJson(x.aNode, ctx, 0); + } +remove_done: + jsonParseReset(&x); +} + +/* +** json_replace(JSON, PATH, VALUE, ...) +** +** Replace the value at PATH with VALUE. If PATH does not already exist, +** this routine is a no-op. If JSON or PATH is malformed, throw an error. +*/ +static void jsonReplaceFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + JsonNode *pNode; + const char *zPath; + u32 i; + + if( argc<1 ) return; + if( (argc&1)==0 ) { + jsonWrongNumArgs(ctx, "replace"); + return; + } + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + for(i=1; i<(u32)argc; i+=2){ + zPath = (const char*)sqlite3_value_text(argv[i]); + pNode = jsonLookup(&x, zPath, 0, ctx); + if( x.nErr ) goto replace_err; + if( pNode ){ + pNode->jnFlags |= (u8)JNODE_REPLACE; + pNode->iVal = (u8)(i+1); + } + } + if( x.aNode[0].jnFlags & JNODE_REPLACE ){ + sqlite3_result_value(ctx, argv[x.aNode[0].iVal]); + }else{ + jsonReturnJson(x.aNode, ctx, argv); + } +replace_err: + jsonParseReset(&x); +} + +/* +** json_set(JSON, PATH, VALUE, ...) +** +** Set the value at PATH to VALUE. Create the PATH if it does not already +** exist. Overwrite existing values that do exist. +** If JSON or PATH is malformed, throw an error. +** +** json_insert(JSON, PATH, VALUE, ...) +** +** Create PATH and initialize it to VALUE. If PATH already exists, this +** routine is a no-op. If JSON or PATH is malformed, throw an error. +*/ +static void jsonSetFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + JsonNode *pNode; + const char *zPath; + u32 i; + int bApnd; + int bIsSet = *(int*)sqlite3_user_data(ctx); + + if( argc<1 ) return; + if( (argc&1)==0 ) { + jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert"); + return; + } + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + for(i=1; i<(u32)argc; i+=2){ + zPath = (const char*)sqlite3_value_text(argv[i]); + bApnd = 0; + pNode = jsonLookup(&x, zPath, &bApnd, ctx); + if( x.oom ){ + sqlite3_result_error_nomem(ctx); + goto jsonSetDone; + }else if( x.nErr ){ + goto jsonSetDone; + }else if( pNode && (bApnd || bIsSet) ){ + pNode->jnFlags |= (u8)JNODE_REPLACE; + pNode->iVal = (u8)(i+1); + } + } + if( x.aNode[0].jnFlags & JNODE_REPLACE ){ + sqlite3_result_value(ctx, argv[x.aNode[0].iVal]); + }else{ + jsonReturnJson(x.aNode, ctx, argv); + } +jsonSetDone: + jsonParseReset(&x); +} + +/* +** json_type(JSON) +** json_type(JSON, PATH) +** +** Return the top-level "type" of a JSON string. Throw an error if +** either the JSON or PATH inputs are not well-formed. +*/ +static void jsonTypeFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + const char *zPath; + JsonNode *pNode; + + if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + if( argc==2 ){ + zPath = (const char*)sqlite3_value_text(argv[1]); + pNode = jsonLookup(&x, zPath, 0, ctx); + }else{ + pNode = x.aNode; + } + if( pNode ){ + sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC); + } + jsonParseReset(&x); +} + +/* +** json_valid(JSON) +** +** Return 1 if JSON is a well-formed JSON string according to RFC-7159. +** Return 0 otherwise. +*/ +static void jsonValidFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonParse x; /* The parse */ + int rc = 0; + + UNUSED_PARAM(argc); + if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){ + rc = 1; + } + jsonParseReset(&x); + sqlite3_result_int(ctx, rc); +} + + +/**************************************************************************** +** Aggregate SQL function implementations +****************************************************************************/ +/* +** json_group_array(VALUE) +** +** Return a JSON array composed of all values in the aggregate. +*/ +static void jsonArrayStep( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonString *pStr; + UNUSED_PARAM(argc); + pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); + if( pStr ){ + if( pStr->zBuf==0 ){ + jsonInit(pStr, ctx); + jsonAppendChar(pStr, '['); + }else{ + jsonAppendChar(pStr, ','); + pStr->pCtx = ctx; + } + jsonAppendValue(pStr, argv[0]); + } +} +static void jsonArrayFinal(sqlite3_context *ctx){ + JsonString *pStr; + pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); + if( pStr ){ + pStr->pCtx = ctx; + jsonAppendChar(pStr, ']'); + if( pStr->bErr ){ + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); + assert( pStr->bStatic ); + }else{ + sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, + pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic = 1; + } + }else{ + sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); + } + sqlite3_result_subtype(ctx, JSON_SUBTYPE); +} + +/* +** json_group_obj(NAME,VALUE) +** +** Return a JSON object composed of all names and values in the aggregate. +*/ +static void jsonObjectStep( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + JsonString *pStr; + const char *z; + u32 n; + UNUSED_PARAM(argc); + pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); + if( pStr ){ + if( pStr->zBuf==0 ){ + jsonInit(pStr, ctx); + jsonAppendChar(pStr, '{'); + }else{ + jsonAppendChar(pStr, ','); + pStr->pCtx = ctx; + } + z = (const char*)sqlite3_value_text(argv[0]); + n = (u32)sqlite3_value_bytes(argv[0]); + jsonAppendString(pStr, z, n); + jsonAppendChar(pStr, ':'); + jsonAppendValue(pStr, argv[1]); + } +} +static void jsonObjectFinal(sqlite3_context *ctx){ + JsonString *pStr; + pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); + if( pStr ){ + jsonAppendChar(pStr, '}'); + if( pStr->bErr ){ + if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx); + assert( pStr->bStatic ); + }else{ + sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed, + pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic = 1; + } + }else{ + sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); + } + sqlite3_result_subtype(ctx, JSON_SUBTYPE); +} + + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/**************************************************************************** +** The json_each virtual table +****************************************************************************/ +typedef struct JsonEachCursor JsonEachCursor; +struct JsonEachCursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + u32 iRowid; /* The rowid */ + u32 iBegin; /* The first node of the scan */ + u32 i; /* Index in sParse.aNode[] of current row */ + u32 iEnd; /* EOF when i equals or exceeds this value */ + u8 eType; /* Type of top-level element */ + u8 bRecursive; /* True for json_tree(). False for json_each() */ + char *zJson; /* Input JSON */ + char *zRoot; /* Path by which to filter zJson */ + JsonParse sParse; /* Parse of the input JSON */ +}; + +/* Constructor for the json_each virtual table */ +static int jsonEachConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + sqlite3_vtab *pNew; + int rc; + +/* Column numbers */ +#define JEACH_KEY 0 +#define JEACH_VALUE 1 +#define JEACH_TYPE 2 +#define JEACH_ATOM 3 +#define JEACH_ID 4 +#define JEACH_PARENT 5 +#define JEACH_FULLKEY 6 +#define JEACH_PATH 7 +#define JEACH_JSON 8 +#define JEACH_ROOT 9 + + UNUSED_PARAM(pzErr); + UNUSED_PARAM(argv); + UNUSED_PARAM(argc); + UNUSED_PARAM(pAux); + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," + "json HIDDEN,root HIDDEN)"); + if( rc==SQLITE_OK ){ + pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + } + return rc; +} + +/* destructor for json_each virtual table */ +static int jsonEachDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* constructor for a JsonEachCursor object for json_each(). */ +static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + JsonEachCursor *pCur; + + UNUSED_PARAM(p); + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* constructor for a JsonEachCursor object for json_tree(). */ +static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + int rc = jsonEachOpenEach(p, ppCursor); + if( rc==SQLITE_OK ){ + JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor; + pCur->bRecursive = 1; + } + return rc; +} + +/* Reset a JsonEachCursor back to its original state. Free any memory +** held. */ +static void jsonEachCursorReset(JsonEachCursor *p){ + sqlite3_free(p->zJson); + sqlite3_free(p->zRoot); + jsonParseReset(&p->sParse); + p->iRowid = 0; + p->i = 0; + p->iEnd = 0; + p->eType = 0; + p->zJson = 0; + p->zRoot = 0; +} + +/* Destructor for a jsonEachCursor object */ +static int jsonEachClose(sqlite3_vtab_cursor *cur){ + JsonEachCursor *p = (JsonEachCursor*)cur; + jsonEachCursorReset(p); + sqlite3_free(cur); + return SQLITE_OK; +} + +/* Return TRUE if the jsonEachCursor object has been advanced off the end +** of the JSON object */ +static int jsonEachEof(sqlite3_vtab_cursor *cur){ + JsonEachCursor *p = (JsonEachCursor*)cur; + return p->i >= p->iEnd; +} + +/* Advance the cursor to the next element for json_tree() */ +static int jsonEachNext(sqlite3_vtab_cursor *cur){ + JsonEachCursor *p = (JsonEachCursor*)cur; + if( p->bRecursive ){ + if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++; + p->i++; + p->iRowid++; + if( p->iiEnd ){ + u32 iUp = p->sParse.aUp[p->i]; + JsonNode *pUp = &p->sParse.aNode[iUp]; + p->eType = pUp->eType; + if( pUp->eType==JSON_ARRAY ){ + if( iUp==p->i-1 ){ + pUp->u.iKey = 0; + }else{ + pUp->u.iKey++; + } + } + } + }else{ + switch( p->eType ){ + case JSON_ARRAY: { + p->i += jsonNodeSize(&p->sParse.aNode[p->i]); + p->iRowid++; + break; + } + case JSON_OBJECT: { + p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]); + p->iRowid++; + break; + } + default: { + p->i = p->iEnd; + break; + } + } + } + return SQLITE_OK; +} + +/* Append the name of the path for element i to pStr +*/ +static void jsonEachComputePath( + JsonEachCursor *p, /* The cursor */ + JsonString *pStr, /* Write the path here */ + u32 i /* Path to this element */ +){ + JsonNode *pNode, *pUp; + u32 iUp; + if( i==0 ){ + jsonAppendChar(pStr, '$'); + return; + } + iUp = p->sParse.aUp[i]; + jsonEachComputePath(p, pStr, iUp); + pNode = &p->sParse.aNode[i]; + pUp = &p->sParse.aNode[iUp]; + if( pUp->eType==JSON_ARRAY ){ + jsonPrintf(30, pStr, "[%d]", pUp->u.iKey); + }else{ + assert( pUp->eType==JSON_OBJECT ); + if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--; + assert( pNode->eType==JSON_STRING ); + assert( pNode->jnFlags & JNODE_LABEL ); + jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); + } +} + +/* Return the value of a column */ +static int jsonEachColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + JsonEachCursor *p = (JsonEachCursor*)cur; + JsonNode *pThis = &p->sParse.aNode[p->i]; + switch( i ){ + case JEACH_KEY: { + if( p->i==0 ) break; + if( p->eType==JSON_OBJECT ){ + jsonReturn(pThis, ctx, 0); + }else if( p->eType==JSON_ARRAY ){ + u32 iKey; + if( p->bRecursive ){ + if( p->iRowid==0 ) break; + iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey; + }else{ + iKey = p->iRowid; + } + sqlite3_result_int64(ctx, (sqlite3_int64)iKey); + } + break; + } + case JEACH_VALUE: { + if( pThis->jnFlags & JNODE_LABEL ) pThis++; + jsonReturn(pThis, ctx, 0); + break; + } + case JEACH_TYPE: { + if( pThis->jnFlags & JNODE_LABEL ) pThis++; + sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC); + break; + } + case JEACH_ATOM: { + if( pThis->jnFlags & JNODE_LABEL ) pThis++; + if( pThis->eType>=JSON_ARRAY ) break; + jsonReturn(pThis, ctx, 0); + break; + } + case JEACH_ID: { + sqlite3_result_int64(ctx, + (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0)); + break; + } + case JEACH_PARENT: { + if( p->i>p->iBegin && p->bRecursive ){ + sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]); + } + break; + } + case JEACH_FULLKEY: { + JsonString x; + jsonInit(&x, ctx); + if( p->bRecursive ){ + jsonEachComputePath(p, &x, p->i); + }else{ + if( p->zRoot ){ + jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); + }else{ + jsonAppendChar(&x, '$'); + } + if( p->eType==JSON_ARRAY ){ + jsonPrintf(30, &x, "[%d]", p->iRowid); + }else{ + jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); + } + } + jsonResult(&x); + break; + } + case JEACH_PATH: { + if( p->bRecursive ){ + JsonString x; + jsonInit(&x, ctx); + jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); + jsonResult(&x); + break; + } + /* For json_each() path and root are the same so fall through + ** into the root case */ + } + case JEACH_ROOT: { + const char *zRoot = p->zRoot; + if( zRoot==0 ) zRoot = "$"; + sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); + break; + } + case JEACH_JSON: { + assert( i==JEACH_JSON ); + sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC); + break; + } + } + return SQLITE_OK; +} + +/* Return the current rowid value */ +static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + JsonEachCursor *p = (JsonEachCursor*)cur; + *pRowid = p->iRowid; + return SQLITE_OK; +} + +/* The query strategy is to look for an equality constraint on the json +** column. Without such a constraint, the table cannot operate. idxNum is +** 1 if the constraint is found, 3 if the constraint and zRoot are found, +** and 0 otherwise. +*/ +static int jsonEachBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int i; + int jsonIdx = -1; + int rootIdx = -1; + const struct sqlite3_index_constraint *pConstraint; + + UNUSED_PARAM(tab); + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + if( pConstraint->usable==0 ) continue; + if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; + switch( pConstraint->iColumn ){ + case JEACH_JSON: jsonIdx = i; break; + case JEACH_ROOT: rootIdx = i; break; + default: /* no-op */ break; + } + } + if( jsonIdx<0 ){ + pIdxInfo->idxNum = 0; + pIdxInfo->estimatedCost = 1e99; + }else{ + pIdxInfo->estimatedCost = 1.0; + pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1; + pIdxInfo->aConstraintUsage[jsonIdx].omit = 1; + if( rootIdx<0 ){ + pIdxInfo->idxNum = 1; + }else{ + pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2; + pIdxInfo->aConstraintUsage[rootIdx].omit = 1; + pIdxInfo->idxNum = 3; + } + } + return SQLITE_OK; +} + +/* Start a search on a new JSON string */ +static int jsonEachFilter( + sqlite3_vtab_cursor *cur, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + JsonEachCursor *p = (JsonEachCursor*)cur; + const char *z; + const char *zRoot = 0; + sqlite3_int64 n; + + UNUSED_PARAM(idxStr); + UNUSED_PARAM(argc); + jsonEachCursorReset(p); + if( idxNum==0 ) return SQLITE_OK; + z = (const char*)sqlite3_value_text(argv[0]); + if( z==0 ) return SQLITE_OK; + n = sqlite3_value_bytes(argv[0]); + p->zJson = sqlite3_malloc64( n+1 ); + if( p->zJson==0 ) return SQLITE_NOMEM; + memcpy(p->zJson, z, (size_t)n+1); + if( jsonParse(&p->sParse, 0, p->zJson) ){ + int rc = SQLITE_NOMEM; + if( p->sParse.oom==0 ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); + if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; + } + jsonEachCursorReset(p); + return rc; + }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){ + jsonEachCursorReset(p); + return SQLITE_NOMEM; + }else{ + JsonNode *pNode = 0; + if( idxNum==3 ){ + const char *zErr = 0; + zRoot = (const char*)sqlite3_value_text(argv[1]); + if( zRoot==0 ) return SQLITE_OK; + n = sqlite3_value_bytes(argv[1]); + p->zRoot = sqlite3_malloc64( n+1 ); + if( p->zRoot==0 ) return SQLITE_NOMEM; + memcpy(p->zRoot, zRoot, (size_t)n+1); + if( zRoot[0]!='$' ){ + zErr = zRoot; + }else{ + pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); + } + if( zErr ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr); + jsonEachCursorReset(p); + return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; + }else if( pNode==0 ){ + return SQLITE_OK; + } + }else{ + pNode = p->sParse.aNode; + } + p->iBegin = p->i = (int)(pNode - p->sParse.aNode); + p->eType = pNode->eType; + if( p->eType>=JSON_ARRAY ){ + pNode->u.iKey = 0; + p->iEnd = p->i + pNode->n + 1; + if( p->bRecursive ){ + p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType; + if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){ + p->i--; + } + }else{ + p->i++; + } + }else{ + p->iEnd = p->i+1; + } + } + return SQLITE_OK; +} + +/* The methods of the json_each virtual table */ +static sqlite3_module jsonEachModule = { + 0, /* iVersion */ + 0, /* xCreate */ + jsonEachConnect, /* xConnect */ + jsonEachBestIndex, /* xBestIndex */ + jsonEachDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + jsonEachOpenEach, /* xOpen - open a cursor */ + jsonEachClose, /* xClose - close a cursor */ + jsonEachFilter, /* xFilter - configure scan constraints */ + jsonEachNext, /* xNext - advance a cursor */ + jsonEachEof, /* xEof - check for end of scan */ + jsonEachColumn, /* xColumn - read data */ + jsonEachRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0 /* xRollbackTo */ +}; + +/* The methods of the json_tree virtual table. */ +static sqlite3_module jsonTreeModule = { + 0, /* iVersion */ + 0, /* xCreate */ + jsonEachConnect, /* xConnect */ + jsonEachBestIndex, /* xBestIndex */ + jsonEachDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + jsonEachOpenTree, /* xOpen - open a cursor */ + jsonEachClose, /* xClose - close a cursor */ + jsonEachFilter, /* xFilter - configure scan constraints */ + jsonEachNext, /* xNext - advance a cursor */ + jsonEachEof, /* xEof - check for end of scan */ + jsonEachColumn, /* xColumn - read data */ + jsonEachRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0 /* xRollbackTo */ +}; +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/**************************************************************************** +** The following routines are the only publically visible identifiers in this +** file. Call the following routines in order to register the various SQL +** functions and the virtual table implemented by this file. +****************************************************************************/ + +int sqlite3Json1Init(sqlite3 *db){ + int rc = SQLITE_OK; + unsigned int i; + static const struct { + const char *zName; + int nArg; + int flag; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFunc[] = { + { "json", 1, 0, jsonRemoveFunc }, + { "json_array", -1, 0, jsonArrayFunc }, + { "json_array_length", 1, 0, jsonArrayLengthFunc }, + { "json_array_length", 2, 0, jsonArrayLengthFunc }, + { "json_extract", -1, 0, jsonExtractFunc }, + { "json_insert", -1, 0, jsonSetFunc }, + { "json_object", -1, 0, jsonObjectFunc }, + { "json_remove", -1, 0, jsonRemoveFunc }, + { "json_replace", -1, 0, jsonReplaceFunc }, + { "json_set", -1, 1, jsonSetFunc }, + { "json_type", 1, 0, jsonTypeFunc }, + { "json_type", 2, 0, jsonTypeFunc }, + { "json_valid", 1, 0, jsonValidFunc }, + +#if SQLITE_DEBUG + /* DEBUG and TESTING functions */ + { "json_parse", 1, 0, jsonParseFunc }, + { "json_test1", 1, 0, jsonTest1Func }, +#endif + }; + static const struct { + const char *zName; + int nArg; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinal)(sqlite3_context*); + } aAgg[] = { + { "json_group_array", 1, jsonArrayStep, jsonArrayFinal }, + { "json_group_object", 2, jsonObjectStep, jsonObjectFinal }, + }; +#ifndef SQLITE_OMIT_VIRTUALTABLE + static const struct { + const char *zName; + sqlite3_module *pModule; + } aMod[] = { + { "json_each", &jsonEachModule }, + { "json_tree", &jsonTreeModule }, + }; +#endif + for(i=0; i